mirror of
https://github.com/ganelson/inform.git
synced 2024-07-08 18:14:21 +03:00
1005 lines
106 KiB
HTML
1005 lines
106 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
|
<html>
|
|
<head>
|
|
<title>25/cp</title>
|
|
<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>
|
|
|
|
<!--Weave of '26/vm' generated by 7-->
|
|
<ul class="crumbs"><li><a href="../webs.html">★</a></li><li><a href="index.html">core</a></li><li><a href="index.html#26">Chapter 26: Compilation Utilities</a></li><li><b>Virtual Machines</b></li></ul><p class="purpose">I7 supports a variety of virtual machines as targets. Most source text should be independent of the target VM, but sometimes numbering is needed, and this is where any VM dependencies are decided.</p>
|
|
|
|
<ul class="toc"><li><a href="#SP1">§1. Definitions</a></li><li><a href="#SP5">§5. Table of supported VMs</a></li><li><a href="#SP14">§14. Parsing VM restrictions</a></li><li><a href="#SP17">§17. Icons for virtual machines</a></li><li><a href="#SP18">§18. Describing the current VM</a></li><li><a href="#SP20">§20. Displaying VM restrictions</a></li><li><a href="#SP24">§24. Resource ID numbers</a></li></ul><hr class="tocbar">
|
|
|
|
<p class="inwebparagraph"><a id="SP1"></a><b>§1. Definitions. </b></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP2"></a><b>§2. </b>We use the term "major VM" to mean one of the families we deal with:
|
|
the Z-machine, for instance, is a major VM. A "minor VM" is a specific
|
|
revision of this, such as version 5 of the Z-machine. The following table
|
|
describes both major and minor VMs: records with version set to -1 are
|
|
major, and the rest minor.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">It is assumed that major VM names are single words: happily Z-machine has
|
|
always traditionally been hyphenated. We also assume their names use only
|
|
the plainest ASCII characters.
|
|
</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP3"></a><b>§3. </b>We store data on both major and minor VMs in the following simple structure.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The point of multiplying version numbers by 10,000 is to allow room for
|
|
sub-versions in future: Glulx in particular has version numbers like 3.4.2,
|
|
which we might want to represent as 30402. (At present we don't distinguish
|
|
versions of Glulx because Glulx's gestalt mechanism means that it's much
|
|
easier to construct story files which can cope nicely on different Glulx
|
|
interpreter versions than would be the case for the Z-machine.) Given that
|
|
the multiplier is larger than 1, it is impossible for -1 to be a valid
|
|
version number of any VM, so this is used as a "not a version number" value.
|
|
</p>
|
|
|
|
|
|
<pre class="definitions">
|
|
<span class="definitionkeyword">define</span> <span class="constant">VMULT</span><span class="plain"> 10000</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">VM_identifier</span><span class="plain"> {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">VM_code</span><span class="plain">; </span> <span class="comment">one of the values above</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">VM_version</span><span class="plain">; </span> <span class="comment">times the <code class="display"><span class="extract">VMULT</span></code>, or -1 to mean generic versionless VM</span>
|
|
<span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">VM_major_name</span><span class="plain">; </span> <span class="comment">or NULL if not a major VM name</span>
|
|
<span class="reserved">char</span><span class="plain"> *</span><span class="identifier">VM_extension</span><span class="plain">; </span> <span class="comment">canonical filename extension</span>
|
|
<span class="reserved">char</span><span class="plain"> *</span><span class="identifier">VM_blorbed_extension</span><span class="plain">; </span> <span class="comment">when blorbed up</span>
|
|
<span class="reserved">char</span><span class="plain"> *</span><span class="identifier">VM_name</span><span class="plain">; </span> <span class="comment">text to use with author</span>
|
|
<span class="reserved">char</span><span class="plain"> *</span><span class="identifier">VM_image</span><span class="plain">; </span> <span class="comment">filename of image for icon denoting VM</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">VM_is_32_bit</span><span class="plain">; </span> <span class="comment">true or false: false means 16-bit</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">max_locals</span><span class="plain">; </span> <span class="comment">upper limit on local variables per stack frame</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">VM_matches</span><span class="plain">; </span> <span class="comment">true or false: computed</span>
|
|
<span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">default_browser_interpreter</span><span class="plain">; </span> <span class="comment">e.g., "Parchment"</span>
|
|
<span class="plain">} </span><span class="reserved">VM_identifier</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The structure VM_identifier is private to this section.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP4"></a><b>§4. </b>We keep track of how array space is used in the VM, since this is in very
|
|
short supply in the Z-machine. This is done purely so that we can index
|
|
helpfully on the Contents index page.
|
|
</p>
|
|
|
|
|
|
<pre class="definitions">
|
|
<span class="definitionkeyword">define</span> <span class="constant">MAX_USAGE_COLUMN_WIDTH</span><span class="plain"> 200</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">VM_usage_note</span><span class="plain"> {</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">structure_name</span><span class="plain">; </span> <span class="comment">name of the structure using this array space...</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">usage_explained</span><span class="plain">; </span> <span class="comment">...or an explanation instead</span>
|
|
<span class="reserved">char</span><span class="plain"> *</span><span class="identifier">usage_category</span><span class="plain">; </span> <span class="comment">e.g., "relation"</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">bytes_used</span><span class="plain">; </span> <span class="comment">number of bytes (not words) given over to this</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">each_flag</span><span class="plain">; </span> <span class="comment">is this a count of how many bytes per usage of something?</span>
|
|
<span class="identifier">MEMORY_MANAGEMENT</span>
|
|
<span class="plain">} </span><span class="reserved">VM_usage_note</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The structure VM_usage_note is private to this section.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP5"></a><b>§5. Table of supported VMs. </b>The following data determines what VMs we know about, and how they can
|
|
be inferred from the present information passed by the GUI to us at the
|
|
command line - viz., the eventual file extension. The application passes
|
|
this by including among the command-line switches a pair like so:
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">-extension ulx</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph">The second word must be one of the file extensions listed in the fourth
|
|
column of the table of VM data below: the comparison is made case
|
|
insensitively, and any initial full stop is skipped, so ".Z6" is
|
|
equivalent to "z6".
|
|
</p>
|
|
|
|
|
|
<pre class="definitions">
|
|
<span class="definitionkeyword">define</span> <span class="constant">Z_VM</span><span class="plain"> 1 </span> <span class="comment">Joel Berez and Marc Blank, 1979, and later hands</span>
|
|
<span class="definitionkeyword">define</span> <span class="constant">GLULX_VM</span><span class="plain"> 2 </span> <span class="comment">Andrew Plotkin, 2000</span>
|
|
<span class="definitionkeyword">define</span> <span class="constant">DEFAULT_TARGET_VM</span><span class="plain"> 3 </span> <span class="comment">if no -extension is supplied, target row 3: Z-machine v8</span>
|
|
</pre>
|
|
|
|
<pre class="display">
|
|
<span class="reserved">VM_identifier</span><span class="plain"> </span><span class="identifier">table_of_VM_data</span><span class="plain">[] = {</span>
|
|
<span class="plain">{ </span><span class="constant">Z_VM</span><span class="plain">, -1, </span><span class="identifier">L</span><span class="string">"z-machine"</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="string">"zblorb"</span><span class="plain">, </span><span class="string">"Z-Machine"</span><span class="plain">, </span><span class="string">"vm_z.png"</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">, 15, </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"Parchment"</span><span class="plain"> },</span>
|
|
<span class="plain">{ </span><span class="constant">Z_VM</span><span class="plain">, 5*</span><span class="constant">VMULT</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="string">"z5"</span><span class="plain">, </span><span class="string">"zblorb"</span><span class="plain">, </span><span class="string">"Z-Machine version 5"</span><span class="plain">, </span><span class="string">"vm_z5.png"</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">, 15, </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"Parchment"</span><span class="plain"> },</span>
|
|
<span class="plain">{ </span><span class="constant">Z_VM</span><span class="plain">, 6*</span><span class="constant">VMULT</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="string">"z6"</span><span class="plain">, </span><span class="string">"zblorb"</span><span class="plain">, </span><span class="string">"Z-Machine version 6"</span><span class="plain">, </span><span class="string">"vm_z6.png"</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">, 15, </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"Parchment"</span><span class="plain"> },</span>
|
|
<span class="plain">{ </span><span class="constant">Z_VM</span><span class="plain">, 8*</span><span class="constant">VMULT</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="string">"z8"</span><span class="plain">, </span><span class="string">"zblorb"</span><span class="plain">, </span><span class="string">"Z-Machine version 8"</span><span class="plain">, </span><span class="string">"vm_z8.png"</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">, 15, </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"Parchment"</span><span class="plain"> },</span>
|
|
<span class="plain">{ </span><span class="constant">GLULX_VM</span><span class="plain">, -1, </span><span class="identifier">L</span><span class="string">"glulx"</span><span class="plain">, </span><span class="string">"ulx"</span><span class="plain">, </span><span class="string">"gblorb"</span><span class="plain">, </span><span class="string">"Glulx"</span><span class="plain">, </span><span class="string">"vm_glulx.png"</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">, 256, </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"Quixe"</span><span class="plain"> },</span>
|
|
<span class="plain">{ -1, 0, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">, 15, </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"Parchment"</span><span class="plain"> }</span>
|
|
<span class="plain">};</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP6"></a><b>§6. </b>At present, we infer the target virtual machine by looking at the file
|
|
extension requested at the command line.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">target_VM</span><span class="plain">; </span> <span class="comment">an index in the above table, or -1 if unknown</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">VirtualMachines::set_identifier</span><span class="plain">(</span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">text</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">text</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) { </span><span class="identifier">target_VM</span><span class="plain"> = </span><span class="constant">DEFAULT_TARGET_VM</span><span class="plain">; </span><span class="reserved">return</span><span class="plain">; }</span>
|
|
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">file_extension</span><span class="plain">);</span>
|
|
<span class="identifier">Str::copy</span><span class="plain">(</span><span class="identifier">file_extension</span><span class="plain">, </span><span class="identifier">text</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::get_first_char</span><span class="plain">(</span><span class="identifier">file_extension</span><span class="plain">) == </span><span class="character">'.'</span><span class="plain">) </span><span class="identifier">Str::delete_first_character</span><span class="plain">(</span><span class="identifier">file_extension</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">file_extension</span><span class="plain">)</span>
|
|
<span class="identifier">Str::put</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">, </span><span class="identifier">Characters::tolower</span><span class="plain">(</span><span class="identifier">Str::get</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">)));</span>
|
|
<span class="identifier">target_VM</span><span class="plain"> = -1;</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">table_of_VM_data</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.VM_code</span><span class="plain"> >= 0; </span><span class="identifier">i</span><span class="plain">++)</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">table_of_VM_data</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.VM_extension</span><span class="plain">) &&</span>
|
|
<span class="plain">(</span><span class="identifier">Str::eq_narrow_string</span><span class="plain">(</span><span class="identifier">file_extension</span><span class="plain">, </span><span class="identifier">table_of_VM_data</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.VM_extension</span><span class="plain">)))</span>
|
|
<span class="identifier">target_VM</span><span class="plain"> = </span><span class="identifier">i</span><span class="plain">;</span>
|
|
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">file_extension</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function VirtualMachines::set_identifier is used in 1/mr (<a href="1-mr.html#SP4_5">§4.5</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP7"></a><b>§7. </b>To help Inform detect overflows, it needs to know whether integers in the
|
|
target VM are 16 or 32 bits wide:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">VirtualMachines::is_16_bit</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">target_VM</span><span class="plain"> == -1) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"target VM not set yet"</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">table_of_VM_data</span><span class="plain">[</span><span class="identifier">target_VM</span><span class="plain">]</span><span class="element">.VM_is_32_bit</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function VirtualMachines::is_16_bit is used in <a href="#SP9">§9</a>, <a href="#SP19">§19</a>, <a href="#SP21">§21</a>, 1/mr (<a href="1-mr.html#SP4_15">§4.15</a>), 5/lp (<a href="5-lp.html#SP12_2">§12.2</a>, <a href="5-lp.html#SP18_3">§18.3</a>), 6/rlt (<a href="6-rlt.html#SP14">§14</a>), 13/rsfk (<a href="13-rsfk.html#SP18_1">§18.1</a>, <a href="13-rsfk.html#SP20">§20</a>), 25/cii (<a href="25-cii.html#SP3_5_8_3">§3.5.8.3</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8"></a><b>§8. </b>Fundamental constants are emitted about our choice of virtual machine.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The old I6 library used to confuse Z-vs-G with 16-vs-32-bit, but we try
|
|
to separate these distinctions here, even though at present the Z-machine
|
|
is our only 16-bit target and Glulx our only 32-bit one. The <code class="display"><span class="extract">WORDSIZE</span></code>
|
|
constant is the word size in bytes, so is the multiplier between <code class="display"><span class="extract">-></span></code> and
|
|
<code class="display"><span class="extract">--></span></code> offsets in I6 pointer syntax.
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<ul class="items"><li>(1) <code class="display"><span class="extract">NULL</span></code> is used, as in C, to represent a null value or pointer. In C,
|
|
this is conventionally 0, but here it is the maximum unsigned value which
|
|
can be stored, pointing to the topmost byte in the directly addressable
|
|
memory map; this means it is also -1 when regarded as a signed
|
|
twos-complement integer, but we write it as an unsigned hexadecimal
|
|
address for clarity's sake.
|
|
</li></ul>
|
|
<ul class="items"><li>(2) <code class="display"><span class="extract">WORD_HIGHBIT</span></code> is the most significant bit in the VM's data word.
|
|
</li></ul>
|
|
<ul class="items"><li>(3) <code class="display"><span class="extract">IMPROBABLE_VALUE</span></code> is one which is unlikely but still possible
|
|
to be a genuine I7 value. The efficiency of some algorithms depends on
|
|
how well chosen this is: they would ran badly if we chose 1, for instance.
|
|
</li></ul>
|
|
<ul class="items"><li>(4) <code class="display"><span class="extract">MAX_POSITIVE_NUMBER</span></code> is the largest representable positive (signed)
|
|
integer, in twos-complement form.
|
|
</li></ul>
|
|
<ul class="items"><li>(5) <code class="display"><span class="extract">REPARSE_CODE</span></code> is a magic value used in the I6 library's parser to
|
|
signal that some code which ought to have been parsing a command has in
|
|
fact rewritten it, so that the whole command must be re-parsed afresh.
|
|
(Returning this value is like throwing an exception in a language like
|
|
Java, though we don't implement it that way.) A comment in the 6/11 library
|
|
reads: "The parser rather gunkily adds addresses to <code class="display"><span class="extract">REPARSE_CODE</span></code> for
|
|
some purposes. And expects the result to be greater than <code class="display"><span class="extract">REPARSE_CODE</span></code>
|
|
(signed comparison). So Glulx Inform is limited to a single gigabyte of
|
|
storage, for the moment." Guilty as charged, but the gigabyte story file
|
|
is a remote prospect for now: even megabyte story files are off the
|
|
horizon. Anyway, it's this comparison issue which means we need a different
|
|
value for each possible word size.
|
|
</li></ul>
|
|
|
|
<pre class="display">
|
|
<span class="identifier">inter_name</span><span class="plain"> *</span><span class="functiontext">VirtualMachines::emit_fundamental_constant</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">id</span><span class="plain">, </span><span class="identifier">inter_t</span><span class="plain"> </span><span class="identifier">val</span><span class="plain">) {</span>
|
|
<span class="identifier">inter_name</span><span class="plain"> *</span><span class="identifier">iname</span><span class="plain"> = </span><span class="functiontext">Hierarchy::find</span><span class="plain">(</span><span class="identifier">id</span><span class="plain">);</span>
|
|
<span class="functiontext">Hierarchy::make_available</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">iname</span><span class="plain">);</span>
|
|
<span class="functiontext">Emit::named_numeric_constant</span><span class="plain">(</span><span class="identifier">iname</span><span class="plain">, </span><span class="identifier">val</span><span class="plain">);</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">iname</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="identifier">inter_name</span><span class="plain"> *</span><span class="functiontext">VirtualMachines::emit_signed_fundamental_constant</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">id</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">val</span><span class="plain">) {</span>
|
|
<span class="identifier">inter_name</span><span class="plain"> *</span><span class="identifier">iname</span><span class="plain"> = </span><span class="functiontext">Hierarchy::find</span><span class="plain">(</span><span class="identifier">id</span><span class="plain">);</span>
|
|
<span class="functiontext">Hierarchy::make_available</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">iname</span><span class="plain">);</span>
|
|
<span class="functiontext">Emit::named_numeric_constant_signed</span><span class="plain">(</span><span class="identifier">iname</span><span class="plain">, </span><span class="identifier">val</span><span class="plain">);</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">iname</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="identifier">inter_name</span><span class="plain"> *</span><span class="functiontext">VirtualMachines::emit_hex_fundamental_constant</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">id</span><span class="plain">, </span><span class="identifier">inter_t</span><span class="plain"> </span><span class="identifier">val</span><span class="plain">) {</span>
|
|
<span class="identifier">inter_name</span><span class="plain"> *</span><span class="identifier">iname</span><span class="plain"> = </span><span class="functiontext">Hierarchy::find</span><span class="plain">(</span><span class="identifier">id</span><span class="plain">);</span>
|
|
<span class="functiontext">Hierarchy::make_available</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">iname</span><span class="plain">);</span>
|
|
<span class="functiontext">Emit::named_numeric_constant_hex</span><span class="plain">(</span><span class="identifier">iname</span><span class="plain">, </span><span class="identifier">val</span><span class="plain">);</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">iname</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="identifier">inter_name</span><span class="plain"> *</span><span class="functiontext">VirtualMachines::emit_unchecked_hex_fundamental_constant</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">id</span><span class="plain">, </span><span class="identifier">inter_t</span><span class="plain"> </span><span class="identifier">val</span><span class="plain">) {</span>
|
|
<span class="identifier">inter_name</span><span class="plain"> *</span><span class="identifier">iname</span><span class="plain"> = </span><span class="functiontext">Hierarchy::find</span><span class="plain">(</span><span class="identifier">id</span><span class="plain">);</span>
|
|
<span class="functiontext">Hierarchy::make_available</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">iname</span><span class="plain">);</span>
|
|
<span class="functiontext">Emit::named_unchecked_constant_hex</span><span class="plain">(</span><span class="identifier">iname</span><span class="plain">, </span><span class="identifier">val</span><span class="plain">);</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">iname</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">VirtualMachines::emit_fundamental_constants</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">target_VM</span><span class="plain"> == -1) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"target VM not set yet"</span><span class="plain">);</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">this_is_a_release_compile</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) || (</span><span class="identifier">this_is_a_debug_compile</span><span class="plain">))</span>
|
|
<span class="functiontext">VirtualMachines::emit_fundamental_constant</span><span class="plain">(</span><span class="constant">DEBUG_HL</span><span class="plain">, 1);</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">table_of_VM_data</span><span class="plain">[</span><span class="identifier">target_VM</span><span class="plain">]</span><span class="element">.VM_code</span><span class="plain"> == </span><span class="constant">Z_VM</span><span class="plain">) {</span>
|
|
<span class="functiontext">VirtualMachines::emit_fundamental_constant</span><span class="plain">(</span><span class="constant">TARGET_ZCODE_HL</span><span class="plain">, 1);</span>
|
|
<span class="functiontext">VirtualMachines::emit_fundamental_constant</span><span class="plain">(</span><span class="constant">DICT_WORD_SIZE_HL</span><span class="plain">, 6);</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">table_of_VM_data</span><span class="plain">[</span><span class="identifier">target_VM</span><span class="plain">]</span><span class="element">.VM_code</span><span class="plain"> == </span><span class="constant">GLULX_VM</span><span class="plain">) {</span>
|
|
<span class="functiontext">VirtualMachines::emit_fundamental_constant</span><span class="plain">(</span><span class="constant">TARGET_GLULX_HL</span><span class="plain">, 1);</span>
|
|
<span class="functiontext">VirtualMachines::emit_fundamental_constant</span><span class="plain">(</span><span class="constant">DICT_WORD_SIZE_HL</span><span class="plain">, 9);</span>
|
|
<span class="functiontext">VirtualMachines::emit_fundamental_constant</span><span class="plain">(</span><span class="constant">INDIV_PROP_START_HL</span><span class="plain">, 0);</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">table_of_VM_data</span><span class="plain">[</span><span class="identifier">target_VM</span><span class="plain">]</span><span class="element">.VM_is_32_bit</span><span class="plain">) {</span>
|
|
<span class="functiontext">VirtualMachines::emit_fundamental_constant</span><span class="plain">(</span><span class="constant">WORDSIZE_HL</span><span class="plain">, 4);</span>
|
|
<span class="functiontext">VirtualMachines::emit_unchecked_hex_fundamental_constant</span><span class="plain">(</span><span class="constant">NULL_HL</span><span class="plain">, 0</span><span class="identifier">xffffffff</span><span class="plain">);</span>
|
|
<span class="functiontext">VirtualMachines::emit_hex_fundamental_constant</span><span class="plain">(</span><span class="constant">WORD_HIGHBIT_HL</span><span class="plain">, 0</span><span class="identifier">x80000000</span><span class="plain">);</span>
|
|
<span class="functiontext">VirtualMachines::emit_hex_fundamental_constant</span><span class="plain">(</span><span class="constant">WORD_NEXTTOHIGHBIT_HL</span><span class="plain">, 0</span><span class="identifier">x40000000</span><span class="plain">);</span>
|
|
<span class="functiontext">VirtualMachines::emit_hex_fundamental_constant</span><span class="plain">(</span><span class="constant">IMPROBABLE_VALUE_HL</span><span class="plain">, 0</span><span class="identifier">xdeadce11</span><span class="plain">);</span>
|
|
<span class="functiontext">VirtualMachines::emit_hex_fundamental_constant</span><span class="plain">(</span><span class="constant">REPARSE_CODE_HL</span><span class="plain">, 0</span><span class="identifier">x40000000</span><span class="plain">);</span>
|
|
<span class="functiontext">VirtualMachines::emit_fundamental_constant</span><span class="plain">(</span><span class="constant">MAX_POSITIVE_NUMBER_HL</span><span class="plain">, 2147483647);</span>
|
|
<span class="functiontext">VirtualMachines::emit_signed_fundamental_constant</span><span class="plain">(</span><span class="constant">MIN_NEGATIVE_NUMBER_HL</span><span class="plain">, -2147483648);</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
|
|
<span class="functiontext">VirtualMachines::emit_fundamental_constant</span><span class="plain">(</span><span class="constant">WORDSIZE_HL</span><span class="plain">, 2);</span>
|
|
<span class="functiontext">VirtualMachines::emit_unchecked_hex_fundamental_constant</span><span class="plain">(</span><span class="constant">NULL_HL</span><span class="plain">, 0</span><span class="identifier">xffff</span><span class="plain">);</span>
|
|
<span class="functiontext">VirtualMachines::emit_hex_fundamental_constant</span><span class="plain">(</span><span class="constant">WORD_HIGHBIT_HL</span><span class="plain">, 0</span><span class="identifier">x8000</span><span class="plain">);</span>
|
|
<span class="functiontext">VirtualMachines::emit_hex_fundamental_constant</span><span class="plain">(</span><span class="constant">WORD_NEXTTOHIGHBIT_HL</span><span class="plain">, 0</span><span class="identifier">x4000</span><span class="plain">);</span>
|
|
<span class="functiontext">VirtualMachines::emit_hex_fundamental_constant</span><span class="plain">(</span><span class="constant">IMPROBABLE_VALUE_HL</span><span class="plain">, 0</span><span class="identifier">x7fe3</span><span class="plain">);</span>
|
|
<span class="functiontext">VirtualMachines::emit_hex_fundamental_constant</span><span class="plain">(</span><span class="constant">REPARSE_CODE_HL</span><span class="plain">, 10000);</span>
|
|
<span class="functiontext">VirtualMachines::emit_fundamental_constant</span><span class="plain">(</span><span class="constant">MAX_POSITIVE_NUMBER_HL</span><span class="plain">, 32767);</span>
|
|
<span class="functiontext">VirtualMachines::emit_signed_fundamental_constant</span><span class="plain">(</span><span class="constant">MIN_NEGATIVE_NUMBER_HL</span><span class="plain">, -32768);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function VirtualMachines::emit_fundamental_constant appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function VirtualMachines::emit_signed_fundamental_constant appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function VirtualMachines::emit_hex_fundamental_constant appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function VirtualMachines::emit_unchecked_hex_fundamental_constant appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function VirtualMachines::emit_fundamental_constants is used in 27/ei (<a href="27-ei.html#SP2">§2</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP9"></a><b>§9. </b>Using which:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">VirtualMachines::veto_number</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">X</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (((</span><span class="identifier">X</span><span class="plain"> > 32767) || (</span><span class="identifier">X</span><span class="plain"> < -32768)) && (</span><span class="functiontext">VirtualMachines::is_16_bit</span><span class="plain">())) {</span>
|
|
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_LiteralOverflow</span><span class="plain">),</span>
|
|
<span class="string">"you use a number which is too large"</span><span class="plain">,</span>
|
|
<span class="string">"at least with the Settings for this project as they currently "</span>
|
|
<span class="string">"are. (Change to Glulx to be allowed to use much larger numbers.)"</span><span class="plain">);</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function VirtualMachines::veto_number appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP10"></a><b>§10. </b>The limits are different on each platform. On Z, the maximum is fixed
|
|
at 15, but Glulx allows it to be set with an I6 memory setting.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">VirtualMachines::allow_this_many_locals</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">target_VM</span><span class="plain"> == -1) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"target VM not set yet"</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">table_of_VM_data</span><span class="plain">[</span><span class="identifier">target_VM</span><span class="plain">]</span><span class="element">.max_locals</span><span class="plain"> >= 0) &&</span>
|
|
<span class="plain">(</span><span class="identifier">table_of_VM_data</span><span class="plain">[</span><span class="identifier">target_VM</span><span class="plain">]</span><span class="element">.max_locals</span><span class="plain"> < </span><span class="identifier">N</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">VirtualMachines::allow_MAX_LOCAL_VARIABLES</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">target_VM</span><span class="plain"> == -1) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"target VM not set yet"</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">table_of_VM_data</span><span class="plain">[</span><span class="identifier">target_VM</span><span class="plain">]</span><span class="element">.max_locals</span><span class="plain"> > 15) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function VirtualMachines::allow_this_many_locals is used in 26/rt (<a href="26-rt.html#SP4">§4</a>).</p>
|
|
|
|
<p class="endnote">The function VirtualMachines::allow_MAX_LOCAL_VARIABLES is used in 26/uo (<a href="26-uo.html#SP18">§18</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11"></a><b>§11. </b>Real numbers are also a concern:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">VirtualMachines::supports</span><span class="plain">(</span><span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">target_VM</span><span class="plain"> == -1) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"target VM not set yet"</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">Kinds::FloatingPoint::uses_floating_point</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">)) &&</span>
|
|
<span class="plain">(</span><span class="identifier">table_of_VM_data</span><span class="plain">[</span><span class="identifier">target_VM</span><span class="plain">]</span><span class="element">.VM_is_32_bit</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function VirtualMachines::supports is used in 13/rsfk (<a href="13-rsfk.html#SP26">§26</a>), 20/eq (<a href="20-eq.html#SP41">§41</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP12"></a><b>§12. </b>When releasing a blorbed story file, the file extension depends on the
|
|
story file wrapped inside. (This is a dubious idea, in the opinion of
|
|
the author of Inform — should not blorb be one unified wrapper? — but
|
|
interpreter writers disagree.)
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">char</span><span class="plain"> *</span><span class="functiontext">VirtualMachines::get_blorbed_extension</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">target_VM</span><span class="plain"> == -1) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"target VM not set yet"</span><span class="plain">);</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">table_of_VM_data</span><span class="plain">[</span><span class="identifier">target_VM</span><span class="plain">]</span><span class="element">.VM_blorbed_extension</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function VirtualMachines::get_blorbed_extension appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP13"></a><b>§13. </b>Different VMs have different in-browser interpreters, which means that
|
|
Inblorb needs to be given different release instructions for them. If the
|
|
user doesn't specify any particular interpreter, he gets:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="identifier">wchar_t</span><span class="plain"> *</span><span class="functiontext">VirtualMachines::get_default_interpreter</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">target_VM</span><span class="plain"> == -1) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"target VM not set yet"</span><span class="plain">);</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">table_of_VM_data</span><span class="plain">[</span><span class="identifier">target_VM</span><span class="plain">]</span><span class="element">.default_browser_interpreter</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function VirtualMachines::get_default_interpreter appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP14"></a><b>§14. Parsing VM restrictions. </b>Given a word range, we see what set of virtual machines it specifies. For example,
|
|
the result of calling
|
|
</p>
|
|
|
|
<blockquote>
|
|
<p>for Z-machine version 5 or 8 only</p>
|
|
|
|
</blockquote>
|
|
|
|
<p class="inwebparagraph">is that the <code class="display"><span class="extract">VM_matches</span></code> field in the table above is set for the two minor VMs
|
|
cited, and cleared for all of the others, while the <code class="display"><span class="extract">VM_matching_error_thrown</span></code>
|
|
is false (since the text was valid). The same result is produced by
|
|
</p>
|
|
|
|
<blockquote>
|
|
<p>for Z-machine versions 5 and 8 only</p>
|
|
|
|
</blockquote>
|
|
|
|
<p class="inwebparagraph">English being quirky that way.
|
|
</p>
|
|
|
|
|
|
<pre class="definitions">
|
|
<span class="definitionkeyword">define</span> <span class="constant">THROW_VM_MATCHING_ERROR_AND_RETURN</span><span class="plain"> { </span><span class="identifier">VM_matching_error_thrown</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">; </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">; }</span>
|
|
</pre>
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">VM_matching_error_thrown</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">; </span> <span class="comment">an error occurred during parsing</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">most_recent_major_VM</span><span class="plain">; </span> <span class="comment">most recent major VM which matched, or -1</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">version_can_be_inferred</span><span class="plain">; </span> <span class="comment">from earlier in the word range parsed</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">VirtualMachines::match_against</span><span class="plain">(</span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain">) {</span>
|
|
<<span class="cwebmacro">Clean the slate ready for a fresh VM parse</span> <span class="cwebmacronumber">14.1</span>><span class="plain">;</span>
|
|
<span class="plain"><</span><span class="identifier">vm</span><span class="plain">-</span><span class="identifier">description</span><span class="plain">-</span><span class="identifier">list</span><span class="plain">>(</span><span class="identifier">W</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function VirtualMachines::match_against is used in <a href="#SP16">§16</a>, <a href="#SP20">§20</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP14_1"></a><b>§14.1. </b>It is slightly lazy of this code to use global variables to preserve state
|
|
through a sequence of function calls to <code class="display"><span class="extract">match_VM_from</span></code>, but sometimes a
|
|
little laziness is what we deserve.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Clean the slate ready for a fresh VM parse</span> <span class="cwebmacronumber">14.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
|
|
<span class="identifier">VM_matching_error_thrown</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="identifier">most_recent_major_VM</span><span class="plain"> = -1;</span>
|
|
<span class="identifier">version_can_be_inferred</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">table_of_VM_data</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.VM_code</span><span class="plain"> >= 0; </span><span class="identifier">i</span><span class="plain">++) </span><span class="identifier">table_of_VM_data</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.VM_matches</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP14">§14</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP15"></a><b>§15. </b>Not much grammar is used to parse virtual machine identifications like:
|
|
</p>
|
|
|
|
<blockquote>
|
|
<p>Z-machine versions 5 and 8</p>
|
|
|
|
</blockquote>
|
|
|
|
<p class="inwebparagraph">The words "Z-machine" and "Glulx" are hard-wired so that they can't be
|
|
altered using Preform. (The Spanish for "Glulx", say, is "Glulx".) Preform
|
|
grammar is used first to split the list:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain"><</span><span class="identifier">vm</span><span class="plain">-</span><span class="identifier">description</span><span class="plain">-</span><span class="identifier">list</span><span class="plain">> ::=</span>
|
|
<span class="plain">... | ==> 0; </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">preform_lookahead_mode</span><span class="plain">; </span> <span class="comment">match only when looking ahead</span>
|
|
<span class="plain"><</span><span class="identifier">vm</span><span class="plain">-</span><span class="identifier">description</span><span class="plain">-</span><span class="identifier">entry</span><span class="plain">> <</span><span class="identifier">vm</span><span class="plain">-</span><span class="identifier">description</span><span class="plain">-</span><span class="identifier">tail</span><span class="plain">> | ==> 0</span>
|
|
<span class="plain"><</span><span class="identifier">vm</span><span class="plain">-</span><span class="identifier">description</span><span class="plain">-</span><span class="identifier">entry</span><span class="plain">> ==> 0</span>
|
|
|
|
<span class="plain"><</span><span class="identifier">vm</span><span class="plain">-</span><span class="identifier">description</span><span class="plain">-</span><span class="identifier">tail</span><span class="plain">> ::=</span>
|
|
<span class="plain">, </span><span class="identifier">_and</span><span class="plain">/</span><span class="identifier">or</span><span class="plain"> <</span><span class="identifier">vm</span><span class="plain">-</span><span class="identifier">description</span><span class="plain">-</span><span class="identifier">list</span><span class="plain">> |</span>
|
|
<span class="identifier">_</span><span class="plain">,/</span><span class="identifier">and</span><span class="plain">/</span><span class="identifier">or</span><span class="plain"> <</span><span class="identifier">vm</span><span class="plain">-</span><span class="identifier">description</span><span class="plain">-</span><span class="identifier">list</span><span class="plain">></span>
|
|
|
|
<span class="plain"><</span><span class="identifier">vm</span><span class="plain">-</span><span class="identifier">description</span><span class="plain">-</span><span class="identifier">entry</span><span class="plain">> ::=</span>
|
|
<span class="plain">... ==> </span><<span class="cwebmacro">Parse latest term in word range list</span> <span class="cwebmacronumber">15.2</span>>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP15_1"></a><b>§15.1. </b>Preform doesn't parse the VM names themselves, but it does pick up the
|
|
optional part about version numbering:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain"><</span><span class="identifier">version</span><span class="plain">-</span><span class="identifier">identification</span><span class="plain">> ::=</span>
|
|
<span class="identifier">version</span><span class="plain">/</span><span class="identifier">versions</span><span class="plain"> <</span><span class="identifier">cardinal</span><span class="plain">-</span><span class="identifier">number</span><span class="plain">> ==> </span><span class="identifier">R</span><span class="plain">[1]</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP15_2"></a><b>§15.2. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Parse latest term in word range list</span> <span class="cwebmacronumber">15.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<<span class="cwebmacro">Detect major VM name, if given, and advance one word</span> <span class="cwebmacronumber">15.2.1</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Give up if no major VM name found in any term of the list so far</span> <span class="cwebmacronumber">15.2.2</span>><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::nonempty</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">)) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">version_specified</span><span class="plain"> = -1;</span>
|
|
<span class="reserved">if</span><span class="plain"> (<</span><span class="identifier">version</span><span class="plain">-</span><span class="identifier">identification</span><span class="plain">>(</span><span class="identifier">W</span><span class="plain">)) {</span>
|
|
<span class="identifier">version_specified</span><span class="plain"> = </span><span class="constant">VMULT</span><span class="plain"> * <<</span><span class="identifier">r</span><span class="plain">>>;</span>
|
|
<span class="identifier">version_can_be_inferred</span><span class="plain"> = </span><span class="identifier">TRUE</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="identifier">version_can_be_inferred</span><span class="plain">) && (<</span><span class="identifier">cardinal</span><span class="plain">-</span><span class="identifier">number</span><span class="plain">>(</span><span class="identifier">W</span><span class="plain">))) {</span>
|
|
<span class="identifier">version_specified</span><span class="plain"> = </span><span class="constant">VMULT</span><span class="plain"> * <<</span><span class="identifier">r</span><span class="plain">>>;</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="constant">THROW_VM_MATCHING_ERROR_AND_RETURN</span><span class="plain">;</span>
|
|
<<span class="cwebmacro">Score a match for this specific version of the major VM, if we know about it</span> <span class="cwebmacronumber">15.2.4</span>><span class="plain">;</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
|
|
<<span class="cwebmacro">Score a match for every known version of the major VM</span> <span class="cwebmacronumber">15.2.3</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP15">§15</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP15_2_1"></a><b>§15.2.1. </b>The word "version" is sometimes implicit, but not after a major VM name.
|
|
Thus "Glulx 3" is not allowed: it has to be "Glulx version 3".
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Detect major VM name, if given, and advance one word</span> <span class="cwebmacronumber">15.2.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">table_of_VM_data</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.VM_code</span><span class="plain"> >= 0; </span><span class="identifier">i</span><span class="plain">++)</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">table_of_VM_data</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.VM_major_name</span><span class="plain">) &&</span>
|
|
<span class="plain">(</span><span class="identifier">Word::compare_by_strcmp</span><span class="plain">(</span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">), </span><span class="identifier">table_of_VM_data</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.VM_major_name</span><span class="plain">))) {</span>
|
|
<span class="identifier">most_recent_major_VM</span><span class="plain"> = </span><span class="identifier">table_of_VM_data</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.VM_code</span><span class="plain">;</span>
|
|
<span class="identifier">version_can_be_inferred</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="identifier">W</span><span class="plain"> = </span><span class="identifier">Wordings::trim_first_word</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">);</span>
|
|
<span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP15_2">§15.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP15_2_2"></a><b>§15.2.2. </b>The variable <code class="display"><span class="extract">VM_matching_error_thrown</span></code> may have been set either on
|
|
this term or a previous one: for instance, if we are reading "Squirrel
|
|
versions 4 and 7" then at the second term, "7", no major VM is named
|
|
but the variable remains set from "Squirrel" having been parsed at the
|
|
first term.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Give up if no major VM name found in any term of the list so far</span> <span class="cwebmacronumber">15.2.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">most_recent_major_VM</span><span class="plain"> == -1) </span><span class="constant">THROW_VM_MATCHING_ERROR_AND_RETURN</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP15_2">§15.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP15_2_3"></a><b>§15.2.3. </b>We either make a run of matches:
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Score a match for every known version of the major VM</span> <span class="cwebmacronumber">15.2.3</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<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">table_of_VM_data</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.VM_code</span><span class="plain"> >= 0; </span><span class="identifier">i</span><span class="plain">++)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">table_of_VM_data</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.VM_code</span><span class="plain"> == </span><span class="identifier">most_recent_major_VM</span><span class="plain">)</span>
|
|
<span class="identifier">table_of_VM_data</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.VM_matches</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP15_2">§15.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP15_2_4"></a><b>§15.2.4. </b>...or else we make a single match, or even none at all. This would not be
|
|
an error: if the request was for "version 71 of Chipmunk", and we were
|
|
unable to compile to this VM (so that no such minor VM record appeared in
|
|
the table) then the situation might be that we are reading the requirements
|
|
of some extension used by other people, who have a later version of Inform
|
|
than us, and which does compile to that VM.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Score a match for this specific version of the major VM, if we know about it</span> <span class="cwebmacronumber">15.2.4</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<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">table_of_VM_data</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.VM_code</span><span class="plain"> >= 0; </span><span class="identifier">i</span><span class="plain">++)</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">table_of_VM_data</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.VM_code</span><span class="plain"> == </span><span class="identifier">most_recent_major_VM</span><span class="plain">) &&</span>
|
|
<span class="plain">(</span><span class="identifier">version_specified</span><span class="plain"> == </span><span class="identifier">table_of_VM_data</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.VM_version</span><span class="plain">))</span>
|
|
<span class="identifier">table_of_VM_data</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.VM_matches</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP15_2">§15.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP16"></a><b>§16. </b>The following nonterminal matches any valid description of a virtual machine,
|
|
with result <code class="display"><span class="extract">TRUE</span></code> if the current target VM matches that description and
|
|
<code class="display"><span class="extract">FALSE</span></code> if not.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain"><</span><span class="identifier">virtual</span><span class="plain">-</span><span class="identifier">machine</span><span class="plain">> </span><span class="identifier">internal</span><span class="plain"> {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">target_VM</span><span class="plain"> == -1) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"target VM not set yet"</span><span class="plain">);</span>
|
|
<span class="functiontext">VirtualMachines::match_against</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">VM_matching_error_thrown</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">table_of_VM_data</span><span class="plain">[</span><span class="identifier">target_VM</span><span class="plain">]</span><span class="element">.VM_matches</span><span class="plain">) *</span><span class="identifier">X</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="reserved">else</span><span class="plain"> *</span><span class="identifier">X</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP17"></a><b>§17. Icons for virtual machines. </b>And everything else is cosmetic: printing, or showing icons to signify,
|
|
the current VM or some set of permitted VMs. The following plots the
|
|
icon associated with a given minor VM, and explicates what the icons mean:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">VirtualMachines::plot_icon</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">minor</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">table_of_VM_data</span><span class="plain">[</span><span class="identifier">minor</span><span class="plain">]</span><span class="element">.VM_image</span><span class="plain">) {</span>
|
|
<span class="identifier">HTML_TAG_WITH</span><span class="plain">(</span><span class="string">"img"</span><span class="plain">,</span>
|
|
<span class="string">"border=0 src=inform:/doc_images/%s"</span><span class="plain">,</span>
|
|
<span class="identifier">table_of_VM_data</span><span class="plain">[</span><span class="identifier">minor</span><span class="plain">]</span><span class="element">.VM_image</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&nbsp;"</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">VirtualMachines::write_key</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">) {</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"Extensions compatible with specific story file formats only: "</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">table_of_VM_data</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.VM_code</span><span class="plain"> >= 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">>0) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">", "</span><span class="plain">);</span>
|
|
<span class="functiontext">VirtualMachines::plot_icon</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">i</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">table_of_VM_data</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.VM_name</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function VirtualMachines::plot_icon is used in <a href="#SP19">§19</a>, <a href="#SP20">§20</a>.</p>
|
|
|
|
<p class="endnote">The function VirtualMachines::write_key is used in 8/ec (<a href="8-ec.html#SP10_5">§10.5</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP18"></a><b>§18. Describing the current VM. </b></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">VirtualMachines::index_innards</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">) {</span>
|
|
<span class="functiontext">VirtualMachines::write_current</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
|
|
<span class="functiontext">UseOptions::index</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
|
|
<span class="identifier">HTML_OPEN</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">);</span>
|
|
<span class="identifier">Index::extra_link</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, 3);</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"See some technicalities for Inform maintainers only"</span><span class="plain">);</span>
|
|
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">);</span>
|
|
<span class="identifier">Index::extra_div_open</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, 3, 2, </span><span class="string">"e0e0e0"</span><span class="plain">);</span>
|
|
<span class="functiontext">Plugins::Manage::show_configuration</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
|
|
<<span class="cwebmacro">Add some paste buttons for the debugging log</span> <span class="cwebmacronumber">18.1</span>><span class="plain">;</span>
|
|
<span class="identifier">Index::extra_div_close</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="string">"e0e0e0"</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function VirtualMachines::index_innards appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP18_1"></a><b>§18.1. </b>The index provides some hidden paste icons for these:
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Add some paste buttons for the debugging log</span> <span class="cwebmacronumber">18.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">HTML_OPEN</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"Debugging log:"</span><span class="plain">);</span>
|
|
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">);</span>
|
|
<span class="identifier">HTML_OPEN</span><span class="plain">(</span><span class="string">"p"</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"><</span><span class="identifier">NO_DEFINED_DA_VALUES</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) {</span>
|
|
<span class="identifier">debugging_aspect</span><span class="plain"> *</span><span class="identifier">da</span><span class="plain"> = &(</span><span class="identifier">the_debugging_aspects</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">Str::len</span><span class="plain">(</span><span class="identifier">da</span><span class="plain">-></span><span class="identifier">unhyphenated_name</span><span class="plain">) > 0) {</span>
|
|
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">is</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">is</span><span class="plain">, </span><span class="string">"Include %S in the debugging log."</span><span class="plain">, </span><span class="identifier">da</span><span class="plain">-></span><span class="identifier">unhyphenated_name</span><span class="plain">);</span>
|
|
<span class="identifier">HTML::Javascript::paste_stream</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">is</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&nbsp;%S"</span><span class="plain">, </span><span class="identifier">is</span><span class="plain">);</span>
|
|
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">is</span><span class="plain">);</span>
|
|
<span class="identifier">HTML_TAG</span><span class="plain">(</span><span class="string">"br"</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP18">§18</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP19"></a><b>§19. </b></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">VirtualMachines::write_current</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">target_VM</span><span class="plain"> == -1) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"target VM not set yet"</span><span class="plain">);</span>
|
|
<span class="identifier">Index::anchor</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"STORYFILE"</span><span class="plain">);</span>
|
|
<span class="identifier">HTML_OPEN</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">); </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"Story file format: "</span><span class="plain">);</span>
|
|
<span class="functiontext">VirtualMachines::plot_icon</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">target_VM</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">table_of_VM_data</span><span class="plain">[</span><span class="identifier">target_VM</span><span class="plain">]</span><span class="element">.VM_name</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="identifier">table_of_VM_data</span><span class="plain">[</span><span class="identifier">target_VM</span><span class="plain">]</span><span class="element">.VM_name</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">"No name available\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
|
|
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">VirtualMachines::is_16_bit</span><span class="plain">()) {</span>
|
|
<span class="identifier">HTML_OPEN</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">); </span><span class="identifier">Index::extra_link</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, 1);</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"See estimates of memory usage"</span><span class="plain">);</span>
|
|
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">);</span>
|
|
<span class="identifier">Index::extra_div_open</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, 1, 1, </span><span class="string">"e0e0e0"</span><span class="plain">);</span>
|
|
<span class="functiontext">VirtualMachines::index_memory_usage</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
|
|
<span class="identifier">Index::extra_div_close</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="string">"e0e0e0"</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function VirtualMachines::write_current is used in <a href="#SP18">§18</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP20"></a><b>§20. Displaying VM restrictions. </b>Given a word range, we parse it to set the match flags, then describe the
|
|
result as concisely as we can with a row of icons.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">VirtualMachines::write_icons</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain">) {</span>
|
|
<span class="functiontext">VirtualMachines::match_against</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">);</span>
|
|
<<span class="cwebmacro">Display nothing if every VM matches</span> <span class="cwebmacronumber">20.1</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Display only the generic Z icon if every Z-machine VM version matches</span> <span class="cwebmacronumber">20.2</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">table_of_VM_data</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.VM_code</span><span class="plain"> >= 0; </span><span class="identifier">i</span><span class="plain">++)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">table_of_VM_data</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.VM_matches</span><span class="plain">)</span>
|
|
<span class="functiontext">VirtualMachines::plot_icon</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function VirtualMachines::write_icons is used in 8/ec (<a href="8-ec.html#SP10_7_4_1_1">§10.7.4.1.1</a>), 8/ed2 (<a href="8-ed2.html#SP3_2_1_2">§3.2.1.2</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP20_1"></a><b>§20.1. </b>To avoid the extensions directory page being plastered with gaudy but
|
|
uncommunicative icons, we leave blank space if the requirements are always
|
|
met. The icons are to signal exceptions.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Display nothing if every VM matches</span> <span class="cwebmacronumber">20.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">everything_matches</span><span class="plain"> = </span><span class="identifier">TRUE</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">table_of_VM_data</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.VM_code</span><span class="plain"> >= 0; </span><span class="identifier">i</span><span class="plain">++)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">table_of_VM_data</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.VM_matches</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">)</span>
|
|
<span class="identifier">everything_matches</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">everything_matches</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP20">§20</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP20_2"></a><b>§20.2. </b>This might happen if the user typed "for Z-machine only", but could also
|
|
come about if he typed a specification naming in turn each minor version we
|
|
know about, so the only way to check is to look at the match flag for each
|
|
one.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Display only the generic Z icon if every Z-machine VM version matches</span> <span class="cwebmacronumber">20.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">every_Z_matches</span><span class="plain"> = </span><span class="identifier">TRUE</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">table_of_VM_data</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.VM_code</span><span class="plain"> >= 0; </span><span class="identifier">i</span><span class="plain">++)</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">table_of_VM_data</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.VM_code</span><span class="plain"> == </span><span class="constant">Z_VM</span><span class="plain">) &&</span>
|
|
<span class="plain">(</span><span class="identifier">table_of_VM_data</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.VM_matches</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">))</span>
|
|
<span class="identifier">every_Z_matches</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">every_Z_matches</span><span class="plain">)</span>
|
|
<<span class="cwebmacro">Replace minor Z VMs in the match set with the single major one</span> <span class="cwebmacronumber">20.2.1</span>><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP20">§20</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP20_2_1"></a><b>§20.2.1. </b>The following operation leaves the match set in a state which does not
|
|
correspond to what parsing would tell us (indeed, that's the point): so
|
|
we must not use the match set again without reparsing it. But in fact,
|
|
the match set is always recalculated before being used, so this is fine.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Replace minor Z VMs in the match set with the single major one</span> <span class="cwebmacronumber">20.2.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<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">table_of_VM_data</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.VM_code</span><span class="plain"> >= 0; </span><span class="identifier">i</span><span class="plain">++)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">table_of_VM_data</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.VM_code</span><span class="plain"> == </span><span class="constant">Z_VM</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">table_of_VM_data</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.VM_major_name</span><span class="plain">) </span> <span class="comment">the major VM line for Z</span>
|
|
<span class="identifier">table_of_VM_data</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.VM_matches</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="reserved">else</span>
|
|
<span class="identifier">table_of_VM_data</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]</span><span class="element">.VM_matches</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">; </span> <span class="comment">one of the minor ones</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP20_2">§20.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP21"></a><b>§21. </b>The following table in the index (on the Contents page) may be useful to a
|
|
few diehard Z-machine hackers, determined to squeeze the maximum out of the
|
|
tiny array space available.
|
|
</p>
|
|
|
|
|
|
<pre class="definitions">
|
|
<span class="definitionkeyword">define</span> <span class="constant">NOTEWORTHY_USAGE_THRESHOLD</span><span class="plain"> 50 </span> <span class="comment">don't mention arrays smaller than this, in bytes</span>
|
|
</pre>
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">VirtualMachines::note_usage</span><span class="plain">(</span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">cat</span><span class="plain">, </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">name</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">words</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">bytes</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">each</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">b</span><span class="plain"> = </span><span class="identifier">bytes</span><span class="plain"> + </span><span class="identifier">words</span><span class="plain">*((</span><span class="functiontext">VirtualMachines::is_16_bit</span><span class="plain">())?2:4);</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">each</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) && (</span><span class="identifier">b</span><span class="plain"> < </span><span class="constant">NOTEWORTHY_USAGE_THRESHOLD</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">b</span><span class="plain"> == 0) </span><span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="reserved">VM_usage_note</span><span class="plain"> *</span><span class="identifier">VMun</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">VM_usage_note</span><span class="plain">);</span>
|
|
<span class="identifier">VMun</span><span class="plain">-</span><span class="element">>structure_name</span><span class="plain"> = </span><span class="identifier">W</span><span class="plain">;</span>
|
|
<span class="identifier">VMun</span><span class="plain">-</span><span class="element">>usage_explained</span><span class="plain"> = </span><span class="identifier">Str::duplicate</span><span class="plain">(</span><span class="identifier">name</span><span class="plain">);</span>
|
|
<span class="identifier">VMun</span><span class="plain">-</span><span class="element">>usage_category</span><span class="plain"> = </span><span class="identifier">cat</span><span class="plain">;</span>
|
|
<span class="identifier">VMun</span><span class="plain">-</span><span class="element">>bytes_used</span><span class="plain"> = </span><span class="identifier">b</span><span class="plain">;</span>
|
|
<span class="identifier">VMun</span><span class="plain">-</span><span class="element">>each_flag</span><span class="plain"> = </span><span class="identifier">each</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function VirtualMachines::note_usage is used in 6/rlt (<a href="6-rlt.html#SP20">§20</a>), 15/epv (<a href="15-epv.html#SP1">§1</a>), 19/rsft (<a href="19-rsft.html#SP1_4">§1.4</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP22"></a><b>§22. </b>The explanatory note here probably ought to use the words "approximately",
|
|
"incomplete" and so forth. It's really no better than a guide.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">VirtualMachines::index_memory_usage</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">nr</span><span class="plain"> = </span><span class="identifier">NUMBER_CREATED</span><span class="plain">(</span><span class="reserved">VM_usage_note</span><span class="plain">);</span>
|
|
<span class="reserved">VM_usage_note</span><span class="plain"> **</span><span class="identifier">sorted</span><span class="plain"> = </span><span class="identifier">Memory::I7_calloc</span><span class="plain">(</span><span class="identifier">nr</span><span class="plain">, </span><span class="reserved">sizeof</span><span class="plain">(</span><span class="reserved">VM_usage_note</span><span class="plain"> *), </span><span class="constant">INDEX_SORTING_MREASON</span><span class="plain">);</span>
|
|
<span class="identifier">HTML_OPEN</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">); </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"In a Z-machine story file, array memory can be very limited. "</span>
|
|
<span class="string">"Switching to the Glulx setting removes all difficulty, but some authors "</span>
|
|
<span class="string">"like to squeeze the very most out of the Z-machine instead. This "</span>
|
|
<span class="string">"list shows about how much array space is used by some larger items "</span>
|
|
<span class="string">"the source text has chosen to create."</span><span class="plain">);</span>
|
|
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">);</span>
|
|
<<span class="cwebmacro">Sort the array usages</span> <span class="cwebmacronumber">22.2</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Tabulate the array usages</span> <span class="cwebmacronumber">22.1</span>><span class="plain">;</span>
|
|
<span class="identifier">Memory::I7_array_free</span><span class="plain">(</span><span class="identifier">sorted</span><span class="plain">, </span><span class="constant">INDEX_SORTING_MREASON</span><span class="plain">, </span><span class="identifier">nr</span><span class="plain">, </span><span class="reserved">sizeof</span><span class="plain">(</span><span class="reserved">VM_usage_note</span><span class="plain"> *));</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function VirtualMachines::index_memory_usage is used in <a href="#SP19">§19</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP22_1"></a><b>§22.1. </b>The rows in the table mention pathetically small numbers of bytes, of course,
|
|
by any rational measure.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Tabulate the array usages</span> <span class="cwebmacronumber">22.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">HTML::begin_plain_html_table</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
|
|
<span class="reserved">VM_usage_note</span><span class="plain"> *</span><span class="identifier">VMun</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain"><</span><span class="identifier">nr</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) {</span>
|
|
<span class="identifier">VMun</span><span class="plain"> = </span><span class="identifier">sorted</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">];</span>
|
|
<span class="identifier">HTML::first_html_column</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, 0);</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%s"</span><span class="plain">, </span><span class="identifier">VMun</span><span class="plain">-</span><span class="element">>usage_category</span><span class="plain">);</span>
|
|
<span class="identifier">HTML::next_html_column</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, 0);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">VMun</span><span class="plain">-</span><span class="element">>each_flag</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"each "</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::len</span><span class="plain">(</span><span class="identifier">VMun</span><span class="plain">-</span><span class="element">>usage_explained</span><span class="plain">) > 0)</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%S"</span><span class="plain">, </span><span class="identifier">VMun</span><span class="plain">-</span><span class="element">>usage_explained</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">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">VMun</span><span class="plain">-</span><span class="element">>structure_name</span><span class="plain">) >= 0)</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%W"</span><span class="plain">, </span><span class="identifier">VMun</span><span class="plain">-</span><span class="element">>structure_name</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">VMun</span><span class="plain">-</span><span class="element">>structure_name</span><span class="plain">) >= 0)</span>
|
|
<span class="identifier">Index::link</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">VMun</span><span class="plain">-</span><span class="element">>structure_name</span><span class="plain">));</span>
|
|
<span class="identifier">HTML::next_html_column</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, 0);</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%d bytes"</span><span class="plain">, </span><span class="identifier">VMun</span><span class="plain">-</span><span class="element">>bytes_used</span><span class="plain">);</span>
|
|
<span class="identifier">HTML::end_html_row</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">HTML::end_html_table</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP22">§22</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP22_2"></a><b>§22.2. </b>As usual, we sort with the C library's <code class="display"><span class="extract">qsort</span></code>.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Sort the array usages</span> <span class="cwebmacronumber">22.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain"> = 0;</span>
|
|
<span class="reserved">VM_usage_note</span><span class="plain"> *</span><span class="identifier">VMun</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">VMun</span><span class="plain">, </span><span class="reserved">VM_usage_note</span><span class="plain">) </span><span class="identifier">sorted</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">++] = </span><span class="identifier">VMun</span><span class="plain">;</span>
|
|
<span class="identifier">qsort</span><span class="plain">(</span><span class="identifier">sorted</span><span class="plain">, (</span><span class="identifier">size_t</span><span class="plain">) </span><span class="identifier">nr</span><span class="plain">, </span><span class="reserved">sizeof</span><span class="plain">(</span><span class="reserved">VM_usage_note</span><span class="plain"> *), </span><span class="functiontext">VirtualMachines::compare_usage</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP22">§22</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP23"></a><b>§23. </b>The following means the table is sorted in decreasing order of bytes used,
|
|
with ties resolved by listing the first-declared item first.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">VirtualMachines::compare_usage</span><span class="plain">(</span><span class="reserved">const</span><span class="plain"> </span><span class="reserved">void</span><span class="plain"> *</span><span class="identifier">ent1</span><span class="plain">, </span><span class="reserved">const</span><span class="plain"> </span><span class="reserved">void</span><span class="plain"> *</span><span class="identifier">ent2</span><span class="plain">) {</span>
|
|
<span class="reserved">const</span><span class="plain"> </span><span class="reserved">VM_usage_note</span><span class="plain"> *</span><span class="identifier">v1</span><span class="plain"> = *((</span><span class="reserved">const</span><span class="plain"> </span><span class="reserved">VM_usage_note</span><span class="plain"> **) </span><span class="identifier">ent1</span><span class="plain">);</span>
|
|
<span class="reserved">const</span><span class="plain"> </span><span class="reserved">VM_usage_note</span><span class="plain"> *</span><span class="identifier">v2</span><span class="plain"> = *((</span><span class="reserved">const</span><span class="plain"> </span><span class="reserved">VM_usage_note</span><span class="plain"> **) </span><span class="identifier">ent2</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">v2</span><span class="plain">-</span><span class="element">>bytes_used</span><span class="plain"> != </span><span class="identifier">v1</span><span class="plain">-</span><span class="element">>bytes_used</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">v2</span><span class="plain">-</span><span class="element">>bytes_used</span><span class="plain"> - </span><span class="identifier">v1</span><span class="plain">-</span><span class="element">>bytes_used</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">v1</span><span class="plain">-</span><span class="element">>structure_name</span><span class="plain">) - </span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">v2</span><span class="plain">-</span><span class="element">>structure_name</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function VirtualMachines::compare_usage is used in <a href="#SP22_2">§22.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP24"></a><b>§24. Resource ID numbers. </b>Resources in a Blorb file have unique ID numbers which are positive integers,
|
|
but these are not required to start from 1, nor to be contiguous. For Inform,
|
|
ID number 1 is reserved for the cover image (whether or not any cover image
|
|
is provided: it is legal for there to be figures but no cover, and vice versa).
|
|
Other figures, and sound effects, then mix freely as needed from ID number 3
|
|
on upwards. We skip 2 so that it can be guaranteed that no sound resource
|
|
has ID 1 or 2: this is to help people trying to play sounds in the Z-machine,
|
|
where operand 1 or 2 in the <code class="display"><span class="extract">@sound</span></code> opcode signifies not a sound resource
|
|
number but a long or short beep. If a genuine sound effect had resource ID
|
|
1 or 2, therefore, it would be unplayable on the Z-machine.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">next_free_resource_ID</span><span class="plain"> = 3;</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">VirtualMachines::get_next_free_blorb_resource_ID</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">next_free_resource_ID</span><span class="plain">++;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function VirtualMachines::get_next_free_blorb_resource_ID appears nowhere else.</p>
|
|
|
|
<hr class="tocbar">
|
|
<ul class="toc"><li><i>(This section begins Chapter 26: Compilation Utilities.)</i></li><li><a href="26-i6i.html">Continue with 'Inform 6 Inclusions'</a></li></ul><hr class="tocbar">
|
|
<!--End of weave-->
|
|
</body>
|
|
</html>
|
|
|