1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-05 16:44:21 +03:00
inform7/docs/core-module/26-ct.html
2020-04-07 01:06:09 +01:00

534 lines
81 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>26/jl</title>
<meta name="viewport" content="width=device-width initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="../inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body>
<nav role="navigation">
<h1><a href="../webs.html">Sources</a></h1>
<ul>
<li><a href="../compiler.html"><b>compiler tools</b></a></li>
<li><a href="../other.html">other tools</a></li>
<li><a href="../extensions.html">extensions and kits</a></li>
<li><a href="../units.html">unit test tools</a></li>
</ul>
<h2>Compiler Webs</h2>
<ul>
<li><a href="../inbuild/index.html">inbuild</a></li>
<li><a href="../inform7/index.html">inform7</a></li>
<li><a href="../inter/index.html">inter</a></li>
</ul>
<h2>Inbuild Modules</h2>
<ul>
<li><a href="../inbuild-module/index.html">inbuild</a></li>
<li><a href="../arch-module/index.html">arch</a></li>
<li><a href="../words-module/index.html">words</a></li>
<li><a href="../syntax-module/index.html">syntax</a></li>
<li><a href="../html-module/index.html">html</a></li>
</ul>
<h2>Inform7 Modules</h2>
<ul>
<li><a href="../core-module/index.html">core</a></li>
<li><a href="../problems-module/index.html">problems</a></li>
<li><a href="../inflections-module/index.html">inflections</a></li>
<li><a href="../linguistics-module/index.html">linguistics</a></li>
<li><a href="../kinds-module/index.html">kinds</a></li>
<li><a href="../if-module/index.html">if</a></li>
<li><a href="../multimedia-module/index.html">multimedia</a></li>
<li><a href="../index-module/index.html">index</a></li>
</ul>
<h2>Inter Modules</h2>
<ul>
<li><a href="../inter-module/index.html">inter</a></li>
<li><a href="../building-module/index.html">building</a></li>
<li><a href="../codegen-module/index.html">codegen</a></li>
</ul>
<h2>Foundation</h2>
<ul>
<li><a href="../../../inweb/docs/foundation-module/index.html">foundation</a></li>
</ul>
</nav>
<main role="main">
<!--Weave of '26/ct' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="../compiler.html">Compiler Modules</a></li><li><a href="index.html">core</a></li><li><a href="index.html#26">Chapter 26: Compilation Utilities</a></li><li><b>Compiled Text</b></li></ul><p class="purpose">To compile string constants and comments.</p>
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. </b>We now take a wide Unicode string and compile a double-quoted I6 string
constant which will print out the same content, or initialise a string array.
</p>
<p class="inwebparagraph">A subtly different set of escape characters are used here. It's all trickier
than it might be because of some unfortunate design choices in I6. For
instance, an <code class="display"><span class="extract">@</span></code> character can't be escaped as <code class="display"><span class="extract">@{40}</span></code> because that
would be expanded too early in the string-reading process, so that it
would still be read as an escape-character <code class="display"><span class="extract">@</span></code>, not a literal one.
We therefore have to use <code class="display"><span class="extract">@@64</span></code>. This unfortunately goes wrong, however,
when the immediately following character is a decimal digit, because then
we might construct, e.g., <code class="display"><span class="extract">@@647</span></code>, and I6 will throw an error: no valid
character has ZSCII code 647. We therefore use the <code class="display"><span class="extract">@{...}</span></code> escape to
represent any digit following an <code class="display"><span class="extract">@@</span></code> escape. Since no digit is itself
an escape character with side-effects, a vicious circle is avoided.
</p>
<p class="inwebparagraph">Initialisation of I6 string arrays has different conventions again: these
behave more like dictionary words and the <code class="display"><span class="extract">@@</span></code> escape is not allowed.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">CT_CAPITALISE</span><span class="plain"> </span><span class="constant">1</span><span class="plain"> </span><span class="comment">capitalise first letter of text</span>
<span class="definitionkeyword">define</span> <span class="constant">CT_EXPAND_APOSTROPHES</span><span class="plain"> </span><span class="constant">2</span><span class="plain"> </span><span class="comment">sometimes regard <code class="display"><span class="extract">'</span></code> as <code class="display"><span class="extract">"</span></code></span>
<span class="definitionkeyword">define</span> <span class="constant">CT_RECOGNISE_APOSTROPHE_SUBSTITUTION</span><span class="plain"> </span><span class="constant">4</span><span class="plain"> </span><span class="comment">recognise <code class="display"><span class="extract">[']</span></code> as a literal <code class="display"><span class="extract">'</span></code></span>
<span class="definitionkeyword">define</span> <span class="constant">CT_RECOGNISE_UNICODE_SUBSTITUTION</span><span class="plain"> </span><span class="constant">8</span><span class="plain"> </span><span class="comment">recognise <code class="display"><span class="extract">[unicode N]</span></code> as a literal char</span>
<span class="definitionkeyword">define</span> <span class="constant">CT_DEQUOTE</span><span class="plain"> </span><span class="constant">16</span><span class="plain"> </span><span class="comment">ignore initial and terminal <code class="display"><span class="extract">"</span></code> pair, e.g., render <code class="display"><span class="extract">"fish"</span></code> as <code class="display"><span class="extract">fish</span></code></span>
<span class="definitionkeyword">define</span> <span class="constant">CT_FOR_ARRAY</span><span class="plain"> </span><span class="constant">32</span><span class="plain"> </span><span class="comment">force use of <code class="display"><span class="extract">@{xx}</span></code> form not <code class="display"><span class="extract">@@ddd</span></code></span>
<span class="definitionkeyword">define</span> <span class="constant">CT_BOX_QUOTATION</span><span class="plain"> </span><span class="constant">64</span><span class="plain"> </span><span class="comment">format line breaks into text for an I6 <code class="display"><span class="extract">box</span></code> statement</span>
<span class="definitionkeyword">define</span> <span class="constant">CT_RAW</span><span class="plain"> </span><span class="constant">128</span><span class="plain"> </span><span class="comment">ignore everything except capitalisation and dequoting</span>
<span class="definitionkeyword">define</span> <span class="constant">CT_I6</span><span class="plain"> </span><span class="constant">256</span><span class="plain"> </span><span class="comment">ignore everything except capitalisation and dequoting</span>
<span class="definitionkeyword">define</span> <span class="constant">CT_EXPAND_APOSTROPHES_RAWLY</span><span class="plain"> </span><span class="constant">512</span><span class="plain"> </span><span class="comment">sometimes regard <code class="display"><span class="extract">'</span></code> as <code class="display"><span class="extract">"</span></code></span>
</pre>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">CompiledText::from_wide_string</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">options</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="identifier">from</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">, </span><span class="identifier">to</span><span class="plain"> = </span><span class="identifier">Wide::len</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">), </span><span class="identifier">esc_digit</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">options</span><span class="plain"> &amp; </span><span class="constant">CT_DEQUOTE</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">[0] == </span><span class="character">'"'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">to</span><span class="plain">-1] == </span><span class="character">'"'</span><span class="plain">)) {</span>
<span class="identifier">from</span><span class="plain">++; </span><span class="identifier">to</span><span class="plain">--;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">options</span><span class="plain"> &amp; </span><span class="constant">CT_RAW</span><span class="plain">) {</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=</span><span class="identifier">from</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">to</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">i</span><span class="plain"> == </span><span class="identifier">from</span><span class="plain">) &amp;&amp; (</span><span class="identifier">options</span><span class="plain"> &amp; </span><span class="constant">CT_CAPITALISE</span><span class="plain">))</span>
<span class="identifier">PUT</span><span class="plain">(</span><span class="identifier">Characters::toupper</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]));</span>
<span class="reserved">else</span>
<span class="identifier">PUT</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]);</span>
<span class="plain">}</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=</span><span class="identifier">from</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">to</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'\n'</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">options</span><span class="plain"> &amp; </span><span class="constant">CT_BOX_QUOTATION</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\n"</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" "</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'\t'</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">options</span><span class="plain"> &amp; </span><span class="constant">CT_BOX_QUOTATION</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\n"</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" "</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">NEWLINE_IN_STRING:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">options</span><span class="plain"> &amp; </span><span class="constant">CT_BOX_QUOTATION</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\n"</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"^"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'"'</span><span class="plain">: </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"~"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'@'</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">options</span><span class="plain"> &amp; </span><span class="constant">CT_FOR_ARRAY</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"@{40}"</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">"@@64"</span><span class="plain">); </span><span class="identifier">esc_digit</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">; </span><span class="reserved">continue</span><span class="plain">; }</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'^'</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">options</span><span class="plain"> &amp; </span><span class="constant">CT_BOX_QUOTATION</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"^"</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">options</span><span class="plain"> &amp; </span><span class="constant">CT_FOR_ARRAY</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"@{5E}"</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">"@@94"</span><span class="plain">); </span><span class="identifier">esc_digit</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">; </span><span class="reserved">continue</span><span class="plain">; }</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'~'</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">options</span><span class="plain"> &amp; </span><span class="constant">CT_FOR_ARRAY</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"@{7E}"</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">"@@126"</span><span class="plain">); </span><span class="identifier">esc_digit</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">; </span><span class="reserved">continue</span><span class="plain">; }</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'\\'</span><span class="plain">: </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"@{5C}"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'\''</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">options</span><span class="plain"> &amp; </span><span class="constant">CT_EXPAND_APOSTROPHES</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Apply Inform 7's convention on interpreting single quotation marks</span> <span class="cwebmacronumber">1.1</span>&gt;
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"'"</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'['</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">options</span><span class="plain"> &amp; </span><span class="constant">CT_RECOGNISE_APOSTROPHE_SUBSTITUTION</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+1] == </span><span class="character">'\''</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+2] == </span><span class="character">']'</span><span class="plain">)) { </span><span class="identifier">i</span><span class="plain"> += </span><span class="constant">2</span><span class="plain">; </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"'"</span><span class="plain">); }</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">options</span><span class="plain"> &amp; </span><span class="constant">CT_RECOGNISE_UNICODE_SUBSTITUTION</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">n</span><span class="plain"> = </span><span class="functiontext">CompiledText::expand_unisub</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">p</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">n</span><span class="plain"> == -1) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"["</span><span class="plain">); </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">i</span><span class="plain"> = </span><span class="identifier">n</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"["</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="identifier">default:</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">i</span><span class="plain">==</span><span class="identifier">from</span><span class="plain">) &amp;&amp; (</span><span class="identifier">options</span><span class="plain"> &amp; </span><span class="constant">CT_CAPITALISE</span><span class="plain">))</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%c"</span><span class="plain">, </span><span class="identifier">Characters::toupper</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</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">esc_digit</span><span class="plain">) &amp;&amp; (</span><span class="identifier">Characters::isdigit</span><span class="plain">(</span><span class="identifier">p</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">"@{%02x}"</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]);</span>
<span class="reserved">else</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%c"</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">esc_digit</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</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">CompiledText::from_wide_string_for_emission</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">p</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="identifier">from</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">, </span><span class="identifier">to</span><span class="plain"> = </span><span class="identifier">Wide::len</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">p</span><span class="plain">[0] == </span><span class="character">'"'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">to</span><span class="plain">-1] == </span><span class="character">'"'</span><span class="plain">)) {</span>
<span class="identifier">from</span><span class="plain">++; </span><span class="identifier">to</span><span class="plain">--;</span>
<span class="plain">}</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=</span><span class="identifier">from</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">to</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'\n'</span><span class="plain">:</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" "</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'\t'</span><span class="plain">:</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" "</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">NEWLINE_IN_STRING:</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\n"</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'\''</span><span class="plain">:</span>
&lt;<span class="cwebmacro">Rawly apply Inform 7's convention on interpreting single quotation marks</span> <span class="cwebmacronumber">1.2</span>&gt;
<span class="reserved">break</span><span class="plain">;</span>
<span class="identifier">default:</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%c"</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]);</span>
<span class="reserved">break</span><span class="plain">;</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">CompiledText::bq_from_wide_string</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">p</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="identifier">from</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">, </span><span class="identifier">to</span><span class="plain"> = </span><span class="identifier">Wide::len</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">), </span><span class="identifier">esc_digit</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">p</span><span class="plain">[0] == </span><span class="character">'"'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">to</span><span class="plain">-1] == </span><span class="character">'"'</span><span class="plain">)) {</span>
<span class="identifier">from</span><span class="plain">++; </span><span class="identifier">to</span><span class="plain">--;</span>
<span class="plain">}</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=</span><span class="identifier">from</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">to</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">p</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">"\n"</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'\t'</span><span class="plain">:</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\n"</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">NEWLINE_IN_STRING:</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\n"</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'"'</span><span class="plain">: </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"~"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'@'</span><span class="plain">:</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"@@64"</span><span class="plain">); </span><span class="identifier">esc_digit</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">; </span><span class="reserved">continue</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'^'</span><span class="plain">:</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"^"</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'~'</span><span class="plain">:</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"@@126"</span><span class="plain">); </span><span class="identifier">esc_digit</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">; </span><span class="reserved">continue</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'\\'</span><span class="plain">: </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"@{5C}"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'\''</span><span class="plain">:</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"'"</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">*/</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'['</span><span class="plain">: {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">n</span><span class="plain"> = </span><span class="functiontext">CompiledText::expand_unisub</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">p</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">n</span><span class="plain"> == -1) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"["</span><span class="plain">); </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">i</span><span class="plain"> = </span><span class="identifier">n</span><span class="plain">;</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">default:</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">esc_digit</span><span class="plain">) &amp;&amp; (</span><span class="identifier">Characters::isdigit</span><span class="plain">(</span><span class="identifier">p</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">"@{%02x}"</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]);</span>
<span class="reserved">else</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%c"</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">esc_digit</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function CompiledText::from_wide_string is used in <a href="#SP5">&#167;5</a>, 5/lp (<a href="5-lp.html#SP27_3_1">&#167;27.3.1</a>), 13/rsfk (<a href="13-rsfk.html#SP24_3">&#167;24.3</a>), 17/tl (<a href="17-tl.html#SP14_1">&#167;14.1</a>).</p>
<p class="endnote">The function CompiledText::from_wide_string_for_emission is used in 25/cii (<a href="25-cii.html#SP3_5_8_1">&#167;3.5.8.1</a>).</p>
<p class="endnote">The function CompiledText::bq_from_wide_string is used in 17/tl (<a href="17-tl.html#SP14_2">&#167;14.2</a>).</p>
<p class="inwebparagraph"><a id="SP1_1"></a><b>&#167;1.1. </b>This is where Inform's convention on expanding single quotation marks
to double, provided they appear to be quoting text rather than used as
apostrophes in contractions such as "don't", is implemented. Note the
exceptional case.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Apply Inform 7's convention on interpreting single quotation marks</span> <span class="cwebmacronumber">1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">i</span><span class="plain">==</span><span class="identifier">from</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+1] == </span><span class="character">'s'</span><span class="plain">) &amp;&amp; ((</span><span class="identifier">to</span><span class="plain"> == </span><span class="constant">3</span><span class="plain">) || (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+2] == </span><span class="character">' '</span><span class="plain">)))</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"'"</span><span class="plain">); </span><span class="comment">allow apostrophe if appending e.g. "'s nose" to "Jane"</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">i</span><span class="plain">&gt;0) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+1]) &amp;&amp;</span>
<span class="plain">(</span><span class="functiontext">CompiledText::alphabetic</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">-1])) &amp;&amp;</span>
<span class="plain">(</span><span class="functiontext">CompiledText::alphabetic</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+1])))</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"'"</span><span class="plain">); </span><span class="comment">allow apostrophe sandwiched between two letters</span>
<span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"~"</span><span class="plain">); </span><span class="comment">and otherwise convert to double-quote</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP1">&#167;1</a>.</p>
<p class="inwebparagraph"><a id="SP1_2"></a><b>&#167;1.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Rawly apply Inform 7's convention on interpreting single quotation marks</span> <span class="cwebmacronumber">1.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">i</span><span class="plain">==</span><span class="identifier">from</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+1] == </span><span class="character">'s'</span><span class="plain">) &amp;&amp; ((</span><span class="identifier">to</span><span class="plain"> == </span><span class="constant">3</span><span class="plain">) || (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+2] == </span><span class="character">' '</span><span class="plain">)))</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"'"</span><span class="plain">); </span><span class="comment">allow apostrophe if appending e.g. "'s nose" to "Jane"</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">i</span><span class="plain">&gt;0) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+1]) &amp;&amp;</span>
<span class="plain">(</span><span class="functiontext">CompiledText::alphabetic</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">-1])) &amp;&amp;</span>
<span class="plain">(</span><span class="functiontext">CompiledText::alphabetic</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+1])))</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"'"</span><span class="plain">); </span><span class="comment">allow apostrophe sandwiched between two letters</span>
<span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\""</span><span class="plain">); </span><span class="comment">and otherwise convert to double-quote</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP1">&#167;1</a>.</p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. </b></p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">CompiledText::from_stream</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">options</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="identifier">from</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">, </span><span class="identifier">to</span><span class="plain"> = </span><span class="identifier">Str::len</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">), </span><span class="identifier">esc_digit</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">options</span><span class="plain"> &amp; </span><span class="constant">CT_DEQUOTE</span><span class="plain">) &amp;&amp; (</span><span class="identifier">Str::get_at</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">from</span><span class="plain">) == </span><span class="character">'"'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">Str::get_at</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">to</span><span class="plain">-1) == </span><span class="character">'"'</span><span class="plain">)) {</span>
<span class="identifier">from</span><span class="plain">++; </span><span class="identifier">to</span><span class="plain">--;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">options</span><span class="plain"> &amp; </span><span class="constant">CT_RAW</span><span class="plain">) {</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=</span><span class="identifier">from</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">to</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = </span><span class="identifier">Str::get_at</span><span class="plain">(</span><span class="identifier">p</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">i</span><span class="plain"> == </span><span class="identifier">from</span><span class="plain">) &amp;&amp; (</span><span class="identifier">options</span><span class="plain"> &amp; </span><span class="constant">CT_CAPITALISE</span><span class="plain">))</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%c"</span><span class="plain">, </span><span class="identifier">Characters::toupper</span><span class="plain">(</span><span class="identifier">c</span><span class="plain">));</span>
<span class="reserved">else</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%c"</span><span class="plain">, </span><span class="identifier">c</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=</span><span class="identifier">from</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">to</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = </span><span class="identifier">Str::get_at</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">);</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">c</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'\n'</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">options</span><span class="plain"> &amp; </span><span class="constant">CT_BOX_QUOTATION</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\"\n\""</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" "</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'\t'</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">options</span><span class="plain"> &amp; </span><span class="constant">CT_BOX_QUOTATION</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\"\n\""</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" "</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">NEWLINE_IN_STRING:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">options</span><span class="plain"> &amp; </span><span class="constant">CT_BOX_QUOTATION</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\"\n\""</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"^"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'"'</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">options</span><span class="plain"> &amp; </span><span class="constant">CT_I6</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"~"</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%c"</span><span class="plain">, </span><span class="identifier">c</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'@'</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">options</span><span class="plain"> &amp; </span><span class="constant">CT_I6</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">options</span><span class="plain"> &amp; </span><span class="constant">CT_FOR_ARRAY</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"@{40}"</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">"@@64"</span><span class="plain">); </span><span class="identifier">esc_digit</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">; </span><span class="reserved">continue</span><span class="plain">; }</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">"%c"</span><span class="plain">, </span><span class="identifier">c</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'^'</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">options</span><span class="plain"> &amp; </span><span class="constant">CT_I6</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">options</span><span class="plain"> &amp; </span><span class="constant">CT_BOX_QUOTATION</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\"\n\""</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">options</span><span class="plain"> &amp; </span><span class="constant">CT_FOR_ARRAY</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"@{5E}"</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">"@@94"</span><span class="plain">); </span><span class="identifier">esc_digit</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">; </span><span class="reserved">continue</span><span class="plain">; }</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">"%c"</span><span class="plain">, </span><span class="identifier">c</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'~'</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">options</span><span class="plain"> &amp; </span><span class="constant">CT_I6</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">options</span><span class="plain"> &amp; </span><span class="constant">CT_FOR_ARRAY</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"@{7E}"</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">"@@126"</span><span class="plain">); </span><span class="identifier">esc_digit</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">; </span><span class="reserved">continue</span><span class="plain">; }</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">"%c"</span><span class="plain">, </span><span class="identifier">c</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'\\'</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">options</span><span class="plain"> &amp; </span><span class="constant">CT_I6</span><span class="plain">) {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"@{5C}"</span><span class="plain">);</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">"%c"</span><span class="plain">, </span><span class="identifier">c</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'\''</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">options</span><span class="plain"> &amp; </span><span class="constant">CT_EXPAND_APOSTROPHES</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Apply Inform 7's convention on interpreting single quotation marks, stream version</span> <span class="cwebmacronumber">2.1</span>&gt;
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"'"</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'['</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">options</span><span class="plain"> &amp; </span><span class="constant">CT_RECOGNISE_APOSTROPHE_SUBSTITUTION</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">Str::get_at</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">+1) == </span><span class="character">'\''</span><span class="plain">) &amp;&amp; (</span><span class="identifier">Str::get_at</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">+2) == </span><span class="character">']'</span><span class="plain">)) { </span><span class="identifier">i</span><span class="plain"> += </span><span class="constant">2</span><span class="plain">; </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"'"</span><span class="plain">); }</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">options</span><span class="plain"> &amp; </span><span class="constant">CT_RECOGNISE_UNICODE_SUBSTITUTION</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">n</span><span class="plain"> = </span><span class="functiontext">CompiledText::expand_unisub_S</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">p</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">n</span><span class="plain"> == -1) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"["</span><span class="plain">); </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">i</span><span class="plain"> = </span><span class="identifier">n</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"["</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="identifier">default:</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">i</span><span class="plain">==</span><span class="identifier">from</span><span class="plain">) &amp;&amp; (</span><span class="identifier">options</span><span class="plain"> &amp; </span><span class="constant">CT_CAPITALISE</span><span class="plain">))</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%c"</span><span class="plain">, </span><span class="identifier">Characters::toupper</span><span class="plain">(</span><span class="identifier">c</span><span class="plain">));</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">esc_digit</span><span class="plain">) &amp;&amp; (</span><span class="identifier">Characters::isdigit</span><span class="plain">(</span><span class="identifier">c</span><span class="plain">)))</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"@{%02x}"</span><span class="plain">, </span><span class="identifier">c</span><span class="plain">);</span>
<span class="reserved">else</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%c"</span><span class="plain">, </span><span class="identifier">c</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">esc_digit</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function CompiledText::from_stream is used in 5/lp (<a href="5-lp.html#SP27_3_2">&#167;27.3.2</a>), 26/ts (<a href="26-ts.html#SP10">&#167;10</a>).</p>
<p class="inwebparagraph"><a id="SP2_1"></a><b>&#167;2.1. </b>This is where Inform's convention on expanding single quotation marks
to double, provided they appear to be quoting text rather than used as
apostrophes in contractions such as "don't", is implemented. Note the
exceptional case.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Apply Inform 7's convention on interpreting single quotation marks, stream version</span> <span class="cwebmacronumber">2.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">i</span><span class="plain">==</span><span class="identifier">from</span><span class="plain">) &amp;&amp; (</span><span class="identifier">Str::get_at</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">+1) == </span><span class="character">'s'</span><span class="plain">) &amp;&amp; ((</span><span class="identifier">to</span><span class="plain"> == </span><span class="constant">3</span><span class="plain">) || (</span><span class="identifier">Str::get_at</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">+2) == </span><span class="character">' '</span><span class="plain">)))</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"'"</span><span class="plain">); </span><span class="comment">allow apostrophe if appending e.g. "'s nose" to "Jane"</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">i</span><span class="plain">&gt;0) &amp;&amp; (</span><span class="identifier">Str::get_at</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">+1)) &amp;&amp;</span>
<span class="plain">(</span><span class="functiontext">CompiledText::alphabetic</span><span class="plain">(</span><span class="identifier">Str::get_at</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">-1))) &amp;&amp;</span>
<span class="plain">(</span><span class="functiontext">CompiledText::alphabetic</span><span class="plain">(</span><span class="identifier">Str::get_at</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">+1))))</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"'"</span><span class="plain">); </span><span class="comment">allow apostrophe sandwiched between two letters</span>
<span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">options</span><span class="plain"> &amp; </span><span class="constant">CT_I6</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"~"</span><span class="plain">); </span><span class="comment">and otherwise convert to double-quote</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\""</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP2">&#167;2</a>.</p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>Where we must tiresomely use this:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">CompiledText::alphabetic</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">letter</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">isalpha</span><span class="plain">(</span><span class="identifier">Characters::remove_accent</span><span class="plain">(</span><span class="identifier">letter</span><span class="plain">));</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function CompiledText::alphabetic is used in <a href="#SP1_1">&#167;1.1</a>, <a href="#SP1_2">&#167;1.2</a>, <a href="#SP2_1">&#167;2.1</a>.</p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. </b>This looks for "[unicode 8212]" and turns it into an em-dash, for example.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">MAX_UNISUB_LENGTH</span><span class="plain"> </span><span class="constant">128</span>
</pre>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">CompiledText::expand_unisub</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">p</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">if</span><span class="plain"> ((</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+1] == </span><span class="character">'u'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+2] == </span><span class="character">'n'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+3] == </span><span class="character">'i'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+4] == </span><span class="character">'c'</span><span class="plain">)</span>
<span class="plain">&amp;&amp; (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+5] == </span><span class="character">'o'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+6] == </span><span class="character">'d'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+7] == </span><span class="character">'e'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+8] == </span><span class="character">' '</span><span class="plain">)) {</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">substitution_buffer</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">j</span><span class="plain"> = </span><span class="identifier">i</span><span class="plain">+9;</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">] == </span><span class="character">' '</span><span class="plain">) </span><span class="identifier">j</span><span class="plain">++;</span>
<span class="reserved">while</span><span class="plain"> ((</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">]) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">] != </span><span class="character">']'</span><span class="plain">))</span>
<span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">substitution_buffer</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">++]);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">] == </span><span class="character">']'</span><span class="plain">) {</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">XW</span><span class="plain"> = </span><span class="identifier">Feeds::feed_stream</span><span class="plain">(</span><span class="identifier">substitution_buffer</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">unicode</span><span class="plain">-</span><span class="identifier">character</span><span class="plain">&gt;(</span><span class="identifier">XW</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> -1;</span>
<span class="identifier">PUT</span><span class="plain">(</span><span class="functiontext">Rvalues::to_Unicode_point</span><span class="plain">(&lt;&lt;</span><span class="identifier">rp</span><span class="plain">&gt;&gt;));</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">j</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> -1;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> -1;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">CompiledText::expand_unisub_S</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">p</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">if</span><span class="plain"> (</span><span class="identifier">Str::includes_wide_string_at</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"unicode "</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">+1)) {</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">substitution_buffer</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">j</span><span class="plain"> = </span><span class="identifier">i</span><span class="plain">+9;</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">Str::get_at</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">j</span><span class="plain">) == </span><span class="character">' '</span><span class="plain">) </span><span class="identifier">j</span><span class="plain">++;</span>
<span class="reserved">while</span><span class="plain"> ((</span><span class="identifier">Str::get_at</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">j</span><span class="plain">)) &amp;&amp; (</span><span class="identifier">Str::get_at</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">j</span><span class="plain">) != </span><span class="character">']'</span><span class="plain">))</span>
<span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">substitution_buffer</span><span class="plain">, </span><span class="identifier">Str::get_at</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">j</span><span class="plain">++));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::get_at</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">j</span><span class="plain">) == </span><span class="character">']'</span><span class="plain">) {</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">XW</span><span class="plain"> = </span><span class="identifier">Feeds::feed_stream</span><span class="plain">(</span><span class="identifier">substitution_buffer</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">unicode</span><span class="plain">-</span><span class="identifier">character</span><span class="plain">&gt;(</span><span class="identifier">XW</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> -1;</span>
<span class="identifier">PUT</span><span class="plain">(</span><span class="functiontext">Rvalues::to_Unicode_point</span><span class="plain">(&lt;&lt;</span><span class="identifier">rp</span><span class="plain">&gt;&gt;));</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">j</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> -1;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> -1;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function CompiledText::expand_unisub is used in <a href="#SP1">&#167;1</a>.</p>
<p class="endnote">The function CompiledText::expand_unisub_S is used in <a href="#SP2">&#167;2</a>.</p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. </b>A convenient package for the above:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">CompiledText::from_text_with_options</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="reserved">int</span><span class="plain"> </span><span class="identifier">opts</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">raw</span><span class="plain">) {</span>
<span class="identifier">LOOP_THROUGH_WORDING</span><span class="plain">(</span><span class="identifier">j</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">) {</span>
<span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">raw</span><span class="plain">) </span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">Lexer::word_raw_text</span><span class="plain">(</span><span class="identifier">j</span><span class="plain">); </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">Lexer::word_text</span><span class="plain">(</span><span class="identifier">j</span><span class="plain">);</span>
<span class="functiontext">CompiledText::from_wide_string</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">opts</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">j</span><span class="plain">&lt;</span><span class="identifier">Wordings::last_wn</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">)) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" "</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function CompiledText::from_text_with_options is used in <a href="#SP6">&#167;6</a>.</p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. </b>Whence:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">CompiledText::comment</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">CompiledText::from_text_with_options</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">, </span><span class="constant">0</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">CompiledText::from_text</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">CompiledText::from_text_with_options</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">, </span><span class="constant">0</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 CompiledText::comment is used in 25/cp (<a href="25-cp.html#SP5_1">&#167;5.1</a>).</p>
<p class="endnote">The function CompiledText::from_text is used in 6/rlt (<a href="6-rlt.html#SP15_1_5">&#167;15.1.5</a>), 21/rl (<a href="21-rl.html#SP20_2_1">&#167;20.2.1</a>).</p>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. </b>This doesn't really belong here, or anywhere else, really:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">CompiledText::divider_comment</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="identifier">Produce::comment</span><span class="plain">(</span><span class="functiontext">Emit::tree</span><span class="plain">(), </span><span class="identifier">I</span><span class="string">"----------------------------------------------------------------------------------------------------"</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function CompiledText::divider_comment is used in 21/rb (<a href="21-rb.html#SP22">&#167;22</a>).</p>
<hr class="tocbar">
<ul class="toc"><li><a href="26-jl.html">Back to 'Jump Labels'</a></li><li><a href="26-rt.html">Continue with 'Routines'</a></li></ul><hr class="tocbar">
<!--End of weave-->
</main>
</body>
</html>