inweb-bootstrap/docs/foundation-module/4-prp.html
2022-07-28 17:45:04 +01:00

1028 lines
217 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Preprocessor</title>
<link href="../docs-assets/Breadcrumbs.css" rel="stylesheet" rev="stylesheet" type="text/css">
<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="../docs-assets/Contents.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Progress.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Navigation.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Fonts.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Base.css" rel="stylesheet" rev="stylesheet" type="text/css">
<script>
function togglePopup(material_id) {
var popup = document.getElementById(material_id);
popup.classList.toggle("show");
}
</script>
<link href="../docs-assets/Popups.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Colours.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body class="commentary-font">
<nav role="navigation">
<h1><a href="../index.html">
<img src="../docs-assets/Octagram.png" width=72 height=72">
</a></h1>
<ul><li><a href="../inweb/index.html">inweb</a></li>
</ul><h2>Foundation Module</h2><ul>
<li><a href="index.html"><span class="selectedlink">foundation</span></a></li>
<li><a href="../foundation-test/index.html">foundation-test</a></li>
</ul><h2>Example Webs</h2><ul>
<li><a href="../goldbach/index.html">goldbach</a></li>
<li><a href="../twinprimes/twinprimes.html">twinprimes</a></li>
<li><a href="../eastertide/index.html">eastertide</a></li>
</ul><h2>Repository</h2><ul>
<li><a href="https://github.com/ganelson/inweb"><img src="../docs-assets/github.png" height=18> github</a></li>
</ul><h2>Related Projects</h2><ul>
<li><a href="../../../inform/docs/index.html">inform</a></li>
<li><a href="../../../intest/docs/index.html">intest</a></li>
</ul>
</nav>
<main role="main">
<!--Weave of 'Preprocessor' generated by Inweb-->
<div class="breadcrumbs">
<ul class="crumbs"><li><a href="../index.html">Home</a></li><li><a href="index.html">foundation</a></li><li><a href="index.html#4">Chapter 4: Text Handling</a></li><li><b>Preprocessor</b></li></ul></div>
<p class="purpose">A simple, general-purpose preprocessor for text files, expanding macros and performing repetitions.</p>
<ul class="toc"><li><a href="4-prp.html#SP1">&#167;1. Scanner</a></li><li><a href="4-prp.html#SP5">&#167;5. Variables</a></li><li><a href="4-prp.html#SP9">&#167;9. Macros</a></li><li><a href="4-prp.html#SP13">&#167;13. Reserved macros</a></li><li><a href="4-prp.html#SP15">&#167;15. The expander for user-defined macros</a></li><li><a href="4-prp.html#SP16">&#167;16. The set expander</a></li><li><a href="4-prp.html#SP17">&#167;17. The repeat expander</a></li><li><a href="4-prp.html#SP18">&#167;18. The expander used for all loop ends</a></li></ul><hr class="tocbar">
<p class="commentary firstcommentary"><a id="SP1" class="paragraph-anchor"></a><b>&#167;1. Scanner. </b>Writing a general-purpose preprocessor really is coding like it's 1974, but
it turns out to be useful for multiple applications in the Inform project, and
saves us having to have dependencies on behemoths like the mighty <span class="extract"><span class="extract-syntax">m4</span></span>.
</p>
<p class="commentary">For documentation on the markup notation, see <a href="../inweb/M-wtaw.html" class="internal">Webs, Tangling and Weaving (in inweb)</a>.
</p>
<p class="commentary">To use the preprocessor, call:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="function-syntax">Preprocessor::preprocess</span><span class="plain-syntax">(</span><span class="identifier-syntax">from</span><span class="plain-syntax">, </span><span class="identifier-syntax">to</span><span class="plain-syntax">, </span><span class="identifier-syntax">header</span><span class="plain-syntax">, </span><span class="identifier-syntax">special_macros</span><span class="plain-syntax">, </span><span class="identifier-syntax">specifics</span><span class="plain-syntax">, </span><span class="identifier-syntax">encoding</span><span class="plain-syntax">)</span>
</pre>
<p class="commentary">where <span class="extract"><span class="extract-syntax">from</span></span> and <span class="extract"><span class="extract-syntax">to</span></span> are filenames, <span class="extract"><span class="extract-syntax">header</span></span> is text to place at the top of
the file (if any), <span class="extract"><span class="extract-syntax">special_macros</span></span> is a <span class="extract"><span class="extract-syntax">linked_list</span></span> of <span class="extract"><span class="extract-syntax">preprocessor_macro</span></span>s
set up with special meanings to the situation, and <span class="extract"><span class="extract-syntax">specifics</span></span> is a general
pointer to any data those special meanings need to use. <span class="extract"><span class="extract-syntax">encoding</span></span> should be
one of <span class="extract"><span class="extract-syntax">UTF8_ENC</span></span> or <span class="extract"><span class="extract-syntax">ISO_ENC</span></span>.
</p>
<pre class="definitions code-font"><span class="definition-keyword">define</span> <span class="constant-syntax">PROTECTED_OPEN_BRACE_PPCHAR</span><span class="plain-syntax"> </span><span class="constant-syntax">0x25A0</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">PROTECTED_CLOSE_BRACE_PPCHAR</span><span class="plain-syntax"> </span><span class="constant-syntax">0x25A1</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">PROTECTED_BLANK_PPCHAR</span><span class="plain-syntax"> </span><span class="constant-syntax">0x25A2</span>
</pre>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Preprocessor::preprocess</span><span class="plain-syntax">(</span><span class="reserved-syntax">filename</span><span class="plain-syntax"> *</span><span class="identifier-syntax">prototype</span><span class="plain-syntax">, </span><span class="reserved-syntax">filename</span><span class="plain-syntax"> *</span><span class="identifier-syntax">F</span><span class="plain-syntax">, </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">header</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">linked_list</span><span class="plain-syntax"> *</span><span class="identifier-syntax">special_macros</span><span class="plain-syntax">, </span><span class="reserved-syntax">general_pointer</span><span class="plain-syntax"> </span><span class="identifier-syntax">specifics</span><span class="plain-syntax">, </span><span class="identifier-syntax">wchar_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">comment_char</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">encoding</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> </span><span class="identifier-syntax">processed_file</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">STREAM_OPEN_TO_FILE</span><span class="plain-syntax">(&amp;</span><span class="identifier-syntax">processed_file</span><span class="plain-syntax">, </span><span class="identifier-syntax">F</span><span class="plain-syntax">, </span><span class="identifier-syntax">encoding</span><span class="plain-syntax">) == </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><a href="3-em.html#SP2" class="function-link"><span class="function-syntax">Errors::fatal_with_file</span></a><span class="plain-syntax">(</span><span class="string-syntax">"unable to write tangled file"</span><span class="plain-syntax">, </span><span class="identifier-syntax">F</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">OUT</span><span class="plain-syntax"> = &amp;</span><span class="identifier-syntax">processed_file</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"%S"</span><span class="plain-syntax">, </span><span class="identifier-syntax">header</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">preprocessor_state</span><span class="plain-syntax"> </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="4-prp.html#SP1_2" class="named-paragraph-link"><span class="named-paragraph">Initialise the preprocessor state</span><span class="named-paragraph-number">1.2</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><a href="4-tf.html#SP5" class="function-link"><span class="function-syntax">TextFiles::read</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">prototype</span><span class="plain-syntax">, </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">, </span><span class="string-syntax">"can't open prototype file"</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="constant-syntax">TRUE</span><span class="plain-syntax">, </span><a href="4-prp.html#SP3" class="function-link"><span class="function-syntax">Preprocessor::scan_line</span></a><span class="plain-syntax">, </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, &amp;</span><span class="identifier-syntax">PPS</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax">=0; </span><span class="identifier-syntax">i</span><span class="plain-syntax">&lt;</span><a href="4-sm.html#SP8" class="function-link"><span class="function-syntax">Str::len</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">PPS</span><span class="plain-syntax">.</span><span class="identifier-syntax">dest</span><span class="plain-syntax">); </span><span class="identifier-syntax">i</span><span class="plain-syntax">++) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">wchar_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">c</span><span class="plain-syntax"> = </span><a href="4-sm.html#SP13" class="function-link"><span class="function-syntax">Str::get_at</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">PPS</span><span class="plain-syntax">.</span><span class="element-syntax">dest</span><span class="plain-syntax">, </span><span class="identifier-syntax">i</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">c</span><span class="plain-syntax"> == </span><span class="constant-syntax">PROTECTED_OPEN_BRACE_PPCHAR</span><span class="plain-syntax">) </span><span class="identifier-syntax">PUT</span><span class="plain-syntax">(</span><span class="character-syntax">'{'</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">c</span><span class="plain-syntax"> == </span><span class="constant-syntax">PROTECTED_CLOSE_BRACE_PPCHAR</span><span class="plain-syntax">) </span><span class="identifier-syntax">PUT</span><span class="plain-syntax">(</span><span class="character-syntax">'}'</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">c</span><span class="plain-syntax"> != </span><span class="constant-syntax">PROTECTED_BLANK_PPCHAR</span><span class="plain-syntax">) </span><span class="identifier-syntax">PUT</span><span class="plain-syntax">(</span><span class="identifier-syntax">c</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">STREAM_CLOSE</span><span class="plain-syntax">(</span><span class="identifier-syntax">OUT</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP1_1" class="paragraph-anchor"></a><b>&#167;1.1. </b>The following imposing-looking set of state data is used as we work through
the prototype file line-by-line:
</p>
<pre class="definitions code-font"><span class="definition-keyword">define</span> <span class="constant-syntax">MAX_PREPROCESSOR_LOOP_DEPTH</span><span class="plain-syntax"> </span><span class="constant-syntax">8</span>
</pre>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">typedef</span><span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">preprocessor_state</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">dest</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">preprocessor_macro</span><span class="plain-syntax"> *</span><span class="identifier-syntax">defining</span><span class="plain-syntax">; </span><span class="comment-syntax"> a "define" body being scanned</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">repeat_sp</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">shadow_sp</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">preprocessor_loop</span><span class="plain-syntax"> </span><span class="identifier-syntax">repeat_data</span><span class="plain-syntax">[</span><span class="constant-syntax">MAX_PREPROCESSOR_LOOP_DEPTH</span><span class="plain-syntax">];</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">suppress_newline</span><span class="plain-syntax">; </span><span class="comment-syntax"> at the end of this line</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">last_line_was_blank</span><span class="plain-syntax">; </span><span class="comment-syntax"> used to suppress runs of multiple blank lines</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">preprocessor_variable_set</span><span class="plain-syntax"> *</span><span class="identifier-syntax">global_variables</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">preprocessor_variable_set</span><span class="plain-syntax"> *</span><span class="identifier-syntax">stack_frame</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">linked_list</span><span class="plain-syntax"> *</span><span class="identifier-syntax">known_macros</span><span class="plain-syntax">; </span><span class="comment-syntax"> of </span><span class="extract"><span class="extract-syntax">preprocessor_macro</span></span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">general_pointer</span><span class="plain-syntax"> </span><span class="identifier-syntax">specifics</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">wchar_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">comment_character</span><span class="plain-syntax">;</span>
<span class="plain-syntax">} </span><span class="reserved-syntax">preprocessor_state</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">typedef</span><span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">preprocessor_loop</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">loop_var_name</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">linked_list</span><span class="plain-syntax"> *</span><span class="identifier-syntax">iterations</span><span class="plain-syntax">; </span><span class="comment-syntax"> of </span><span class="extract"><span class="extract-syntax">text_stream</span></span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">repeat_is_block</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">repeat_saved_dest</span><span class="plain-syntax">;</span>
<span class="plain-syntax">} </span><span class="reserved-syntax">preprocessor_loop</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>The structure preprocessor_state is private to this section.</li><li>The structure preprocessor_loop is private to this section.</li></ul>
<p class="commentary firstcommentary"><a id="SP1_2" class="paragraph-anchor"></a><b>&#167;1.2. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Initialise the preprocessor state</span><span class="named-paragraph-number">1.2</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">.</span><span class="element-syntax">dest</span><span class="plain-syntax"> = </span><a href="4-sm.html#SP2" class="function-link"><span class="function-syntax">Str::new</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">.</span><span class="element-syntax">suppress_newline</span><span class="plain-syntax"> = </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">.</span><span class="element-syntax">last_line_was_blank</span><span class="plain-syntax"> = </span><span class="constant-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">.</span><span class="element-syntax">defining</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">.</span><span class="element-syntax">repeat_sp</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">.</span><span class="element-syntax">shadow_sp</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">.</span><span class="element-syntax">global_variables</span><span class="plain-syntax"> = </span><a href="4-prp.html#SP7" class="function-link"><span class="function-syntax">Preprocessor::new_variable_set</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">NULL</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">.</span><span class="element-syntax">stack_frame</span><span class="plain-syntax"> = </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">.</span><span class="element-syntax">global_variables</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">.</span><span class="element-syntax">known_macros</span><span class="plain-syntax"> = </span><a href="4-prp.html#SP13" class="function-link"><span class="function-syntax">Preprocessor::list_of_reserved_macros</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">special_macros</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">.</span><span class="element-syntax">specifics</span><span class="plain-syntax"> = </span><span class="identifier-syntax">specifics</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">.</span><span class="element-syntax">comment_character</span><span class="plain-syntax"> = </span><span class="identifier-syntax">comment_char</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-prp.html#SP1">&#167;1</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP2" class="paragraph-anchor"></a><b>&#167;2. </b>Conceptually, each loop runs a variable with a given name through a series
of textual values in sequence, and we store that data here:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Preprocessor::set_loop_var_name</span><button class="popup" onclick="togglePopup('usagePopup1')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup1">Usage of <span class="code-font"><span class="function-syntax">Preprocessor::set_loop_var_name</span></span>:<br/><a href="4-prp.html#SP4_1_3_1_3">&#167;4.1.3.1.3</a>, <a href="4-prp.html#SP17">&#167;17</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">preprocessor_loop</span><span class="plain-syntax"> *</span><span class="identifier-syntax">loop</span><span class="plain-syntax">, </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">name</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">loop</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">loop_var_name</span><span class="plain-syntax"> = </span><a href="4-sm.html#SP3" class="function-link"><span class="function-syntax">Str::duplicate</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">name</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Preprocessor::add_loop_iteration</span><button class="popup" onclick="togglePopup('usagePopup2')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup2">Usage of <span class="code-font"><span class="function-syntax">Preprocessor::add_loop_iteration</span></span>:<br/><a href="4-prp.html#SP17">&#167;17</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">preprocessor_loop</span><span class="plain-syntax"> *</span><span class="identifier-syntax">loop</span><span class="plain-syntax">, </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">value</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">ADD_TO_LINKED_LIST</span><span class="plain-syntax">(</span><a href="4-sm.html#SP3" class="function-link"><span class="function-syntax">Str::duplicate</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">value</span><span class="plain-syntax">), </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax">, </span><span class="identifier-syntax">loop</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">iterations</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP3" class="paragraph-anchor"></a><b>&#167;3. </b>Lines from the prototype (or sometimes from files spliced in) are read, one
at a time, by the following.
</p>
<p class="commentary">Note that <span class="extract"><span class="extract-syntax">define</span></span> and <span class="extract"><span class="extract-syntax">end-define</span></span> are not themselves macros, and are handled
directly here. So you cannot use repeat loops to define multiple macros with
parametrised names: but then, nor should you.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Preprocessor::scan_line</span><button class="popup" onclick="togglePopup('usagePopup3')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup3">Usage of <span class="code-font"><span class="function-syntax">Preprocessor::scan_line</span></span>:<br/><a href="4-prp.html#SP1">&#167;1</a>, <a href="4-prp.html#SP15">&#167;15</a>, <a href="4-prp.html#SP18_1">&#167;18.1</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">line</span><span class="plain-syntax">, </span><span class="reserved-syntax">text_file_position</span><span class="plain-syntax"> *</span><span class="identifier-syntax">tfp</span><span class="plain-syntax">, </span><span class="reserved-syntax">void</span><span class="plain-syntax"> *</span><span class="identifier-syntax">X</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">preprocessor_state</span><span class="plain-syntax"> *</span><span class="identifier-syntax">PPS</span><span class="plain-syntax"> = (</span><span class="reserved-syntax">preprocessor_state</span><span class="plain-syntax"> *) </span><span class="identifier-syntax">X</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="4-prp.html#SP3_1" class="named-paragraph-link"><span class="named-paragraph">Skip comments</span><span class="named-paragraph-number">3.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="4-prp.html#SP3_2" class="named-paragraph-link"><span class="named-paragraph">Make backslash literals safe</span><span class="named-paragraph-number">3.2</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="4-prp.html#SP3_3" class="named-paragraph-link"><span class="named-paragraph">Deal with textual definitions of new macros</span><span class="named-paragraph-number">3.3</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><a href="4-prp.html#SP4" class="function-link"><span class="function-syntax">Preprocessor::expand</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">line</span><span class="plain-syntax">, </span><span class="identifier-syntax">tfp</span><span class="plain-syntax">, </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="4-prp.html#SP3_4" class="named-paragraph-link"><span class="named-paragraph">Sometimes, but only sometimes, output a newline</span><span class="named-paragraph-number">3.4</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP3_1" class="paragraph-anchor"></a><b>&#167;3.1. </b>A line is a comment to the preprocessor if its first non-whitespace character
is the special comment character: often <span class="extract"><span class="extract-syntax">#</span></span>, but not necessarily.
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Skip comments</span><span class="named-paragraph-number">3.1</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_THROUGH_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">pos</span><span class="plain-syntax">, </span><span class="identifier-syntax">line</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">wchar_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">c</span><span class="plain-syntax"> = </span><a href="4-sm.html#SP13" class="function-link"><span class="function-syntax">Str::get</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pos</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">c</span><span class="plain-syntax"> == </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">comment_character</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="4-chr.html#SP2" class="function-link"><span class="function-syntax">Characters::is_whitespace</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">c</span><span class="plain-syntax">) == </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">) </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-prp.html#SP3">&#167;3</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP3_2" class="paragraph-anchor"></a><b>&#167;3.2. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Make backslash literals safe</span><span class="named-paragraph-number">3.2</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</span><span class="plain-syntax"> &lt; </span><a href="4-sm.html#SP8" class="function-link"><span class="function-syntax">Str::len</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">line</span><span class="plain-syntax">); </span><span class="identifier-syntax">i</span><span class="plain-syntax">++) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">wchar_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">c</span><span class="plain-syntax"> = </span><a href="4-sm.html#SP13" class="function-link"><span class="function-syntax">Str::get_at</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">line</span><span class="plain-syntax">, </span><span class="identifier-syntax">i</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">c</span><span class="plain-syntax"> == </span><span class="character-syntax">'\\'</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">wchar_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">d</span><span class="plain-syntax"> = </span><a href="4-sm.html#SP13" class="function-link"><span class="function-syntax">Str::get_at</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">line</span><span class="plain-syntax">, </span><span class="identifier-syntax">i</span><span class="plain-syntax">+1);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">switch</span><span class="plain-syntax"> (</span><span class="identifier-syntax">d</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="character-syntax">'{'</span><span class="plain-syntax">:</span>
<span class="plain-syntax"> </span><a href="4-sm.html#SP14" class="function-link"><span class="function-syntax">Str::put_at</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">line</span><span class="plain-syntax">, </span><span class="identifier-syntax">i</span><span class="plain-syntax">, </span><span class="constant-syntax">PROTECTED_OPEN_BRACE_PPCHAR</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="4-sm.html#SP14" class="function-link"><span class="function-syntax">Str::put_at</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">line</span><span class="plain-syntax">, </span><span class="identifier-syntax">i</span><span class="plain-syntax">+1, </span><span class="constant-syntax">PROTECTED_BLANK_PPCHAR</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="character-syntax">'}'</span><span class="plain-syntax">:</span>
<span class="plain-syntax"> </span><a href="4-sm.html#SP14" class="function-link"><span class="function-syntax">Str::put_at</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">line</span><span class="plain-syntax">, </span><span class="identifier-syntax">i</span><span class="plain-syntax">, </span><span class="constant-syntax">PROTECTED_CLOSE_BRACE_PPCHAR</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="4-sm.html#SP14" class="function-link"><span class="function-syntax">Str::put_at</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">line</span><span class="plain-syntax">, </span><span class="identifier-syntax">i</span><span class="plain-syntax">+1, </span><span class="constant-syntax">PROTECTED_BLANK_PPCHAR</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="character-syntax">'\\'</span><span class="plain-syntax">:</span>
<span class="plain-syntax"> </span><a href="4-sm.html#SP14" class="function-link"><span class="function-syntax">Str::put_at</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">line</span><span class="plain-syntax">, </span><span class="identifier-syntax">i</span><span class="plain-syntax">+1, </span><span class="constant-syntax">PROTECTED_BLANK_PPCHAR</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="character-syntax">' '</span><span class="plain-syntax">: </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="character-syntax">'\t'</span><span class="plain-syntax">: </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="character-syntax">'\n'</span><span class="plain-syntax">: </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="character-syntax">'\r'</span><span class="plain-syntax">: </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="constant-syntax">0</span><span class="plain-syntax">: </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">default:</span>
<span class="plain-syntax"> </span><a href="3-em.html#SP5" class="function-link"><span class="function-syntax">Errors::in_text_file</span></a><span class="plain-syntax">(</span><span class="string-syntax">"backslash '\\' must be followed by '{', '}' or '\\'"</span><span class="plain-syntax">, </span><span class="identifier-syntax">tfp</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-prp.html#SP3">&#167;3</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP3_3" class="paragraph-anchor"></a><b>&#167;3.3. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Deal with textual definitions of new macros</span><span class="named-paragraph-number">3.3</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">match_results</span><span class="plain-syntax"> </span><span class="identifier-syntax">mr</span><span class="plain-syntax"> = </span><a href="4-pm.html#SP9" class="function-link"><span class="function-syntax">Regexp::create_mr</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="4-pm.html#SP10" class="function-link"><span class="function-syntax">Regexp::match</span></a><span class="plain-syntax">(&amp;</span><span class="identifier-syntax">mr</span><span class="plain-syntax">, </span><span class="identifier-syntax">line</span><span class="plain-syntax">, </span><span class="identifier-syntax">L</span><span class="string-syntax">" *{define: *(%C+) *} *"</span><span class="plain-syntax">)) </span><span class="named-paragraph-container code-font"><a href="4-prp.html#SP3_3_1" class="named-paragraph-link"><span class="named-paragraph">Begin a bare definition</span><span class="named-paragraph-number">3.3.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="4-pm.html#SP10" class="function-link"><span class="function-syntax">Regexp::match</span></a><span class="plain-syntax">(&amp;</span><span class="identifier-syntax">mr</span><span class="plain-syntax">, </span><span class="identifier-syntax">line</span><span class="plain-syntax">, </span><span class="identifier-syntax">L</span><span class="string-syntax">" *{define: *(%C+) (%c*)} *"</span><span class="plain-syntax">)) </span><span class="named-paragraph-container code-font"><a href="4-prp.html#SP3_3_2" class="named-paragraph-link"><span class="named-paragraph">Begin a definition</span><span class="named-paragraph-number">3.3.2</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="4-pm.html#SP10" class="function-link"><span class="function-syntax">Regexp::match</span></a><span class="plain-syntax">(&amp;</span><span class="identifier-syntax">mr</span><span class="plain-syntax">, </span><span class="identifier-syntax">line</span><span class="plain-syntax">, </span><span class="identifier-syntax">L</span><span class="string-syntax">" *{end-define} *"</span><span class="plain-syntax">)) </span><span class="named-paragraph-container code-font"><a href="4-prp.html#SP3_3_4" class="named-paragraph-link"><span class="named-paragraph">End a definition</span><span class="named-paragraph-number">3.3.4</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">defining</span><span class="plain-syntax">) </span><span class="named-paragraph-container code-font"><a href="4-prp.html#SP3_3_3" class="named-paragraph-link"><span class="named-paragraph">Continue a definition</span><span class="named-paragraph-number">3.3.3</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><a href="4-pm.html#SP9" class="function-link"><span class="function-syntax">Regexp::dispose_of</span></a><span class="plain-syntax">(&amp;</span><span class="identifier-syntax">mr</span><span class="plain-syntax">);</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-prp.html#SP3">&#167;3</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP3_3_1" class="paragraph-anchor"></a><b>&#167;3.3.1. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Begin a bare definition</span><span class="named-paragraph-number">3.3.1</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">defining</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><a href="3-em.html#SP5" class="function-link"><span class="function-syntax">Errors::in_text_file</span></a><span class="plain-syntax">(</span><span class="string-syntax">"nested definitions are not allowed"</span><span class="plain-syntax">, </span><span class="identifier-syntax">tfp</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">name</span><span class="plain-syntax"> = </span><span class="identifier-syntax">mr</span><span class="plain-syntax">.</span><span class="element-syntax">exp</span><span class="plain-syntax">[0];</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">parameter_specification</span><span class="plain-syntax"> = </span><a href="4-sm.html#SP2" class="function-link"><span class="function-syntax">Str::new</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">defining</span><span class="plain-syntax"> = </span><a href="4-prp.html#SP11" class="function-link"><span class="function-syntax">Preprocessor::new_macro</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">known_macros</span><span class="plain-syntax">, </span><span class="identifier-syntax">name</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">parameter_specification</span><span class="plain-syntax">, </span><a href="4-prp.html#SP15" class="function-link"><span class="function-syntax">Preprocessor::default_expander</span></a><span class="plain-syntax">, </span><span class="identifier-syntax">tfp</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="4-pm.html#SP9" class="function-link"><span class="function-syntax">Regexp::dispose_of</span></a><span class="plain-syntax">(&amp;</span><span class="identifier-syntax">mr</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-prp.html#SP3_3">&#167;3.3</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP3_3_2" class="paragraph-anchor"></a><b>&#167;3.3.2. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Begin a definition</span><span class="named-paragraph-number">3.3.2</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">defining</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><a href="3-em.html#SP5" class="function-link"><span class="function-syntax">Errors::in_text_file</span></a><span class="plain-syntax">(</span><span class="string-syntax">"nested definitions are not allowed"</span><span class="plain-syntax">, </span><span class="identifier-syntax">tfp</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">name</span><span class="plain-syntax"> = </span><span class="identifier-syntax">mr</span><span class="plain-syntax">.</span><span class="element-syntax">exp</span><span class="plain-syntax">[0];</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">parameter_specification</span><span class="plain-syntax"> = </span><span class="identifier-syntax">mr</span><span class="plain-syntax">.</span><span class="element-syntax">exp</span><span class="plain-syntax">[1];</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">defining</span><span class="plain-syntax"> = </span><a href="4-prp.html#SP11" class="function-link"><span class="function-syntax">Preprocessor::new_macro</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">known_macros</span><span class="plain-syntax">, </span><span class="identifier-syntax">name</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">parameter_specification</span><span class="plain-syntax">, </span><a href="4-prp.html#SP15" class="function-link"><span class="function-syntax">Preprocessor::default_expander</span></a><span class="plain-syntax">, </span><span class="identifier-syntax">tfp</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="4-pm.html#SP9" class="function-link"><span class="function-syntax">Regexp::dispose_of</span></a><span class="plain-syntax">(&amp;</span><span class="identifier-syntax">mr</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-prp.html#SP3_3">&#167;3.3</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP3_3_3" class="paragraph-anchor"></a><b>&#167;3.3.3. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Continue a definition</span><span class="named-paragraph-number">3.3.3</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><a href="4-prp.html#SP12" class="function-link"><span class="function-syntax">Preprocessor::add_line_to_macro</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">defining</span><span class="plain-syntax">, </span><span class="identifier-syntax">line</span><span class="plain-syntax">, </span><span class="identifier-syntax">tfp</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="4-pm.html#SP9" class="function-link"><span class="function-syntax">Regexp::dispose_of</span></a><span class="plain-syntax">(&amp;</span><span class="identifier-syntax">mr</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-prp.html#SP3_3">&#167;3.3</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP3_3_4" class="paragraph-anchor"></a><b>&#167;3.3.4. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">End a definition</span><span class="named-paragraph-number">3.3.4</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">defining</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><a href="3-em.html#SP5" class="function-link"><span class="function-syntax">Errors::in_text_file</span></a><span class="plain-syntax">(</span><span class="string-syntax">"{end-define} without {define: ...}"</span><span class="plain-syntax">, </span><span class="identifier-syntax">tfp</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">defining</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><a href="4-pm.html#SP9" class="function-link"><span class="function-syntax">Regexp::dispose_of</span></a><span class="plain-syntax">(&amp;</span><span class="identifier-syntax">mr</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-prp.html#SP3_3">&#167;3.3</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP3_4" class="paragraph-anchor"></a><b>&#167;3.4. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Sometimes, but only sometimes, output a newline</span><span class="named-paragraph-number">3.4</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">suppress_newline</span><span class="plain-syntax"> == </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">OUT</span><span class="plain-syntax"> = </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">dest</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="4-sm.html#SP8" class="function-link"><span class="function-syntax">Str::len</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">line</span><span class="plain-syntax">) == </span><span class="constant-syntax">0</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">last_line_was_blank</span><span class="plain-syntax"> == </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">) </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"\n"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">last_line_was_blank</span><span class="plain-syntax"> = </span><span class="constant-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">last_line_was_blank</span><span class="plain-syntax"> = </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"\n"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">suppress_newline</span><span class="plain-syntax"> = </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-prp.html#SP3">&#167;3</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP4" class="paragraph-anchor"></a><b>&#167;4. </b>The expander works on material fed to it which:
</p>
<ul class="items"><li>(i) Does not contain any newlines;
</li><li>(ii) Contains braces <span class="extract"><span class="extract-syntax">{ ... }</span></span> used in nested pairs (unless there is a syntax
error in the prototype, in which case we must complain).
</li></ul>
<p class="commentary">The idea is to pass everything straight through except any braced matter,
which needs special attention.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Preprocessor::expand</span><button class="popup" onclick="togglePopup('usagePopup4')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup4">Usage of <span class="code-font"><span class="function-syntax">Preprocessor::expand</span></span>:<br/><a href="4-prp.html#SP3">&#167;3</a>, <a href="4-prp.html#SP4_1_2">&#167;4.1.2</a>, <a href="4-prp.html#SP4_1_3">&#167;4.1.3</a>, <a href="4-prp.html#SP4_1_3_1_1">&#167;4.1.3.1.1</a>, <a href="4-prp.html#SP18_1">&#167;18.1</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">text</span><span class="plain-syntax">, </span><span class="reserved-syntax">text_file_position</span><span class="plain-syntax"> *</span><span class="identifier-syntax">tfp</span><span class="plain-syntax">, </span><span class="reserved-syntax">preprocessor_state</span><span class="plain-syntax"> *</span><span class="identifier-syntax">PPS</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">TEMPORARY_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">before_matter</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">TEMPORARY_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">braced_matter</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">TEMPORARY_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">after_matter</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">bl</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="identifier-syntax">after_times</span><span class="plain-syntax"> = </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</span><span class="plain-syntax"> &lt; </span><a href="4-sm.html#SP8" class="function-link"><span class="function-syntax">Str::len</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">text</span><span class="plain-syntax">); </span><span class="identifier-syntax">i</span><span class="plain-syntax">++) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">wchar_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">c</span><span class="plain-syntax"> = </span><a href="4-sm.html#SP13" class="function-link"><span class="function-syntax">Str::get_at</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">text</span><span class="plain-syntax">, </span><span class="identifier-syntax">i</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">after_times</span><span class="plain-syntax">) </span><span class="identifier-syntax">PUT_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">after_matter</span><span class="plain-syntax">, </span><span class="identifier-syntax">c</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">c</span><span class="plain-syntax"> == </span><span class="character-syntax">'{'</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">bl</span><span class="plain-syntax">++;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bl</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">1</span><span class="plain-syntax">) </span><span class="identifier-syntax">PUT_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">braced_matter</span><span class="plain-syntax">, </span><span class="identifier-syntax">c</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">c</span><span class="plain-syntax"> == </span><span class="character-syntax">'}'</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">bl</span><span class="plain-syntax">--;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bl</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">after_times</span><span class="plain-syntax"> = </span><span class="constant-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="identifier-syntax">PUT_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">braced_matter</span><span class="plain-syntax">, </span><span class="identifier-syntax">c</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bl</span><span class="plain-syntax"> &lt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><a href="3-em.html#SP5" class="function-link"><span class="function-syntax">Errors::in_text_file</span></a><span class="plain-syntax">(</span><span class="string-syntax">"too many '}'s"</span><span class="plain-syntax">, </span><span class="identifier-syntax">tfp</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bl</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">PUT_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">before_matter</span><span class="plain-syntax">, </span><span class="identifier-syntax">c</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="identifier-syntax">PUT_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">braced_matter</span><span class="plain-syntax">, </span><span class="identifier-syntax">c</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bl</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><a href="3-em.html#SP5" class="function-link"><span class="function-syntax">Errors::in_text_file</span></a><span class="plain-syntax">(</span><span class="string-syntax">"too many '{'s"</span><span class="plain-syntax">, </span><span class="identifier-syntax">tfp</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">after_times</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="4-prp.html#SP4_1" class="named-paragraph-link"><span class="named-paragraph">Expand braced matter</span><span class="named-paragraph-number">4.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">dest</span><span class="plain-syntax">, </span><span class="string-syntax">"%S"</span><span class="plain-syntax">, </span><span class="identifier-syntax">text</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">DISCARD_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">before_matter</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">DISCARD_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">braced_matter</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">DISCARD_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">after_matter</span><span class="plain-syntax">)</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP4_1" class="paragraph-anchor"></a><b>&#167;4.1. </b>Suppose we are expanding the text <span class="extract"><span class="extract-syntax">this {ADJECTIVE} ocean {BEHAVIOUR}</span></span>: then
the <span class="extract"><span class="extract-syntax">before_matter</span></span> will be <span class="extract"><span class="extract-syntax">this </span></span>, the <span class="extract"><span class="extract-syntax">braced_matter</span></span> will be <span class="extract"><span class="extract-syntax">ADJECTIVE</span></span>,
and the <span class="extract"><span class="extract-syntax">after_matter</span></span> will be <span class="extract"><span class="extract-syntax"> ocean {BEHAVIOUR}</span></span>.
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Expand braced matter</span><span class="named-paragraph-number">4.1</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="4-prp.html#SP5" class="function-link"><span class="function-syntax">Preprocessor::acceptable_variable_name</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">braced_matter</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="4-prp.html#SP4_1_2" class="named-paragraph-link"><span class="named-paragraph">Expand a variable name</span><span class="named-paragraph-number">4.1.2</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">identifier</span><span class="plain-syntax"> = </span><span class="identifier-syntax">braced_matter</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">parameter_settings</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">match_results</span><span class="plain-syntax"> </span><span class="identifier-syntax">mr</span><span class="plain-syntax"> = </span><a href="4-pm.html#SP9" class="function-link"><span class="function-syntax">Regexp::create_mr</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="4-pm.html#SP10" class="function-link"><span class="function-syntax">Regexp::match</span></a><span class="plain-syntax">(&amp;</span><span class="identifier-syntax">mr</span><span class="plain-syntax">, </span><span class="identifier-syntax">identifier</span><span class="plain-syntax">, </span><span class="identifier-syntax">L</span><span class="string-syntax">"(%C+) (%c*)"</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">identifier</span><span class="plain-syntax"> = </span><span class="identifier-syntax">mr</span><span class="plain-syntax">.</span><span class="element-syntax">exp</span><span class="plain-syntax">[0];</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">parameter_settings</span><span class="plain-syntax"> = </span><span class="identifier-syntax">mr</span><span class="plain-syntax">.</span><span class="element-syntax">exp</span><span class="plain-syntax">[1];</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="4-prp.html#SP4_1_1" class="named-paragraph-link"><span class="named-paragraph">Work out which macro identifier is meant by a loop name</span><span class="named-paragraph-number">4.1.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">preprocessor_macro</span><span class="plain-syntax"> *</span><span class="identifier-syntax">mm</span><span class="plain-syntax"> = </span><a href="4-prp.html#SP14" class="function-link"><span class="function-syntax">Preprocessor::find_macro</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">known_macros</span><span class="plain-syntax">, </span><span class="identifier-syntax">identifier</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">mm</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">TEMPORARY_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">erm</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">erm</span><span class="plain-syntax">, </span><span class="string-syntax">"unknown macro '%S'"</span><span class="plain-syntax">, </span><span class="identifier-syntax">identifier</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="3-em.html#SP5" class="function-link"><span class="function-syntax">Errors::in_text_file_S</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">erm</span><span class="plain-syntax">, </span><span class="identifier-syntax">tfp</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">DISCARD_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">erm</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="4-prp.html#SP4_1_3" class="named-paragraph-link"><span class="named-paragraph">Expand a macro</span><span class="named-paragraph-number">4.1.3</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><a href="4-pm.html#SP9" class="function-link"><span class="function-syntax">Regexp::dispose_of</span></a><span class="plain-syntax">(&amp;</span><span class="identifier-syntax">mr</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-prp.html#SP4">&#167;4</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP4_1_1" class="paragraph-anchor"></a><b>&#167;4.1.1. </b>So, for example, the identifier <span class="extract"><span class="extract-syntax">repeat</span></span> would be changed here either to
<span class="extract"><span class="extract-syntax">repeat-block</span></span> or <span class="extract"><span class="extract-syntax">repeat-span</span></span>: see above for an explanation.
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Work out which macro identifier is meant by a loop name</span><span class="named-paragraph-number">4.1.1</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">preprocessor_macro</span><span class="plain-syntax"> *</span><span class="identifier-syntax">loop_mm</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_OVER_LINKED_LIST</span><span class="plain-syntax">(</span><span class="identifier-syntax">loop_mm</span><span class="plain-syntax">, </span><span class="reserved-syntax">preprocessor_macro</span><span class="plain-syntax">, </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">known_macros</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="4-sm.html#SP8" class="function-link"><span class="function-syntax">Str::len</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">loop_mm</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">loop_name</span><span class="plain-syntax">) &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="4-sm.html#SP19" class="function-link"><span class="function-syntax">Str::eq</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">identifier</span><span class="plain-syntax">, </span><span class="identifier-syntax">loop_mm</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">loop_name</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="4-sm.html#SP23" class="function-link"><span class="function-syntax">Str::is_whitespace</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">after_matter</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">loop_mm</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">span</span><span class="plain-syntax"> == </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">loop_mm</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">begins_loop</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">identifier</span><span class="plain-syntax"> = </span><span class="identifier-syntax">loop_mm</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">identifier</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">loop_mm</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">span</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">loop_mm</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">begins_loop</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">identifier</span><span class="plain-syntax"> = </span><span class="identifier-syntax">loop_mm</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">identifier</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">TEMPORARY_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">end_name</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">end_name</span><span class="plain-syntax">, </span><span class="string-syntax">"end-%S"</span><span class="plain-syntax">, </span><span class="identifier-syntax">loop_mm</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">loop_name</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="4-sm.html#SP19" class="function-link"><span class="function-syntax">Str::eq</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">identifier</span><span class="plain-syntax">, </span><span class="identifier-syntax">end_name</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">repeat_sp</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) &amp;&amp;</span>
<span class="plain-syntax"> (</span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">repeat_data</span><span class="plain-syntax">[</span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">repeat_sp</span><span class="plain-syntax">-1].</span><span class="element-syntax">repeat_is_block</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">loop_mm</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">span</span><span class="plain-syntax"> == </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">loop_mm</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">ends_loop</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">identifier</span><span class="plain-syntax"> = </span><span class="identifier-syntax">loop_mm</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">identifier</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">loop_mm</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">span</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">loop_mm</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">ends_loop</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">identifier</span><span class="plain-syntax"> = </span><span class="identifier-syntax">loop_mm</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">identifier</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">DISCARD_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">end_name</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-prp.html#SP4_1">&#167;4.1</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP4_1_2" class="paragraph-anchor"></a><b>&#167;4.1.2. </b>Note that if we are inside a loop, we do not perform expansion on the variable
name, and instead pass it through unchanged &mdash; still as, say, <span class="extract"><span class="extract-syntax">{NAME}</span></span>. This
is because it won't be expanded until later, when the expander reaches the
end of the loop body.
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Expand a variable name</span><span class="named-paragraph-number">4.1.2</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><a href="4-prp.html#SP4" class="function-link"><span class="function-syntax">Preprocessor::expand</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">before_matter</span><span class="plain-syntax">, </span><span class="identifier-syntax">tfp</span><span class="plain-syntax">, </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">repeat_sp</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">dest</span><span class="plain-syntax">, </span><span class="string-syntax">"{%S}"</span><span class="plain-syntax">, </span><span class="identifier-syntax">braced_matter</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="4-prp.html#SP4_1_2_1" class="named-paragraph-link"><span class="named-paragraph">Definitely expand a variable name</span><span class="named-paragraph-number">4.1.2.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><a href="4-prp.html#SP4" class="function-link"><span class="function-syntax">Preprocessor::expand</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">after_matter</span><span class="plain-syntax">, </span><span class="identifier-syntax">tfp</span><span class="plain-syntax">, </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">);</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-prp.html#SP4_1">&#167;4.1</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP4_1_3" class="paragraph-anchor"></a><b>&#167;4.1.3. </b>Similarly, we don't expand macros inside the body of a loop, except that we
need to expand the <span class="extract"><span class="extract-syntax">{end-repeat-block}</span></span> (or similar) which closes that loop
body, so that we can escape back into normal mode. Because loop constructs
may be nested, we need to react to (but not expand) loop openings, too.
The "shadow stack pointer" shows how deep we are inside these shadowy,
not-yet-acted-on, loops.
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Expand a macro</span><span class="named-paragraph-number">4.1.3</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">mm</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">suppress_whitespace_when_expanding</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (</span><a href="4-chr.html#SP2" class="function-link"><span class="function-syntax">Characters::is_whitespace</span></a><span class="plain-syntax">(</span><a href="4-sm.html#SP13" class="function-link"><span class="function-syntax">Str::get_last_char</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">before_matter</span><span class="plain-syntax">)))</span>
<span class="plain-syntax"> </span><a href="4-sm.html#SP25" class="function-link"><span class="function-syntax">Str::delete_last_character</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">before_matter</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (</span><a href="4-chr.html#SP2" class="function-link"><span class="function-syntax">Characters::is_whitespace</span></a><span class="plain-syntax">(</span><a href="4-sm.html#SP13" class="function-link"><span class="function-syntax">Str::get_first_char</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">after_matter</span><span class="plain-syntax">)))</span>
<span class="plain-syntax"> </span><a href="4-sm.html#SP25" class="function-link"><span class="function-syntax">Str::delete_first_character</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">after_matter</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><a href="4-prp.html#SP4" class="function-link"><span class="function-syntax">Preprocessor::expand</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">before_matter</span><span class="plain-syntax">, </span><span class="identifier-syntax">tfp</span><span class="plain-syntax">, </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">divert_if_repeating</span><span class="plain-syntax"> = </span><span class="constant-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">mm</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">mm</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">begins_loop</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">shadow_sp</span><span class="plain-syntax">++;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">mm</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">mm</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">ends_loop</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">shadow_sp</span><span class="plain-syntax">--;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">shadow_sp</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">divert_if_repeating</span><span class="plain-syntax"> = </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">divert_if_repeating</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">repeat_sp</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">dest</span><span class="plain-syntax">, </span><span class="string-syntax">"{%S}"</span><span class="plain-syntax">, </span><span class="identifier-syntax">braced_matter</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="4-prp.html#SP4_1_3_1" class="named-paragraph-link"><span class="named-paragraph">Definitely expand a macro</span><span class="named-paragraph-number">4.1.3.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">mm</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">suppress_newline_after_expanding</span><span class="plain-syntax">) </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">suppress_newline</span><span class="plain-syntax"> = </span><span class="constant-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><a href="4-prp.html#SP4" class="function-link"><span class="function-syntax">Preprocessor::expand</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">after_matter</span><span class="plain-syntax">, </span><span class="identifier-syntax">tfp</span><span class="plain-syntax">, </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">);</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-prp.html#SP4_1">&#167;4.1</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP4_1_2_1" class="paragraph-anchor"></a><b>&#167;4.1.2.1. </b>We can now forget about the <span class="extract"><span class="extract-syntax">before_matter</span></span>, the <span class="extract"><span class="extract-syntax">after_matter</span></span>, or whether
we ought not to expand after all: that's all taken care of. A variable expands
to its value:
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Definitely expand a variable name</span><span class="named-paragraph-number">4.1.2.1</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">preprocessor_variable</span><span class="plain-syntax"> *</span><span class="identifier-syntax">var</span><span class="plain-syntax"> =</span>
<span class="plain-syntax"> </span><a href="4-prp.html#SP7" class="function-link"><span class="function-syntax">Preprocessor::find_variable</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">braced_matter</span><span class="plain-syntax">, </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stack_frame</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">var</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">dest</span><span class="plain-syntax">, </span><span class="string-syntax">"%S"</span><span class="plain-syntax">, </span><a href="4-prp.html#SP6" class="function-link"><span class="function-syntax">Preprocessor::read_variable</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">var</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">TEMPORARY_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">erm</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">erm</span><span class="plain-syntax">, </span><span class="string-syntax">"unknown variable '%S'"</span><span class="plain-syntax">, </span><span class="identifier-syntax">braced_matter</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="3-em.html#SP5" class="function-link"><span class="function-syntax">Errors::in_text_file_S</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">erm</span><span class="plain-syntax">, </span><span class="identifier-syntax">tfp</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">DISCARD_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">erm</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-prp.html#SP4_1_2">&#167;4.1.2</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP4_1_3_1" class="paragraph-anchor"></a><b>&#167;4.1.3.1. </b>This looks fussy, but really it delegates the work by calling a function
attached to the macro, the <span class="extract"><span class="extract-syntax">expander</span></span>.
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Definitely expand a macro</span><span class="named-paragraph-number">4.1.3.1</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">parameter_values</span><span class="plain-syntax">[</span><span class="constant-syntax">MAX_PP_MACRO_PARAMETERS</span><span class="plain-syntax">];</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax">=0; </span><span class="identifier-syntax">i</span><span class="plain-syntax">&lt;</span><span class="constant-syntax">MAX_PP_MACRO_PARAMETERS</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</span><span class="plain-syntax">++) </span><span class="identifier-syntax">parameter_values</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">] = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="4-prp.html#SP4_1_3_1_1" class="named-paragraph-link"><span class="named-paragraph">Parse the parameters supplied</span><span class="named-paragraph-number">4.1.3.1.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="4-prp.html#SP4_1_3_1_2" class="named-paragraph-link"><span class="named-paragraph">Check that all compulsory parameters have been supplied</span><span class="named-paragraph-number">4.1.3.1.2</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">preprocessor_loop</span><span class="plain-syntax"> *</span><span class="identifier-syntax">loop</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">mm</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">begins_loop</span><span class="plain-syntax">) </span><span class="named-paragraph-container code-font"><a href="4-prp.html#SP4_1_3_1_3" class="named-paragraph-link"><span class="named-paragraph">Initialise repetition data for the loop</span><span class="named-paragraph-number">4.1.3.1.3</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> (*(</span><span class="identifier-syntax">mm</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">expander</span><span class="plain-syntax">))(</span><span class="identifier-syntax">mm</span><span class="plain-syntax">, </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">, </span><span class="identifier-syntax">parameter_values</span><span class="plain-syntax">, </span><span class="identifier-syntax">loop</span><span class="plain-syntax">, </span><span class="identifier-syntax">tfp</span><span class="plain-syntax">);</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-prp.html#SP4_1_3">&#167;4.1.3</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP4_1_3_1_1" class="paragraph-anchor"></a><b>&#167;4.1.3.1.1. </b>Note that textual values of the parameters are themselves expanded before
use: they might contain variables, or even macros. Parameter names are not.
So you can have <span class="extract"><span class="extract-syntax">in: {WHATEVER}</span></span> but not <span class="extract"><span class="extract-syntax">{WHATEVER}: this</span></span>.
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Parse the parameters supplied</span><span class="named-paragraph-number">4.1.3.1.1</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">match_results</span><span class="plain-syntax"> </span><span class="identifier-syntax">mr</span><span class="plain-syntax"> = </span><a href="4-pm.html#SP9" class="function-link"><span class="function-syntax">Regexp::create_mr</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (</span><a href="4-pm.html#SP10" class="function-link"><span class="function-syntax">Regexp::match</span></a><span class="plain-syntax">(&amp;</span><span class="identifier-syntax">mr</span><span class="plain-syntax">, </span><span class="identifier-syntax">parameter_settings</span><span class="plain-syntax">, </span><span class="identifier-syntax">L</span><span class="string-syntax">" *(%C+): *(%c*)"</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">setting</span><span class="plain-syntax"> = </span><span class="identifier-syntax">mr</span><span class="plain-syntax">.</span><span class="element-syntax">exp</span><span class="plain-syntax">[0];</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">value</span><span class="plain-syntax"> = </span><span class="identifier-syntax">mr</span><span class="plain-syntax">.</span><span class="element-syntax">exp</span><span class="plain-syntax">[1];</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">remainder</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">match_results</span><span class="plain-syntax"> </span><span class="identifier-syntax">mr3</span><span class="plain-syntax"> = </span><a href="4-pm.html#SP9" class="function-link"><span class="function-syntax">Regexp::create_mr</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="4-pm.html#SP10" class="function-link"><span class="function-syntax">Regexp::match</span></a><span class="plain-syntax">(&amp;</span><span class="identifier-syntax">mr3</span><span class="plain-syntax">, </span><span class="identifier-syntax">value</span><span class="plain-syntax">, </span><span class="identifier-syntax">L</span><span class="string-syntax">"(%c+?) *(%C+:[^/]%c*)"</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">value</span><span class="plain-syntax"> = </span><span class="identifier-syntax">mr3</span><span class="plain-syntax">.</span><span class="element-syntax">exp</span><span class="plain-syntax">[0];</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">remainder</span><span class="plain-syntax"> = </span><span class="identifier-syntax">mr3</span><span class="plain-syntax">.</span><span class="element-syntax">exp</span><span class="plain-syntax">[1];</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">found</span><span class="plain-syntax"> = </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax">=0; </span><span class="identifier-syntax">i</span><span class="function-syntax">&lt;mm-&gt;</span><span class="element-syntax">no_parameters</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</span><span class="plain-syntax">++)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="4-sm.html#SP19" class="function-link"><span class="function-syntax">Str::eq</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">setting</span><span class="plain-syntax">, </span><span class="identifier-syntax">mm</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">parameters</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">]-&gt;</span><span class="element-syntax">name</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">found</span><span class="plain-syntax"> = </span><span class="constant-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">parameter_values</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">] = </span><a href="4-sm.html#SP2" class="function-link"><span class="function-syntax">Str::new</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">saved</span><span class="plain-syntax"> = </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">dest</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">dest</span><span class="plain-syntax"> = </span><span class="identifier-syntax">parameter_values</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">];</span>
<span class="plain-syntax"> </span><a href="4-prp.html#SP4" class="function-link"><span class="function-syntax">Preprocessor::expand</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">value</span><span class="plain-syntax">, </span><span class="identifier-syntax">tfp</span><span class="plain-syntax">, </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">dest</span><span class="plain-syntax"> = </span><span class="identifier-syntax">saved</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">found</span><span class="plain-syntax"> == </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">TEMPORARY_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">erm</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">erm</span><span class="plain-syntax">, </span><span class="string-syntax">"unknown parameter '%S:'"</span><span class="plain-syntax">, </span><span class="identifier-syntax">setting</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="3-em.html#SP5" class="function-link"><span class="function-syntax">Errors::in_text_file_S</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">erm</span><span class="plain-syntax">, </span><span class="identifier-syntax">tfp</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">DISCARD_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">erm</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><a href="4-sm.html#SP15" class="function-link"><span class="function-syntax">Str::clear</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">parameter_settings</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="4-sm.html#SP17" class="function-link"><span class="function-syntax">Str::copy</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">parameter_settings</span><span class="plain-syntax">, </span><span class="identifier-syntax">remainder</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="4-pm.html#SP9" class="function-link"><span class="function-syntax">Regexp::dispose_of</span></a><span class="plain-syntax">(&amp;</span><span class="identifier-syntax">mr3</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><a href="4-pm.html#SP9" class="function-link"><span class="function-syntax">Regexp::dispose_of</span></a><span class="plain-syntax">(&amp;</span><span class="identifier-syntax">mr</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="4-sm.html#SP23" class="function-link"><span class="function-syntax">Str::is_whitespace</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">parameter_settings</span><span class="plain-syntax">) == </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><a href="3-em.html#SP5" class="function-link"><span class="function-syntax">Errors::in_text_file</span></a><span class="plain-syntax">(</span><span class="string-syntax">"parameter list is malformed"</span><span class="plain-syntax">, </span><span class="identifier-syntax">tfp</span><span class="plain-syntax">);</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-prp.html#SP4_1_3_1">&#167;4.1.3.1</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP4_1_3_1_2" class="paragraph-anchor"></a><b>&#167;4.1.3.1.2. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Check that all compulsory parameters have been supplied</span><span class="named-paragraph-number">4.1.3.1.2</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax">=0; </span><span class="identifier-syntax">i</span><span class="function-syntax">&lt;mm-&gt;</span><span class="element-syntax">no_parameters</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</span><span class="plain-syntax">++)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">parameter_values</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">] == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">mm</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">parameters</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">]-&gt;</span><span class="element-syntax">optional</span><span class="plain-syntax"> == </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">TEMPORARY_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">erm</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">erm</span><span class="plain-syntax">, </span><span class="string-syntax">"compulsory parameter '%S:' not given"</span><span class="plain-syntax">, </span><span class="identifier-syntax">mm</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">parameters</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">]-&gt;</span><span class="element-syntax">name</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="3-em.html#SP5" class="function-link"><span class="function-syntax">Errors::in_text_file_S</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">erm</span><span class="plain-syntax">, </span><span class="identifier-syntax">tfp</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">DISCARD_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">erm</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-prp.html#SP4_1_3_1">&#167;4.1.3.1</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP4_1_3_1_3" class="paragraph-anchor"></a><b>&#167;4.1.3.1.3. </b>The following code is a little misleading. At present, <span class="extract"><span class="extract-syntax">PPS-&gt;repeat_sp</span></span> is
always either 0 or 1, no matter how deep loop nesting is: but that's just an
artefact of the current scanning algorithm, which might some day change.
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Initialise repetition data for the loop</span><span class="named-paragraph-number">4.1.3.1.3</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">repeat_sp</span><span class="plain-syntax"> &gt;= </span><span class="constant-syntax">MAX_PREPROCESSOR_LOOP_DEPTH</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><a href="3-em.html#SP5" class="function-link"><span class="function-syntax">Errors::in_text_file</span></a><span class="plain-syntax">(</span><span class="string-syntax">"repetition too deep"</span><span class="plain-syntax">, </span><span class="identifier-syntax">tfp</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">loop</span><span class="plain-syntax"> = &amp;(</span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">repeat_data</span><span class="plain-syntax">[</span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">repeat_sp</span><span class="plain-syntax">++]);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">shadow_sp</span><span class="plain-syntax"> = </span><span class="constant-syntax">1</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><a href="4-prp.html#SP2" class="function-link"><span class="function-syntax">Preprocessor::set_loop_var_name</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">loop</span><span class="plain-syntax">, </span><span class="identifier-syntax">I</span><span class="string-syntax">"NAME"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">loop</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">iterations</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NEW_LINKED_LIST</span><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">loop</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">repeat_is_block</span><span class="plain-syntax"> = </span><span class="constant-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">mm</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">span</span><span class="plain-syntax">) </span><span class="identifier-syntax">loop</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">repeat_is_block</span><span class="plain-syntax"> = </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">loop</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">repeat_saved_dest</span><span class="plain-syntax"> = </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">dest</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">dest</span><span class="plain-syntax"> = </span><a href="4-sm.html#SP2" class="function-link"><span class="function-syntax">Str::new</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-prp.html#SP4_1_3_1">&#167;4.1.3.1</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP5" class="paragraph-anchor"></a><b>&#167;5. Variables. </b>Names of variables should conform to:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Preprocessor::acceptable_variable_name</span><button class="popup" onclick="togglePopup('usagePopup5')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup5">Usage of <span class="code-font"><span class="function-syntax">Preprocessor::acceptable_variable_name</span></span>:<br/><a href="4-prp.html#SP4_1">&#167;4.1</a>, <a href="4-prp.html#SP16">&#167;16</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">name</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_THROUGH_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">pos</span><span class="plain-syntax">, </span><span class="identifier-syntax">name</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">wchar_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">c</span><span class="plain-syntax"> = </span><a href="4-sm.html#SP13" class="function-link"><span class="function-syntax">Str::get</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pos</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">c</span><span class="plain-syntax"> &gt;= </span><span class="character-syntax">'0'</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">c</span><span class="plain-syntax"> &lt;= </span><span class="character-syntax">'9'</span><span class="plain-syntax">)) </span><span class="reserved-syntax">continue</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">c</span><span class="plain-syntax"> &gt;= </span><span class="character-syntax">'A'</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">c</span><span class="plain-syntax"> &lt;= </span><span class="character-syntax">'Z'</span><span class="plain-syntax">)) </span><span class="reserved-syntax">continue</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">c</span><span class="plain-syntax"> == </span><span class="character-syntax">'_'</span><span class="plain-syntax">) </span><span class="reserved-syntax">continue</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP6" class="paragraph-anchor"></a><b>&#167;6. </b>Variables are all textual:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">typedef</span><span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">preprocessor_variable</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">name</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">value</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="constant-syntax">CLASS_DEFINITION</span>
<span class="plain-syntax">} </span><span class="reserved-syntax">preprocessor_variable</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="function-syntax">Preprocessor::read_variable</span><button class="popup" onclick="togglePopup('usagePopup6')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup6">Usage of <span class="code-font"><span class="function-syntax">Preprocessor::read_variable</span></span>:<br/><a href="4-prp.html#SP4_1_2_1">&#167;4.1.2.1</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">preprocessor_variable</span><span class="plain-syntax"> *</span><span class="identifier-syntax">var</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">var</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"no such pp variable"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">var</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">value</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Preprocessor::write_variable</span><button class="popup" onclick="togglePopup('usagePopup7')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup7">Usage of <span class="code-font"><span class="function-syntax">Preprocessor::write_variable</span></span>:<br/><a href="4-prp.html#SP8">&#167;8</a>, <a href="4-prp.html#SP15">&#167;15</a>, <a href="4-prp.html#SP16">&#167;16</a>, <a href="4-prp.html#SP18_1">&#167;18.1</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">preprocessor_variable</span><span class="plain-syntax"> *</span><span class="identifier-syntax">var</span><span class="plain-syntax">, </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">val</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">var</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"no such pp variable"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">var</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">value</span><span class="plain-syntax"> = </span><a href="4-sm.html#SP3" class="function-link"><span class="function-syntax">Str::duplicate</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">val</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<ul class="endnotetexts"><li>The structure preprocessor_variable is accessed in 2/dct, 2/trs, 4/jsn, 5/ee, 8/bdfw and here.</li></ul>
<p class="commentary firstcommentary"><a id="SP7" class="paragraph-anchor"></a><b>&#167;7. </b>Each variable belongs to a single "set". If <span class="extract"><span class="extract-syntax">EXAMPLE</span></span> has one meaning outside a
definition and another insider, that's two variables with a common name, not
one variable belonging to two sets at once.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">typedef</span><span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">preprocessor_variable_set</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">linked_list</span><span class="plain-syntax"> *</span><span class="identifier-syntax">variables</span><span class="plain-syntax">; </span><span class="comment-syntax"> of </span><span class="extract"><span class="extract-syntax">preprocessor_variable</span></span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">preprocessor_variable_set</span><span class="plain-syntax"> *</span><span class="identifier-syntax">outer</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="constant-syntax">CLASS_DEFINITION</span>
<span class="plain-syntax">} </span><span class="reserved-syntax">preprocessor_variable_set</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">preprocessor_variable_set</span><span class="plain-syntax"> *</span><span class="function-syntax">Preprocessor::new_variable_set</span><button class="popup" onclick="togglePopup('usagePopup8')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup8">Usage of <span class="code-font"><span class="function-syntax">Preprocessor::new_variable_set</span></span>:<br/><a href="4-prp.html#SP1_2">&#167;1.2</a>, <a href="4-prp.html#SP15">&#167;15</a>, <a href="4-prp.html#SP18">&#167;18</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">preprocessor_variable_set</span><span class="plain-syntax"> *</span><span class="identifier-syntax">outer</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">preprocessor_variable_set</span><span class="plain-syntax"> *</span><span class="identifier-syntax">set</span><span class="plain-syntax"> = </span><span class="identifier-syntax">CREATE</span><span class="plain-syntax">(</span><span class="reserved-syntax">preprocessor_variable_set</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">set</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">variables</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NEW_LINKED_LIST</span><span class="plain-syntax">(</span><span class="reserved-syntax">preprocessor_variable</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">set</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">outer</span><span class="plain-syntax"> = </span><span class="identifier-syntax">outer</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">set</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">preprocessor_variable</span><span class="plain-syntax"> *</span><span class="function-syntax">Preprocessor::find_variable_in_one</span><button class="popup" onclick="togglePopup('usagePopup9')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup9">Usage of <span class="code-font"><span class="function-syntax">Preprocessor::find_variable_in_one</span></span>:<br/><a href="4-prp.html#SP8">&#167;8</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">name</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">preprocessor_variable_set</span><span class="plain-syntax"> *</span><span class="identifier-syntax">set</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">set</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">preprocessor_variable</span><span class="plain-syntax"> *</span><span class="identifier-syntax">var</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_OVER_LINKED_LIST</span><span class="plain-syntax">(</span><span class="identifier-syntax">var</span><span class="plain-syntax">, </span><span class="reserved-syntax">preprocessor_variable</span><span class="plain-syntax">, </span><span class="identifier-syntax">set</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">variables</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="4-sm.html#SP19" class="function-link"><span class="function-syntax">Str::eq</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">name</span><span class="plain-syntax">, </span><span class="identifier-syntax">var</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">name</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">var</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">preprocessor_variable</span><span class="plain-syntax"> *</span><span class="function-syntax">Preprocessor::find_variable</span><button class="popup" onclick="togglePopup('usagePopup10')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup10">Usage of <span class="code-font"><span class="function-syntax">Preprocessor::find_variable</span></span>:<br/><a href="4-prp.html#SP4_1_2_1">&#167;4.1.2.1</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">name</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">preprocessor_variable_set</span><span class="plain-syntax"> *</span><span class="identifier-syntax">set</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (</span><span class="identifier-syntax">set</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">preprocessor_variable</span><span class="plain-syntax"> *</span><span class="identifier-syntax">var</span><span class="plain-syntax"> = </span><a href="4-prp.html#SP7" class="function-link"><span class="function-syntax">Preprocessor::find_variable_in_one</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">name</span><span class="plain-syntax">, </span><span class="identifier-syntax">set</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">var</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">var</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">set</span><span class="plain-syntax"> = </span><span class="identifier-syntax">set</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">outer</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<ul class="endnotetexts"><li>The structure preprocessor_variable_set is private to this section.</li></ul>
<p class="commentary firstcommentary"><a id="SP8" class="paragraph-anchor"></a><b>&#167;8. </b>This creates a variable if it doesn't already exist in the given set. (If
it exists in some outer set, that doesn't count.)
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">preprocessor_variable</span><span class="plain-syntax"> *</span><span class="function-syntax">Preprocessor::ensure_variable</span><button class="popup" onclick="togglePopup('usagePopup11')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup11">Usage of <span class="code-font"><span class="function-syntax">Preprocessor::ensure_variable</span></span>:<br/><a href="4-prp.html#SP15">&#167;15</a>, <a href="4-prp.html#SP16">&#167;16</a>, <a href="4-prp.html#SP18">&#167;18</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">name</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">preprocessor_variable_set</span><span class="plain-syntax"> *</span><span class="identifier-syntax">in_set</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">in_set</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"variable without set"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">preprocessor_variable</span><span class="plain-syntax"> *</span><span class="identifier-syntax">var</span><span class="plain-syntax"> = </span><a href="4-prp.html#SP7" class="function-link"><span class="function-syntax">Preprocessor::find_variable_in_one</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">name</span><span class="plain-syntax">, </span><span class="identifier-syntax">in_set</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">var</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">var</span><span class="plain-syntax"> = </span><span class="identifier-syntax">CREATE</span><span class="plain-syntax">(</span><span class="reserved-syntax">preprocessor_variable</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">var</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">name</span><span class="plain-syntax"> = </span><a href="4-sm.html#SP3" class="function-link"><span class="function-syntax">Str::duplicate</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">name</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="4-prp.html#SP6" class="function-link"><span class="function-syntax">Preprocessor::write_variable</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">var</span><span class="plain-syntax">, </span><span class="identifier-syntax">I</span><span class="string-syntax">""</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">ADD_TO_LINKED_LIST</span><span class="plain-syntax">(</span><span class="identifier-syntax">var</span><span class="plain-syntax">, </span><span class="reserved-syntax">preprocessor_variable</span><span class="plain-syntax">, </span><span class="identifier-syntax">in_set</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">variables</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">var</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP9" class="paragraph-anchor"></a><b>&#167;9. Macros. </b>For the most part, each macro seen by users corresponds to a single
<a href="4-prp.html#SP10" class="internal">preprocessor_macro</a>, but loop constructs are an exception. When the user
types <span class="extract"><span class="extract-syntax">{repeat ...}</span></span>, this is a reference to <span class="extract"><span class="extract-syntax">repeat-block</span></span> if the body of
what to repeat occupies multiple lines, but to <span class="extract"><span class="extract-syntax">repeat-span</span></span> if only one.
</p>
<p class="commentary">For example, the first <span class="extract"><span class="extract-syntax">repeat</span></span> loop here uses the macros <span class="extract"><span class="extract-syntax">repeat-block</span></span> and
<span class="extract"><span class="extract-syntax">end-repeat-block</span></span>, and the second uses <span class="extract"><span class="extract-syntax">repeat-span</span></span> and <span class="extract"><span class="extract-syntax">end-repeat-span</span></span>.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> {repeat with SEA in Black, Caspian}</span>
<span class="plain-syntax"> Welcome to the SEA Sea.</span>
<span class="plain-syntax"> {end-repeat}</span>
<span class="plain-syntax"> ...</span>
<span class="plain-syntax"> Seas available:{repeat with SEA in Sargasso, Libyan} {SEA} Sea;{end-repeat}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP10" class="paragraph-anchor"></a><b>&#167;10. </b>There are (for now, anyway) hard but harmlessly large limits on the number of
parameters and the length of a macro:
</p>
<pre class="definitions code-font"><span class="definition-keyword">define</span> <span class="constant-syntax">MAX_PP_MACRO_PARAMETERS</span><span class="plain-syntax"> </span><span class="constant-syntax">8</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">MAX_PP_MACRO_LINES</span><span class="plain-syntax"> </span><span class="constant-syntax">128</span>
</pre>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">typedef</span><span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">preprocessor_macro</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="comment-syntax"> syntax</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">identifier</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">preprocessor_macro_parameter</span><span class="plain-syntax"> *</span><span class="identifier-syntax">parameters</span><span class="plain-syntax">[</span><span class="constant-syntax">MAX_PP_MACRO_PARAMETERS</span><span class="plain-syntax">];</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">no_parameters</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="comment-syntax"> meaning</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">lines</span><span class="plain-syntax">[</span><span class="constant-syntax">MAX_PP_MACRO_LINES</span><span class="plain-syntax">];</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">no_lines</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">void</span><span class="plain-syntax"> (*</span><span class="identifier-syntax">expander</span><span class="plain-syntax">)(</span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">preprocessor_macro</span><span class="plain-syntax"> *, </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">preprocessor_state</span><span class="plain-syntax"> *, </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> **, </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">preprocessor_loop</span><span class="plain-syntax"> *, </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">text_file_position</span><span class="plain-syntax"> *);</span>
<span class="plain-syntax"> </span><span class="comment-syntax"> loop construct if any</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">begins_loop</span><span class="plain-syntax">; </span><span class="comment-syntax"> </span><span class="extract"><span class="extract-syntax">TRUE</span></span><span class="comment-syntax"> for e.g. </span><span class="extract"><span class="extract-syntax">repeat-block</span></span><span class="comment-syntax"> or </span><span class="extract"><span class="extract-syntax">repeat-span</span></span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">ends_loop</span><span class="plain-syntax">; </span><span class="comment-syntax"> </span><span class="extract"><span class="extract-syntax">TRUE</span></span><span class="comment-syntax"> for e.g. </span><span class="extract"><span class="extract-syntax">end-repeat-block</span></span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">loop_name</span><span class="plain-syntax">; </span><span class="comment-syntax"> e.g. </span><span class="extract"><span class="extract-syntax">repeat</span></span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">span</span><span class="plain-syntax">; </span><span class="comment-syntax"> </span><span class="extract"><span class="extract-syntax">TRUE</span></span><span class="comment-syntax"> for e.g. </span><span class="extract"><span class="extract-syntax">end-repeat-span</span></span><span class="comment-syntax"> or </span><span class="extract"><span class="extract-syntax">repeat-span</span></span>
<span class="plain-syntax"> </span><span class="comment-syntax"> textual behaviour</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">suppress_newline_after_expanding</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">suppress_whitespace_when_expanding</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="constant-syntax">CLASS_DEFINITION</span>
<span class="plain-syntax">} </span><span class="reserved-syntax">preprocessor_macro</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">typedef</span><span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">preprocessor_macro_parameter</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">name</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">definition_token</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">optional</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="constant-syntax">CLASS_DEFINITION</span>
<span class="plain-syntax">} </span><span class="reserved-syntax">preprocessor_macro_parameter</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>The structure preprocessor_macro is private to this section.</li><li>The structure preprocessor_macro_parameter is accessed in 2/trs, 4/jsn and here.</li></ul>
<p class="commentary firstcommentary"><a id="SP11" class="paragraph-anchor"></a><b>&#167;11. </b>The following creates a new macro and adds it to the list <span class="extract"><span class="extract-syntax">L</span></span>. By default, it
has an empty definition (i.e., no lines), but may have a meaning provided by its
<span class="extract"><span class="extract-syntax">expander</span></span> function regardless. The <span class="extract"><span class="extract-syntax">parameter_specification</span></span> is as in the
textual declaration: for example, <span class="extract"><span class="extract-syntax">in: IN ?towards: WAY</span></span> would be valid, with
<span class="extract"><span class="extract-syntax">in</span></span> being compulsory and <span class="extract"><span class="extract-syntax">towards</span></span> optional when the macro is used.
</p>
<p class="commentary">If we expected 10000 macros, a dictionary would be better than a list. But in
fact we expect more like 10.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">preprocessor_macro</span><span class="plain-syntax"> *</span><span class="function-syntax">Preprocessor::new_macro</span><button class="popup" onclick="togglePopup('usagePopup12')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup12">Usage of <span class="code-font"><span class="function-syntax">Preprocessor::new_macro</span></span>:<br/><a href="4-prp.html#SP3_3_1">&#167;3.3.1</a>, <a href="4-prp.html#SP3_3_2">&#167;3.3.2</a>, <a href="4-prp.html#SP13">&#167;13</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">linked_list</span><span class="plain-syntax"> *</span><span class="identifier-syntax">L</span><span class="plain-syntax">, </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">name</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">parameter_specification</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">void</span><span class="plain-syntax"> (*</span><span class="identifier-syntax">expander</span><span class="plain-syntax">)(</span><span class="reserved-syntax">preprocessor_macro</span><span class="plain-syntax"> *, </span><span class="reserved-syntax">preprocessor_state</span><span class="plain-syntax"> *, </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> **, </span><span class="reserved-syntax">preprocessor_loop</span><span class="plain-syntax"> *, </span><span class="reserved-syntax">text_file_position</span><span class="plain-syntax"> *),</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">text_file_position</span><span class="plain-syntax"> *</span><span class="identifier-syntax">tfp</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="4-prp.html#SP14" class="function-link"><span class="function-syntax">Preprocessor::find_macro</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">L</span><span class="plain-syntax">, </span><span class="identifier-syntax">name</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><a href="3-em.html#SP5" class="function-link"><span class="function-syntax">Errors::in_text_file</span></a><span class="plain-syntax">(</span><span class="string-syntax">"a macro with this name already exists"</span><span class="plain-syntax">, </span><span class="identifier-syntax">tfp</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">preprocessor_macro</span><span class="plain-syntax"> *</span><span class="identifier-syntax">new_macro</span><span class="plain-syntax"> = </span><span class="identifier-syntax">CREATE</span><span class="plain-syntax">(</span><span class="reserved-syntax">preprocessor_macro</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="4-prp.html#SP11_1" class="named-paragraph-link"><span class="named-paragraph">Initialise the macro</span><span class="named-paragraph-number">11.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="4-prp.html#SP11_2" class="named-paragraph-link"><span class="named-paragraph">Parse the parameter list</span><span class="named-paragraph-number">11.2</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">ADD_TO_LINKED_LIST</span><span class="plain-syntax">(</span><span class="identifier-syntax">new_macro</span><span class="plain-syntax">, </span><span class="reserved-syntax">preprocessor_macro</span><span class="plain-syntax">, </span><span class="identifier-syntax">L</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">new_macro</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP11_1" class="paragraph-anchor"></a><b>&#167;11.1. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Initialise the macro</span><span class="named-paragraph-number">11.1</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="identifier-syntax">new_macro</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">identifier</span><span class="plain-syntax"> = </span><a href="4-sm.html#SP3" class="function-link"><span class="function-syntax">Str::duplicate</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">name</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">new_macro</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">no_parameters</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">new_macro</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">no_lines</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">new_macro</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">expander</span><span class="plain-syntax"> = </span><span class="identifier-syntax">expander</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">new_macro</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">begins_loop</span><span class="plain-syntax"> = </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">new_macro</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">ends_loop</span><span class="plain-syntax"> = </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">new_macro</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">loop_name</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">new_macro</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">span</span><span class="plain-syntax"> = </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">new_macro</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">suppress_newline_after_expanding</span><span class="plain-syntax"> = </span><span class="constant-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">new_macro</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">suppress_whitespace_when_expanding</span><span class="plain-syntax"> = </span><span class="constant-syntax">TRUE</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-prp.html#SP11">&#167;11</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP11_2" class="paragraph-anchor"></a><b>&#167;11.2. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Parse the parameter list</span><span class="named-paragraph-number">11.2</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">spec</span><span class="plain-syntax"> = </span><a href="4-sm.html#SP3" class="function-link"><span class="function-syntax">Str::duplicate</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">parameter_specification</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">match_results</span><span class="plain-syntax"> </span><span class="identifier-syntax">mr</span><span class="plain-syntax"> = </span><a href="4-pm.html#SP9" class="function-link"><span class="function-syntax">Regexp::create_mr</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (</span><a href="4-pm.html#SP10" class="function-link"><span class="function-syntax">Regexp::match</span></a><span class="plain-syntax">(&amp;</span><span class="identifier-syntax">mr</span><span class="plain-syntax">, </span><span class="identifier-syntax">spec</span><span class="plain-syntax">, </span><span class="identifier-syntax">L</span><span class="string-syntax">" *(%C+): *(%C+) *(%c*)"</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">par_name</span><span class="plain-syntax"> = </span><span class="identifier-syntax">mr</span><span class="plain-syntax">.</span><span class="element-syntax">exp</span><span class="plain-syntax">[0];</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">token_name</span><span class="plain-syntax"> = </span><span class="identifier-syntax">mr</span><span class="plain-syntax">.</span><span class="element-syntax">exp</span><span class="plain-syntax">[1];</span>
<span class="plain-syntax"> </span><a href="4-sm.html#SP15" class="function-link"><span class="function-syntax">Str::clear</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">spec</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="4-sm.html#SP17" class="function-link"><span class="function-syntax">Str::copy</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">spec</span><span class="plain-syntax">, </span><span class="identifier-syntax">mr</span><span class="plain-syntax">.</span><span class="element-syntax">exp</span><span class="plain-syntax">[2]);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">new_macro</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">no_parameters</span><span class="plain-syntax"> &gt;= </span><span class="constant-syntax">MAX_PP_MACRO_PARAMETERS</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><a href="3-em.html#SP5" class="function-link"><span class="function-syntax">Errors::in_text_file</span></a><span class="plain-syntax">(</span><span class="string-syntax">"too many parameters in this definition"</span><span class="plain-syntax">, </span><span class="identifier-syntax">tfp</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="4-prp.html#SP11_2_1" class="named-paragraph-link"><span class="named-paragraph">Add parameter to macro</span><span class="named-paragraph-number">11.2.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><a href="4-pm.html#SP9" class="function-link"><span class="function-syntax">Regexp::dispose_of</span></a><span class="plain-syntax">(&amp;</span><span class="identifier-syntax">mr</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="4-sm.html#SP23" class="function-link"><span class="function-syntax">Str::is_whitespace</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">spec</span><span class="plain-syntax">) == </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><a href="3-em.html#SP5" class="function-link"><span class="function-syntax">Errors::in_text_file</span></a><span class="plain-syntax">(</span><span class="string-syntax">"parameter list for this definition is malformed"</span><span class="plain-syntax">, </span><span class="identifier-syntax">tfp</span><span class="plain-syntax">);</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-prp.html#SP11">&#167;11</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP11_2_1" class="paragraph-anchor"></a><b>&#167;11.2.1. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Add parameter to macro</span><span class="named-paragraph-number">11.2.1</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">preprocessor_macro_parameter</span><span class="plain-syntax"> *</span><span class="identifier-syntax">new_parameter</span><span class="plain-syntax"> = </span><span class="identifier-syntax">CREATE</span><span class="plain-syntax">(</span><span class="reserved-syntax">preprocessor_macro_parameter</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">new_parameter</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">name</span><span class="plain-syntax"> = </span><a href="4-sm.html#SP3" class="function-link"><span class="function-syntax">Str::duplicate</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">par_name</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">new_parameter</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">definition_token</span><span class="plain-syntax"> = </span><a href="4-sm.html#SP3" class="function-link"><span class="function-syntax">Str::duplicate</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">token_name</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">new_parameter</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">optional</span><span class="plain-syntax"> = </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="4-sm.html#SP13" class="function-link"><span class="function-syntax">Str::get_first_char</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">new_parameter</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">name</span><span class="plain-syntax">) == </span><span class="character-syntax">'?'</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">new_parameter</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">optional</span><span class="plain-syntax"> = </span><span class="constant-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><a href="4-sm.html#SP25" class="function-link"><span class="function-syntax">Str::delete_first_character</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">new_parameter</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">name</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">new_macro</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">parameters</span><span class="plain-syntax">[</span><span class="identifier-syntax">new_macro</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">no_parameters</span><span class="plain-syntax">++] = </span><span class="identifier-syntax">new_parameter</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-prp.html#SP11_2">&#167;11.2</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP12" class="paragraph-anchor"></a><b>&#167;12. </b>We can then add lines to a macro (though this will only have an effect if its
expander function is <a href="4-prp.html#SP15" class="internal">Preprocessor::default_expander</a>).
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Preprocessor::add_line_to_macro</span><button class="popup" onclick="togglePopup('usagePopup13')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup13">Usage of <span class="code-font"><span class="function-syntax">Preprocessor::add_line_to_macro</span></span>:<br/><a href="4-prp.html#SP3_3_3">&#167;3.3.3</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">preprocessor_macro</span><span class="plain-syntax"> *</span><span class="identifier-syntax">mm</span><span class="plain-syntax">, </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">line</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">text_file_position</span><span class="plain-syntax"> *</span><span class="identifier-syntax">tfp</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">mm</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">no_lines</span><span class="plain-syntax"> &gt;= </span><span class="constant-syntax">MAX_PP_MACRO_LINES</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><a href="3-em.html#SP5" class="function-link"><span class="function-syntax">Errors::in_text_file</span></a><span class="plain-syntax">(</span><span class="string-syntax">"too many lines in this definition"</span><span class="plain-syntax">, </span><span class="identifier-syntax">tfp</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">mm</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">lines</span><span class="plain-syntax">[</span><span class="identifier-syntax">mm</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">no_lines</span><span class="plain-syntax">++] = </span><a href="4-sm.html#SP3" class="function-link"><span class="function-syntax">Str::duplicate</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">line</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP13" class="paragraph-anchor"></a><b>&#167;13. Reserved macros. </b>A few macros are "reserved", that is, have built-in meanings, and use expander
functions other than <a href="4-prp.html#SP15" class="internal">Preprocessor::default_expander</a>.
</p>
<p class="commentary">Some of these, the <span class="extract"><span class="extract-syntax">special_macros</span></span>, are supplied by the code calling the
preprocessor. Those will provide domain-specific functionality. But a few are
built in here and therefore work in every domain:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">linked_list</span><span class="plain-syntax"> *</span><span class="function-syntax">Preprocessor::list_of_reserved_macros</span><button class="popup" onclick="togglePopup('usagePopup14')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup14">Usage of <span class="code-font"><span class="function-syntax">Preprocessor::list_of_reserved_macros</span></span>:<br/><a href="4-prp.html#SP1_2">&#167;1.2</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">linked_list</span><span class="plain-syntax"> *</span><span class="identifier-syntax">special_macros</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">linked_list</span><span class="plain-syntax"> *</span><span class="identifier-syntax">L</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NEW_LINKED_LIST</span><span class="plain-syntax">(</span><span class="reserved-syntax">preprocessor_macro</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="4-prp.html#SP13" class="function-link"><span class="function-syntax">Preprocessor::new_loop_macro</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">L</span><span class="plain-syntax">, </span><span class="identifier-syntax">I</span><span class="string-syntax">"repeat"</span><span class="plain-syntax">, </span><span class="identifier-syntax">I</span><span class="string-syntax">"with: WITH in: IN"</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><a href="4-prp.html#SP17" class="function-link"><span class="function-syntax">Preprocessor::repeat_expander</span></a><span class="plain-syntax">, </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="4-prp.html#SP11" class="function-link"><span class="function-syntax">Preprocessor::new_macro</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">L</span><span class="plain-syntax">, </span><span class="identifier-syntax">I</span><span class="string-syntax">"set"</span><span class="plain-syntax">, </span><span class="identifier-syntax">I</span><span class="string-syntax">"name: NAME value: VALUE"</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><a href="4-prp.html#SP16" class="function-link"><span class="function-syntax">Preprocessor::set_expander</span></a><span class="plain-syntax">, </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">preprocessor_macro</span><span class="plain-syntax"> *</span><span class="identifier-syntax">mm</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_OVER_LINKED_LIST</span><span class="plain-syntax">(</span><span class="identifier-syntax">mm</span><span class="plain-syntax">, </span><span class="reserved-syntax">preprocessor_macro</span><span class="plain-syntax">, </span><span class="identifier-syntax">special_macros</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">ADD_TO_LINKED_LIST</span><span class="plain-syntax">(</span><span class="identifier-syntax">mm</span><span class="plain-syntax">, </span><span class="reserved-syntax">preprocessor_macro</span><span class="plain-syntax">, </span><span class="identifier-syntax">L</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">L</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Preprocessor::do_not_suppress_whitespace</span><span class="plain-syntax">(</span><span class="reserved-syntax">preprocessor_macro</span><span class="plain-syntax"> *</span><span class="identifier-syntax">mm</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">mm</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">suppress_newline_after_expanding</span><span class="plain-syntax"> = </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">mm</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">suppress_whitespace_when_expanding</span><span class="plain-syntax"> = </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Preprocessor::new_loop_macro</span><span class="plain-syntax">(</span><span class="reserved-syntax">linked_list</span><span class="plain-syntax"> *</span><span class="identifier-syntax">L</span><span class="plain-syntax">, </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">name</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">parameter_specification</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">void</span><span class="plain-syntax"> (*</span><span class="identifier-syntax">expander</span><span class="plain-syntax">)(</span><span class="reserved-syntax">preprocessor_macro</span><span class="plain-syntax"> *, </span><span class="reserved-syntax">preprocessor_state</span><span class="plain-syntax"> *, </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> **, </span><span class="reserved-syntax">preprocessor_loop</span><span class="plain-syntax"> *, </span><span class="reserved-syntax">text_file_position</span><span class="plain-syntax"> *),</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">text_file_position</span><span class="plain-syntax"> *</span><span class="identifier-syntax">tfp</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">TEMPORARY_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">subname</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">subname</span><span class="plain-syntax">, </span><span class="string-syntax">"%S-block"</span><span class="plain-syntax">, </span><span class="identifier-syntax">name</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">preprocessor_macro</span><span class="plain-syntax"> *</span><span class="identifier-syntax">mm</span><span class="plain-syntax"> = </span><a href="4-prp.html#SP11" class="function-link"><span class="function-syntax">Preprocessor::new_macro</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">L</span><span class="plain-syntax">, </span><span class="identifier-syntax">subname</span><span class="plain-syntax">, </span><span class="identifier-syntax">parameter_specification</span><span class="plain-syntax">, </span><span class="identifier-syntax">expander</span><span class="plain-syntax">, </span><span class="identifier-syntax">tfp</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">mm</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">begins_loop</span><span class="plain-syntax"> = </span><span class="constant-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">mm</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">loop_name</span><span class="plain-syntax"> = </span><a href="4-sm.html#SP3" class="function-link"><span class="function-syntax">Str::duplicate</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">name</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="4-sm.html#SP15" class="function-link"><span class="function-syntax">Str::clear</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">subname</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">subname</span><span class="plain-syntax">, </span><span class="string-syntax">"end-%S-block"</span><span class="plain-syntax">, </span><span class="identifier-syntax">name</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">mm</span><span class="plain-syntax"> = </span><a href="4-prp.html#SP11" class="function-link"><span class="function-syntax">Preprocessor::new_macro</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">L</span><span class="plain-syntax">, </span><span class="identifier-syntax">subname</span><span class="plain-syntax">, </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, </span><a href="4-prp.html#SP18" class="function-link"><span class="function-syntax">Preprocessor::end_loop_expander</span></a><span class="plain-syntax">, </span><span class="identifier-syntax">tfp</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">mm</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">ends_loop</span><span class="plain-syntax"> = </span><span class="constant-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">mm</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">loop_name</span><span class="plain-syntax"> = </span><a href="4-sm.html#SP3" class="function-link"><span class="function-syntax">Str::duplicate</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">name</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="4-sm.html#SP15" class="function-link"><span class="function-syntax">Str::clear</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">subname</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">subname</span><span class="plain-syntax">, </span><span class="string-syntax">"%S-span"</span><span class="plain-syntax">, </span><span class="identifier-syntax">name</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">mm</span><span class="plain-syntax"> = </span><a href="4-prp.html#SP11" class="function-link"><span class="function-syntax">Preprocessor::new_macro</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">L</span><span class="plain-syntax">, </span><span class="identifier-syntax">subname</span><span class="plain-syntax">, </span><span class="identifier-syntax">parameter_specification</span><span class="plain-syntax">, </span><span class="identifier-syntax">expander</span><span class="plain-syntax">, </span><span class="identifier-syntax">tfp</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">mm</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">begins_loop</span><span class="plain-syntax"> = </span><span class="constant-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">mm</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">loop_name</span><span class="plain-syntax"> = </span><a href="4-sm.html#SP3" class="function-link"><span class="function-syntax">Str::duplicate</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">name</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">mm</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">span</span><span class="plain-syntax"> = </span><span class="constant-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><a href="4-prp.html#SP13" class="function-link"><span class="function-syntax">Preprocessor::do_not_suppress_whitespace</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">mm</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="4-sm.html#SP15" class="function-link"><span class="function-syntax">Str::clear</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">subname</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">subname</span><span class="plain-syntax">, </span><span class="string-syntax">"end-%S-span"</span><span class="plain-syntax">, </span><span class="identifier-syntax">name</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">mm</span><span class="plain-syntax"> = </span><a href="4-prp.html#SP11" class="function-link"><span class="function-syntax">Preprocessor::new_macro</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">L</span><span class="plain-syntax">, </span><span class="identifier-syntax">subname</span><span class="plain-syntax">, </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, </span><a href="4-prp.html#SP18" class="function-link"><span class="function-syntax">Preprocessor::end_loop_expander</span></a><span class="plain-syntax">, </span><span class="identifier-syntax">tfp</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">mm</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">ends_loop</span><span class="plain-syntax"> = </span><span class="constant-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">mm</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">loop_name</span><span class="plain-syntax"> = </span><a href="4-sm.html#SP3" class="function-link"><span class="function-syntax">Str::duplicate</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">name</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">mm</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">span</span><span class="plain-syntax"> = </span><span class="constant-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><a href="4-prp.html#SP13" class="function-link"><span class="function-syntax">Preprocessor::do_not_suppress_whitespace</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">mm</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">DISCARD_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">subname</span><span class="plain-syntax">)</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP14" class="paragraph-anchor"></a><b>&#167;14. </b>Finding a macro in a list:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">preprocessor_macro</span><span class="plain-syntax"> *</span><span class="function-syntax">Preprocessor::find_macro</span><button class="popup" onclick="togglePopup('usagePopup15')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup15">Usage of <span class="code-font"><span class="function-syntax">Preprocessor::find_macro</span></span>:<br/><a href="4-prp.html#SP4_1">&#167;4.1</a>, <a href="4-prp.html#SP11">&#167;11</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">linked_list</span><span class="plain-syntax"> *</span><span class="identifier-syntax">L</span><span class="plain-syntax">, </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">name</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">preprocessor_macro</span><span class="plain-syntax"> *</span><span class="identifier-syntax">mm</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_OVER_LINKED_LIST</span><span class="plain-syntax">(</span><span class="identifier-syntax">mm</span><span class="plain-syntax">, </span><span class="reserved-syntax">preprocessor_macro</span><span class="plain-syntax">, </span><span class="identifier-syntax">L</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="4-sm.html#SP19" class="function-link"><span class="function-syntax">Str::eq</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">mm</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">identifier</span><span class="plain-syntax">, </span><span class="identifier-syntax">name</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">mm</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP15" class="paragraph-anchor"></a><b>&#167;15. The expander for user-defined macros. </b>All macros created by <span class="extract"><span class="extract-syntax">{define: ...}</span></span> are expanded by the following function.
It creates a local "stack frame" making the parameters available as variables,
then runs the definition lines through the scanner, then dismantles the stack
frame again.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Preprocessor::default_expander</span><button class="popup" onclick="togglePopup('usagePopup16')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup16">Usage of <span class="code-font"><span class="function-syntax">Preprocessor::default_expander</span></span>:<br/><a href="4-prp.html#SP3_3_1">&#167;3.3.1</a>, <a href="4-prp.html#SP3_3_2">&#167;3.3.2</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">preprocessor_macro</span><span class="plain-syntax"> *</span><span class="identifier-syntax">mm</span><span class="plain-syntax">, </span><span class="reserved-syntax">preprocessor_state</span><span class="plain-syntax"> *</span><span class="identifier-syntax">PPS</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> **</span><span class="identifier-syntax">parameter_values</span><span class="plain-syntax">, </span><span class="reserved-syntax">preprocessor_loop</span><span class="plain-syntax"> *</span><span class="identifier-syntax">loop</span><span class="plain-syntax">, </span><span class="reserved-syntax">text_file_position</span><span class="plain-syntax"> *</span><span class="identifier-syntax">tfp</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stack_frame</span><span class="plain-syntax"> = </span><a href="4-prp.html#SP7" class="function-link"><span class="function-syntax">Preprocessor::new_variable_set</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stack_frame</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax">=0; </span><span class="identifier-syntax">i</span><span class="function-syntax">&lt;mm-&gt;</span><span class="element-syntax">no_parameters</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</span><span class="plain-syntax">++) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">preprocessor_variable</span><span class="plain-syntax"> *</span><span class="identifier-syntax">var</span><span class="plain-syntax"> =</span>
<span class="plain-syntax"> </span><a href="4-prp.html#SP8" class="function-link"><span class="function-syntax">Preprocessor::ensure_variable</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">mm</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">parameters</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">]-&gt;</span><span class="element-syntax">definition_token</span><span class="plain-syntax">, </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stack_frame</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="4-prp.html#SP6" class="function-link"><span class="function-syntax">Preprocessor::write_variable</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">var</span><span class="plain-syntax">, </span><span class="identifier-syntax">parameter_values</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">]);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax">=0; </span><span class="identifier-syntax">i</span><span class="function-syntax">&lt;mm-&gt;</span><span class="element-syntax">no_lines</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</span><span class="plain-syntax">++)</span>
<span class="plain-syntax"> </span><a href="4-prp.html#SP3" class="function-link"><span class="function-syntax">Preprocessor::scan_line</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">mm</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">lines</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">], </span><span class="identifier-syntax">tfp</span><span class="plain-syntax">, (</span><span class="reserved-syntax">void</span><span class="plain-syntax"> *) </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stack_frame</span><span class="plain-syntax"> = </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stack_frame</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">outer</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP16" class="paragraph-anchor"></a><b>&#167;16. The set expander. </b>An easy one.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Preprocessor::set_expander</span><button class="popup" onclick="togglePopup('usagePopup17')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup17">Usage of <span class="code-font"><span class="function-syntax">Preprocessor::set_expander</span></span>:<br/><a href="4-prp.html#SP13">&#167;13</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">preprocessor_macro</span><span class="plain-syntax"> *</span><span class="identifier-syntax">mm</span><span class="plain-syntax">, </span><span class="reserved-syntax">preprocessor_state</span><span class="plain-syntax"> *</span><span class="identifier-syntax">PPS</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> **</span><span class="identifier-syntax">parameter_values</span><span class="plain-syntax">, </span><span class="reserved-syntax">preprocessor_loop</span><span class="plain-syntax"> *</span><span class="identifier-syntax">loop</span><span class="plain-syntax">, </span><span class="reserved-syntax">text_file_position</span><span class="plain-syntax"> *</span><span class="identifier-syntax">tfp</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">name</span><span class="plain-syntax"> = </span><span class="identifier-syntax">parameter_values</span><span class="plain-syntax">[0];</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">value</span><span class="plain-syntax"> = </span><span class="identifier-syntax">parameter_values</span><span class="plain-syntax">[1];</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="4-prp.html#SP5" class="function-link"><span class="function-syntax">Preprocessor::acceptable_variable_name</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">name</span><span class="plain-syntax">) == </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><a href="3-em.html#SP5" class="function-link"><span class="function-syntax">Errors::in_text_file</span></a><span class="plain-syntax">(</span><span class="string-syntax">"improper variable name"</span><span class="plain-syntax">, </span><span class="identifier-syntax">tfp</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">preprocessor_variable</span><span class="plain-syntax"> *</span><span class="identifier-syntax">var</span><span class="plain-syntax"> = </span><a href="4-prp.html#SP8" class="function-link"><span class="function-syntax">Preprocessor::ensure_variable</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">name</span><span class="plain-syntax">, </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stack_frame</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="4-prp.html#SP6" class="function-link"><span class="function-syntax">Preprocessor::write_variable</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">var</span><span class="plain-syntax">, </span><span class="identifier-syntax">value</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP17" class="paragraph-anchor"></a><b>&#167;17. The repeat expander. </b></p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Preprocessor::repeat_expander</span><button class="popup" onclick="togglePopup('usagePopup18')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup18">Usage of <span class="code-font"><span class="function-syntax">Preprocessor::repeat_expander</span></span>:<br/><a href="4-prp.html#SP13">&#167;13</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">preprocessor_macro</span><span class="plain-syntax"> *</span><span class="identifier-syntax">mm</span><span class="plain-syntax">, </span><span class="reserved-syntax">preprocessor_state</span><span class="plain-syntax"> *</span><span class="identifier-syntax">PPS</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> **</span><span class="identifier-syntax">parameter_values</span><span class="plain-syntax">, </span><span class="reserved-syntax">preprocessor_loop</span><span class="plain-syntax"> *</span><span class="identifier-syntax">loop</span><span class="plain-syntax">, </span><span class="reserved-syntax">text_file_position</span><span class="plain-syntax"> *</span><span class="identifier-syntax">tfp</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">with</span><span class="plain-syntax"> = </span><span class="identifier-syntax">parameter_values</span><span class="plain-syntax">[0];</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">in</span><span class="plain-syntax"> = </span><span class="identifier-syntax">parameter_values</span><span class="plain-syntax">[1];</span>
<span class="plain-syntax"> </span><a href="4-prp.html#SP2" class="function-link"><span class="function-syntax">Preprocessor::set_loop_var_name</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">loop</span><span class="plain-syntax">, </span><span class="identifier-syntax">with</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">match_results</span><span class="plain-syntax"> </span><span class="identifier-syntax">mr</span><span class="plain-syntax"> = </span><a href="4-pm.html#SP9" class="function-link"><span class="function-syntax">Regexp::create_mr</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (</span><a href="4-pm.html#SP10" class="function-link"><span class="function-syntax">Regexp::match</span></a><span class="plain-syntax">(&amp;</span><span class="identifier-syntax">mr</span><span class="plain-syntax">, </span><span class="identifier-syntax">in</span><span class="plain-syntax">, </span><span class="identifier-syntax">L</span><span class="string-syntax">"(%c*?),(%c*)"</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">value</span><span class="plain-syntax"> = </span><span class="identifier-syntax">mr</span><span class="plain-syntax">.</span><span class="element-syntax">exp</span><span class="plain-syntax">[0];</span>
<span class="plain-syntax"> </span><a href="4-sm.html#SP24" class="function-link"><span class="function-syntax">Str::trim_white_space</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">value</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="4-prp.html#SP2" class="function-link"><span class="function-syntax">Preprocessor::add_loop_iteration</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">loop</span><span class="plain-syntax">, </span><span class="identifier-syntax">value</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="4-sm.html#SP15" class="function-link"><span class="function-syntax">Str::clear</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">in</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="4-sm.html#SP17" class="function-link"><span class="function-syntax">Str::copy</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">in</span><span class="plain-syntax">, </span><span class="identifier-syntax">mr</span><span class="plain-syntax">.</span><span class="element-syntax">exp</span><span class="plain-syntax">[1]);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><a href="4-pm.html#SP9" class="function-link"><span class="function-syntax">Regexp::dispose_of</span></a><span class="plain-syntax">(&amp;</span><span class="identifier-syntax">mr</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">value</span><span class="plain-syntax"> = </span><span class="identifier-syntax">in</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><a href="4-sm.html#SP24" class="function-link"><span class="function-syntax">Str::trim_white_space</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">value</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="4-prp.html#SP2" class="function-link"><span class="function-syntax">Preprocessor::add_loop_iteration</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">loop</span><span class="plain-syntax">, </span><span class="identifier-syntax">value</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP18" class="paragraph-anchor"></a><b>&#167;18. The expander used for all loop ends. </b>The macros which open a loop just store up the name of the variable and the
range of its values: otherwise, they do nothing. It's only when the end of a
loop is reached that any expansion happens, and this is where.
</p>
<p class="commentary">We create a new stack frame inside the current one, and put the loop variable
into it. Then we run through the iteration values, setting the variable to
each in turn, and expand the material.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Preprocessor::end_loop_expander</span><button class="popup" onclick="togglePopup('usagePopup19')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup19">Usage of <span class="code-font"><span class="function-syntax">Preprocessor::end_loop_expander</span></span>:<br/><a href="4-prp.html#SP13">&#167;13</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">preprocessor_macro</span><span class="plain-syntax"> *</span><span class="identifier-syntax">mm</span><span class="plain-syntax">, </span><span class="reserved-syntax">preprocessor_state</span><span class="plain-syntax"> *</span><span class="identifier-syntax">PPS</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> **</span><span class="identifier-syntax">parameter_values</span><span class="plain-syntax">, </span><span class="reserved-syntax">preprocessor_loop</span><span class="plain-syntax"> *</span><span class="identifier-syntax">loop</span><span class="plain-syntax">, </span><span class="reserved-syntax">text_file_position</span><span class="plain-syntax"> *</span><span class="identifier-syntax">tfp</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">shadow_sp</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">repeat_sp</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><a href="3-em.html#SP5" class="function-link"><span class="function-syntax">Errors::in_text_file</span></a><span class="plain-syntax">(</span><span class="string-syntax">"end without repeat"</span><span class="plain-syntax">, </span><span class="identifier-syntax">tfp</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">preprocessor_loop</span><span class="plain-syntax"> *</span><span class="identifier-syntax">loop</span><span class="plain-syntax"> = &amp;(</span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">repeat_data</span><span class="plain-syntax">[--(</span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">repeat_sp</span><span class="plain-syntax">)]);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">matter</span><span class="plain-syntax"> = </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">dest</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">dest</span><span class="plain-syntax"> = </span><span class="identifier-syntax">loop</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">repeat_saved_dest</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stack_frame</span><span class="plain-syntax"> = </span><a href="4-prp.html#SP7" class="function-link"><span class="function-syntax">Preprocessor::new_variable_set</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stack_frame</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">preprocessor_variable</span><span class="plain-syntax"> *</span><span class="identifier-syntax">loop_var</span><span class="plain-syntax"> =</span>
<span class="plain-syntax"> </span><a href="4-prp.html#SP8" class="function-link"><span class="function-syntax">Preprocessor::ensure_variable</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">loop</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">loop_var_name</span><span class="plain-syntax">, </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stack_frame</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">value</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_OVER_LINKED_LIST</span><span class="plain-syntax">(</span><span class="identifier-syntax">value</span><span class="plain-syntax">, </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax">, </span><span class="identifier-syntax">loop</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">iterations</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="4-prp.html#SP18_1" class="named-paragraph-link"><span class="named-paragraph">Iterate with this value</span><span class="named-paragraph-number">18.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stack_frame</span><span class="plain-syntax"> = </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">stack_frame</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">outer</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP18_1" class="paragraph-anchor"></a><b>&#167;18.1. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Iterate with this value</span><span class="named-paragraph-number">18.1</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><a href="4-prp.html#SP6" class="function-link"><span class="function-syntax">Preprocessor::write_variable</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">loop_var</span><span class="plain-syntax">, </span><span class="identifier-syntax">value</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">mm</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">span</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><a href="4-prp.html#SP4" class="function-link"><span class="function-syntax">Preprocessor::expand</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">matter</span><span class="plain-syntax">, </span><span class="identifier-syntax">tfp</span><span class="plain-syntax">, </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">TEMPORARY_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">line</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_THROUGH_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">pos</span><span class="plain-syntax">, </span><span class="identifier-syntax">matter</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="4-sm.html#SP13" class="function-link"><span class="function-syntax">Str::get</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pos</span><span class="plain-syntax">) == </span><span class="character-syntax">'\n'</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><a href="4-prp.html#SP3" class="function-link"><span class="function-syntax">Preprocessor::scan_line</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">line</span><span class="plain-syntax">, </span><span class="identifier-syntax">tfp</span><span class="plain-syntax">, (</span><span class="reserved-syntax">void</span><span class="plain-syntax"> *) </span><span class="identifier-syntax">PPS</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="4-sm.html#SP15" class="function-link"><span class="function-syntax">Str::clear</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">line</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PUT_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">line</span><span class="plain-syntax">, </span><a href="4-sm.html#SP13" class="function-link"><span class="function-syntax">Str::get</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pos</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">DISCARD_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">line</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="4-prp.html#SP18">&#167;18</a>.</li></ul>
<nav role="progress"><div class="progresscontainer">
<ul class="progressbar"><li class="progressprev"><a href="4-tf.html">&#10094;</a></li><li class="progresschapter"><a href="P-abgtf.html">P</a></li><li class="progresschapter"><a href="1-fm.html">1</a></li><li class="progresschapter"><a href="2-dl.html">2</a></li><li class="progresschapter"><a href="3-em.html">3</a></li><li class="progresscurrentchapter">4</li><li class="progresssection"><a href="4-chr.html">chr</a></li><li class="progresssection"><a href="4-cst.html">cst</a></li><li class="progresssection"><a href="4-ws.html">ws</a></li><li class="progresssection"><a href="4-sm.html">sm</a></li><li class="progresssection"><a href="4-tf.html">tf</a></li><li class="progresscurrent">prp</li><li class="progresssection"><a href="4-taa.html">taa</a></li><li class="progresssection"><a href="4-pm.html">pm</a></li><li class="progresssection"><a href="4-jsn.html">jsn</a></li><li class="progresschapter"><a href="5-htm.html">5</a></li><li class="progresschapter"><a href="6-bf.html">6</a></li><li class="progresschapter"><a href="7-vn.html">7</a></li><li class="progresschapter"><a href="8-ws.html">8</a></li><li class="progressnext"><a href="4-taa.html">&#10095;</a></li></ul></div>
</nav><!--End of weave-->
</main>
</body>
</html>