inweb-bootstrap/docs/inweb/4-cl.html
2020-04-08 13:03:15 +01:00

1095 lines
130 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>4/tp</title>
<meta name="viewport" content="width=device-width initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="../inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body>
<nav role="navigation">
<h1><a href="../webs.html">Sources</a></h1>
<ul>
<li><a href="../inweb/index.html">inweb</a></li>
</ul>
<h2>Foundation</h2>
<ul>
<li><a href="../foundation-module/index.html">foundation-module</a></li>
<li><a href="../foundation-test/index.html">foundation-test</a></li>
</ul>
</nav>
<main role="main">
<!--Weave of '4/cl' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb</a></li><li><a href="index.html#4">Chapter 4: Languages</a></li><li><b>C-Like Languages</b></li></ul><p class="purpose">To provide special features for the whole C family of languages.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. </a></li><li><a href="#SP2">&#167;2. Parsing</a></li><li><a href="#SP2_2">&#167;2.2. Structures</a></li><li><a href="#SP2_3">&#167;2.3. Structure dependency</a></li><li><a href="#SP2_4">&#167;2.4. Functions</a></li><li><a href="#SP4">&#167;4. Subcategorisation</a></li><li><a href="#SP5">&#167;5. Tangling extras</a></li><li><a href="#SP6">&#167;6. Tangling predeclarations</a></li><li><a href="#SP7">&#167;7. Overriding regular code weaving</a></li><li><a href="#SP8">&#167;8. Analysis</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. </b>What makes a language C-like?
This does:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">CLike::make_c_like</span><span class="plain">(</span><span class="reserved">programming_language</span><span class="plain"> *</span><span class="identifier">pl</span><span class="plain">) {</span>
<span class="identifier">METHOD_ADD</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">, </span><span class="constant">FURTHER_PARSING_PAR_MTID</span><span class="plain">, </span><span class="functiontext">CLike::further_parsing</span><span class="plain">);</span>
<span class="identifier">METHOD_ADD</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">, </span><span class="constant">SUBCATEGORISE_LINE_PAR_MTID</span><span class="plain">, </span><span class="functiontext">CLike::subcategorise_code</span><span class="plain">);</span>
<span class="identifier">METHOD_ADD</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">, </span><span class="constant">ADDITIONAL_EARLY_MATTER_TAN_MTID</span><span class="plain">, </span><span class="functiontext">CLike::additional_early_matter</span><span class="plain">);</span>
<span class="identifier">METHOD_ADD</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">, </span><span class="constant">ADDITIONAL_PREDECLARATIONS_TAN_MTID</span><span class="plain">, </span><span class="functiontext">CLike::additional_predeclarations</span><span class="plain">);</span>
<span class="identifier">METHOD_ADD</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">, </span><span class="constant">CATALOGUE_ANA_MTID</span><span class="plain">, </span><span class="functiontext">CLike::catalogue</span><span class="plain">);</span>
<span class="identifier">METHOD_ADD</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">, </span><span class="constant">EARLY_PREWEAVE_ANALYSIS_ANA_MTID</span><span class="plain">, </span><span class="functiontext">CLike::analyse_code</span><span class="plain">);</span>
<span class="identifier">METHOD_ADD</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">, </span><span class="constant">LATE_PREWEAVE_ANALYSIS_ANA_MTID</span><span class="plain">, </span><span class="functiontext">CLike::post_analysis</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function CLike::make_c_like is used in 4/pl (<a href="4-pl.html#SP7_2">&#167;7.2</a>).</p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. Parsing. </b>After a web has been read in and then parsed, code supporting its language
is then called to do any further parsing it might want to. The code below
is run if the language is "C-like": regular C and InC both qualify.
</p>
<p class="inwebparagraph">In scanning the web, we need to keep track of <code class="display"><span class="extract">#ifdef</span></code> and <code class="display"><span class="extract">#endif</span></code> pairs
in the source. This matters because we will want to predeclare functions;
but if functions are declared in conditional compilation, then their
predeclarations have to be made under the same conditions.
</p>
<p class="inwebparagraph">The following stack holds the current set of conditional compilations which the
source line being scanned lies within.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">MAX_CONDITIONAL_COMPILATION_STACK</span><span class="plain"> </span><span class="constant">8</span>
</pre>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">cc_sp</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">source_line</span><span class="plain"> *</span><span class="identifier">cc_stack</span><span class="plain">[</span><span class="constant">MAX_CONDITIONAL_COMPILATION_STACK</span><span class="plain">];</span>
<span class="reserved">c_structure</span><span class="plain"> *</span><span class="identifier">first_cst_alphabetically</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">CLike::further_parsing</span><span class="plain">(</span><span class="reserved">programming_language</span><span class="plain"> *</span><span class="identifier">self</span><span class="plain">, </span><span class="reserved">web</span><span class="plain"> *</span><span class="identifier">W</span><span class="plain">) {</span>
&lt;<span class="cwebmacro">Find every typedef struct in the tangle</span> <span class="cwebmacronumber">2.2</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Work out which structs contain which others</span> <span class="cwebmacronumber">2.3</span>&gt;<span class="plain">;</span>
<span class="identifier">cc_sp</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">chapter</span><span class="plain"> *</span><span class="identifier">C</span><span class="plain">;</span>
<span class="reserved">section</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">;</span>
<span class="identifier">LOOP_WITHIN_TANGLE</span><span class="plain">(</span><span class="identifier">C</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">, </span><span class="functiontext">Tangler::primary_target</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">))</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">category</span><span class="plain"> == </span><span class="constant">CODE_BODY_LCAT</span><span class="plain">) ||</span>
<span class="plain">(</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">category</span><span class="plain"> == </span><span class="constant">BEGIN_DEFINITION_LCAT</span><span class="plain">) ||</span>
<span class="plain">(</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">category</span><span class="plain"> == </span><span class="constant">CONT_DEFINITION_LCAT</span><span class="plain">)) {</span>
&lt;<span class="cwebmacro">Look for conditional compilation on this line</span> <span class="cwebmacronumber">2.1</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Look for a function definition on this line</span> <span class="cwebmacronumber">2.4</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cc_sp</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">)</span>
<span class="functiontext">Main::error_in_web</span><span class="plain">(</span><span class="identifier">I</span><span class="string">"program ended with conditional compilation open"</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function CLike::further_parsing is used in <a href="#SP1">&#167;1</a>.</p>
<p class="inwebparagraph"><a id="SP2_1"></a><b>&#167;2.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Look for conditional compilation on this line</span> <span class="cwebmacronumber">2.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">match_results</span><span class="plain"> </span><span class="identifier">mr</span><span class="plain"> = </span><span class="functiontext">Regexp::create_mr</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">text</span><span class="plain">, </span><span class="identifier">L</span><span class="string">" *#ifn*def %c+"</span><span class="plain">)) ||</span>
<span class="plain">(</span><span class="functiontext">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">text</span><span class="plain">, </span><span class="identifier">L</span><span class="string">" *#IFN*DEF %c+"</span><span class="plain">))) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cc_sp</span><span class="plain"> &gt;= </span><span class="constant">MAX_CONDITIONAL_COMPILATION_STACK</span><span class="plain">)</span>
<span class="functiontext">Main::error_in_web</span><span class="plain">(</span><span class="identifier">I</span><span class="string">"conditional compilation too deeply nested"</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">);</span>
<span class="reserved">else</span>
<span class="identifier">cc_stack</span><span class="plain">[</span><span class="identifier">cc_sp</span><span class="plain">++] = </span><span class="identifier">L</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">text</span><span class="plain">, </span><span class="identifier">L</span><span class="string">" *#endif *"</span><span class="plain">)) ||</span>
<span class="plain">(</span><span class="functiontext">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">text</span><span class="plain">, </span><span class="identifier">L</span><span class="string">" *#ENDIF *"</span><span class="plain">))) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cc_sp</span><span class="plain"> &lt;= </span><span class="constant">0</span><span class="plain">)</span>
<span class="functiontext">Main::error_in_web</span><span class="plain">(</span><span class="identifier">I</span><span class="string">"found #endif without #ifdef or #ifndef"</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">);</span>
<span class="reserved">else</span>
<span class="identifier">cc_sp</span><span class="plain">--;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP2">&#167;2</a>.</p>
<p class="inwebparagraph"><a id="SP2_2"></a><b>&#167;2.2. Structures. </b>We're going to assume that the C source code uses structures looking
something like this:
</p>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="identifier">fruit</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">pip</span><span class="plain"> </span><span class="identifier">the_pips</span><span class="plain">[5];</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">fruit</span><span class="plain"> *</span><span class="identifier">often_confused_with</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">tree_species</span><span class="plain"> *</span><span class="identifier">grows_on</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">typical_weight</span><span class="plain">;</span>
<span class="plain">} </span><span class="identifier">fruit</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph">which adopts the traditional layout conventions of Kernighan and Ritchie.
The structure definitions in this Inweb web all take the required form,
of course, and provide many more examples.
</p>
<p class="inwebparagraph">Note that a <code class="display"><span class="extract">fruit</span></code> structure contains a <code class="display"><span class="extract">pip</span></code> structure (in fact, five of
them), but only contains pointers to <code class="display"><span class="extract">tree_species</span></code> structures and itself.
C requires therefore that the structure definition for <code class="display"><span class="extract">pip</span></code> must occur
earlier in the code than that for <code class="display"><span class="extract">fruit</span></code>. This is a nuisance, so Inweb
takes care of it automatically.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Find every typedef struct in the tangle</span> <span class="cwebmacronumber">2.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">c_structure</span><span class="plain"> *</span><span class="identifier">current_str</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">chapter</span><span class="plain"> *</span><span class="identifier">C</span><span class="plain">;</span>
<span class="reserved">section</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">;</span>
<span class="identifier">LOOP_WITHIN_TANGLE</span><span class="plain">(</span><span class="identifier">C</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">, </span><span class="functiontext">Tangler::primary_target</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">)) {</span>
<span class="reserved">match_results</span><span class="plain"> </span><span class="identifier">mr</span><span class="plain"> = </span><span class="functiontext">Regexp::create_mr</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">text</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"typedef struct (%i+) %c*{%c*"</span><span class="plain">)) {</span>
&lt;<span class="cwebmacro">Attach a structure to this source line</span> <span class="cwebmacronumber">2.2.2</span>&gt;<span class="plain">;</span>
<span class="functiontext">Tags::add_by_name</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">owning_paragraph</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Structures"</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Str::get_first_char</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">text</span><span class="plain">) == </span><span class="character">'}'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">current_str</span><span class="plain">)) {</span>
<span class="identifier">current_str</span><span class="plain">-&gt;</span><span class="element">typedef_ends</span><span class="plain"> = </span><span class="identifier">L</span><span class="plain">;</span>
<span class="identifier">current_str</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">current_str</span><span class="plain">) &amp;&amp; (</span><span class="identifier">current_str</span><span class="plain">-&gt;</span><span class="element">typedef_ends</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)) {</span>
&lt;<span class="cwebmacro">Work through the a line in the structure definition</span> <span class="cwebmacronumber">2.2.3</span>&gt;<span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">text</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"typedef %c+"</span><span class="plain">)) &amp;&amp;</span>
<span class="plain">(</span><span class="functiontext">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">text</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"%c+##%c+"</span><span class="plain">) == </span><span class="constant">FALSE</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">owning_paragraph</span><span class="plain">-&gt;</span><span class="element">placed_very_early</span><span class="plain"> == </span><span class="constant">FALSE</span><span class="plain">)</span>
<span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">category</span><span class="plain"> = </span><span class="constant">TYPEDEF_LCAT</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="functiontext">Regexp::dispose_of</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP2">&#167;2</a>.</p>
<p class="inwebparagraph"><a id="SP2_2_1"></a><b>&#167;2.2.1. </b>For each <code class="display"><span class="extract">typedef struct</span></code> we find, we will make one of these:
</p>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">c_structure</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">structure_name</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">tangled</span><span class="plain">; </span><span class="comment"> whether the structure definition has been tangled out</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">source_line</span><span class="plain"> *</span><span class="identifier">typedef_begins</span><span class="plain">; </span><span class="comment"> opening line of <code class="display"><span class="extract">typedef</span></code></span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">source_line</span><span class="plain"> *</span><span class="identifier">typedef_ends</span><span class="plain">; </span><span class="comment"> closing line, where <code class="display"><span class="extract">}</span></code> appears</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">linked_list</span><span class="plain"> *</span><span class="identifier">incorporates</span><span class="plain">; </span><span class="comment"> of <code class="display"><span class="extract">c_structure</span></code></span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">linked_list</span><span class="plain"> *</span><span class="identifier">elements</span><span class="plain">; </span><span class="comment"> of <code class="display"><span class="extract">structure_element</span></code></span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">c_structure</span><span class="plain"> *</span><span class="identifier">next_cst_alphabetically</span><span class="plain">;</span>
<span class="constant">MEMORY_MANAGEMENT</span>
<span class="plain">} </span><span class="reserved">c_structure</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure c_structure is accessed in 3/tw and here.</p>
<p class="inwebparagraph"><a id="SP2_2_2"></a><b>&#167;2.2.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Attach a structure to this source line</span> <span class="cwebmacronumber">2.2.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">c_structure</span><span class="plain"> *</span><span class="identifier">str</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">c_structure</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Initialise the C structure structure</span> <span class="cwebmacronumber">2.2.2.1</span>&gt;<span class="plain">;</span>
<span class="functiontext">Analyser::mark_reserved_word_for_section</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">owning_section</span><span class="plain">, </span><span class="identifier">str</span><span class="plain">-&gt;</span><span class="element">structure_name</span><span class="plain">, </span><span class="constant">RESERVED_COLOUR</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Add this to the lists for its web and its paragraph</span> <span class="cwebmacronumber">2.2.2.2</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Insertion-sort this into the alphabetical list of all structures found</span> <span class="cwebmacronumber">2.2.2.3</span>&gt;<span class="plain">;</span>
<span class="identifier">current_str</span><span class="plain"> = </span><span class="identifier">str</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP2_2">&#167;2.2</a>.</p>
<p class="inwebparagraph"><a id="SP2_2_2_1"></a><b>&#167;2.2.2.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Initialise the C structure structure</span> <span class="cwebmacronumber">2.2.2.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">str</span><span class="plain">-&gt;</span><span class="element">structure_name</span><span class="plain"> = </span><span class="functiontext">Str::duplicate</span><span class="plain">(</span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[0]);</span>
<span class="identifier">str</span><span class="plain">-&gt;</span><span class="element">typedef_begins</span><span class="plain"> = </span><span class="identifier">L</span><span class="plain">;</span>
<span class="identifier">str</span><span class="plain">-&gt;</span><span class="element">tangled</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="identifier">str</span><span class="plain">-&gt;</span><span class="element">typedef_ends</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">str</span><span class="plain">-&gt;</span><span class="element">incorporates</span><span class="plain"> = </span><span class="identifier">NEW_LINKED_LIST</span><span class="plain">(</span><span class="reserved">c_structure</span><span class="plain">);</span>
<span class="identifier">str</span><span class="plain">-&gt;</span><span class="element">elements</span><span class="plain"> = </span><span class="identifier">NEW_LINKED_LIST</span><span class="plain">(</span><span class="reserved">structure_element</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP2_2_2">&#167;2.2.2</a>.</p>
<p class="inwebparagraph"><a id="SP2_2_2_2"></a><b>&#167;2.2.2.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Add this to the lists for its web and its paragraph</span> <span class="cwebmacronumber">2.2.2.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">ADD_TO_LINKED_LIST</span><span class="plain">(</span><span class="identifier">str</span><span class="plain">, </span><span class="reserved">c_structure</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">c_structures</span><span class="plain">);</span>
<span class="identifier">ADD_TO_LINKED_LIST</span><span class="plain">(</span><span class="identifier">str</span><span class="plain">, </span><span class="reserved">c_structure</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">owning_paragraph</span><span class="plain">-&gt;</span><span class="element">structures</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP2_2_2">&#167;2.2.2</a>.</p>
<p class="inwebparagraph"><a id="SP2_2_2_3"></a><b>&#167;2.2.2.3. </b><code class="display">
&lt;<span class="cwebmacrodefn">Insertion-sort this into the alphabetical list of all structures found</span> <span class="cwebmacronumber">2.2.2.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">str</span><span class="plain">-&gt;</span><span class="element">next_cst_alphabetically</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">first_cst_alphabetically</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">first_cst_alphabetically</span><span class="plain"> = </span><span class="identifier">str</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">placed</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="reserved">c_structure</span><span class="plain"> *</span><span class="identifier">last</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">c_structure</span><span class="plain"> *</span><span class="identifier">seq</span><span class="plain"> = </span><span class="identifier">first_cst_alphabetically</span><span class="plain">; </span><span class="identifier">seq</span><span class="plain">;</span>
<span class="identifier">seq</span><span class="plain"> = </span><span class="identifier">seq</span><span class="plain">-&gt;</span><span class="identifier">next_cst_alphabetically</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::cmp</span><span class="plain">(</span><span class="identifier">str</span><span class="plain">-&gt;</span><span class="element">structure_name</span><span class="plain">, </span><span class="identifier">seq</span><span class="plain">-&gt;</span><span class="element">structure_name</span><span class="plain">) &lt; </span><span class="constant">0</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">seq</span><span class="plain"> == </span><span class="identifier">first_cst_alphabetically</span><span class="plain">) {</span>
<span class="identifier">str</span><span class="plain">-&gt;</span><span class="element">next_cst_alphabetically</span><span class="plain"> = </span><span class="identifier">first_cst_alphabetically</span><span class="plain">;</span>
<span class="identifier">first_cst_alphabetically</span><span class="plain"> = </span><span class="identifier">str</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">last</span><span class="plain">-&gt;</span><span class="element">next_cst_alphabetically</span><span class="plain"> = </span><span class="identifier">str</span><span class="plain">;</span>
<span class="identifier">str</span><span class="plain">-&gt;</span><span class="element">next_cst_alphabetically</span><span class="plain"> = </span><span class="identifier">seq</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">placed</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">last</span><span class="plain"> = </span><span class="identifier">seq</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">placed</span><span class="plain"> == </span><span class="constant">FALSE</span><span class="plain">) </span><span class="identifier">last</span><span class="plain">-&gt;</span><span class="element">next_cst_alphabetically</span><span class="plain"> = </span><span class="identifier">str</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP2_2_2">&#167;2.2.2</a>.</p>
<p class="inwebparagraph"><a id="SP2_2_3"></a><b>&#167;2.2.3. </b>At this point we're reading a line within the structure's definition; for
the sake of an illustrative example, let's suppose that line is:
</p>
<pre class="display">
<span class="plain">unsigned long long int *val;</span>
</pre>
<p class="inwebparagraph">We need to extract the element name, <code class="display"><span class="extract">val</span></code>, and make a note of it.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Work through the a line in the structure definition</span> <span class="cwebmacronumber">2.2.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
<span class="functiontext">Str::copy</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">text</span><span class="plain">);</span>
<span class="functiontext">Str::trim_white_space</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Remove C type modifiers from the front of p</span> <span class="cwebmacronumber">2.2.3.1</span>&gt;<span class="plain">;</span>
<span class="reserved">string_position</span><span class="plain"> </span><span class="identifier">pos</span><span class="plain"> = </span><span class="functiontext">Str::start</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::get</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">) != </span><span class="character">'/'</span><span class="plain">) { </span><span class="comment"> a slash must introduce a comment here</span>
&lt;<span class="cwebmacro">Move pos past the type name</span> <span class="cwebmacronumber">2.2.3.2</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Move pos past any typographical type modifiers</span> <span class="cwebmacronumber">2.2.3.3</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::in_range</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">)) {</span>
<span class="reserved">match_results</span><span class="plain"> </span><span class="identifier">mr</span><span class="plain"> = </span><span class="functiontext">Regexp::create_mr</span><span class="plain">();</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">elname</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Copy the element name into elname</span> <span class="cwebmacronumber">2.2.3.4</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Record the element</span> <span class="cwebmacronumber">2.2.3.6</span>&gt;<span class="plain">;</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">elname</span><span class="plain">);</span>
<span class="functiontext">Regexp::dispose_of</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP2_2">&#167;2.2</a>.</p>
<p class="inwebparagraph"><a id="SP2_2_3_1"></a><b>&#167;2.2.3.1. </b>The following reduces <code class="display"><span class="extract">unsigned long long int *val;</span></code> to just <code class="display"><span class="extract">int *val;</span></code>.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Remove C type modifiers from the front of p</span> <span class="cwebmacronumber">2.2.3.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">modifier_patterns</span><span class="plain">[] = {</span>
<span class="identifier">L</span><span class="string">"(struct )(%C%c*)"</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"(signed )(%C%c*)"</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"(unsigned )(%C%c*)"</span><span class="plain">,</span>
<span class="identifier">L</span><span class="string">"(short )(%C%c*)"</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"(long )(%C%c*)"</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"(static )(%C%c*)"</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain"> };</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">seek_modifiers</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">seek_modifiers</span><span class="plain">) {</span>
<span class="identifier">seek_modifiers</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">; </span><span class="identifier">modifier_patterns</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]; </span><span class="identifier">i</span><span class="plain">++)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">modifier_patterns</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">])) {</span>
<span class="functiontext">Str::copy</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[1]);</span>
<span class="identifier">seek_modifiers</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP2_2_3">&#167;2.2.3</a>.</p>
<p class="inwebparagraph"><a id="SP2_2_3_2"></a><b>&#167;2.2.3.2. </b>At this point <code class="display"><span class="extract">p</span></code> has been reduced to <code class="display"><span class="extract">int *val;</span></code>, but the following moves
<code class="display"><span class="extract">pos</span></code> to point to the <code class="display"><span class="extract">*</span></code>:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Move pos past the type name</span> <span class="cwebmacronumber">2.2.3.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">while</span><span class="plain"> ((</span><span class="functiontext">Str::get</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">)) &amp;&amp; (</span><span class="functiontext">Characters::is_space_or_tab</span><span class="plain">(</span><span class="functiontext">Str::get</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">)) == </span><span class="constant">FALSE</span><span class="plain">))</span>
<span class="identifier">pos</span><span class="plain"> = </span><span class="functiontext">Str::forward</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP2_2_3">&#167;2.2.3</a>.</p>
<p class="inwebparagraph"><a id="SP2_2_3_3"></a><b>&#167;2.2.3.3. </b>And this moves it past the <code class="display"><span class="extract">*</span></code> to point to the <code class="display"><span class="extract">v</span></code> in <code class="display"><span class="extract">int *val;</span></code>:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Move pos past any typographical type modifiers</span> <span class="cwebmacronumber">2.2.3.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">while</span><span class="plain"> ((</span><span class="functiontext">Characters::is_space_or_tab</span><span class="plain">(</span><span class="functiontext">Str::get</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">))) || (</span><span class="functiontext">Str::get</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">) == </span><span class="character">'*'</span><span class="plain">) ||</span>
<span class="plain">(</span><span class="functiontext">Str::get</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">) == </span><span class="character">'('</span><span class="plain">) || (</span><span class="functiontext">Str::get</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">) == </span><span class="character">')'</span><span class="plain">)) </span><span class="identifier">pos</span><span class="plain"> = </span><span class="functiontext">Str::forward</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP2_2_3">&#167;2.2.3</a>.</p>
<p class="inwebparagraph"><a id="SP2_2_3_4"></a><b>&#167;2.2.3.4. </b>This then first copies the substring <code class="display"><span class="extract">val;</span></code> into <code class="display"><span class="extract">elname</span></code>, then cuts that
down to just the identifier characters at the front, i.e., to <code class="display"><span class="extract">val</span></code>.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Copy the element name into elname</span> <span class="cwebmacronumber">2.2.3.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="functiontext">Str::substr</span><span class="plain">(</span><span class="identifier">elname</span><span class="plain">, </span><span class="identifier">pos</span><span class="plain">, </span><span class="functiontext">Str::end</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">elname</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"(%i+)%c*"</span><span class="plain">)) </span><span class="functiontext">Str::copy</span><span class="plain">(</span><span class="identifier">elname</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[0]);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP2_2_3">&#167;2.2.3</a>.</p>
<p class="inwebparagraph"><a id="SP2_2_3_5"></a><b>&#167;2.2.3.5. </b>Now we create an instance of <code class="display"><span class="extract">structure_element</span></code> to record the existence
of the element <code class="display"><span class="extract">val</span></code>, and add it to the linked list of elements of the
structure being defined.
</p>
<p class="inwebparagraph">In InC, only, certain element names used often in Inform's source code are
given mildly special treatment. This doesn't amount to much. <code class="display"><span class="extract">allow_sharing</span></code>
has no effect on tangling, so it doesn't change the program. It simply
affects the reports in the woven code about where structures are used.
</p>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">structure_element</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">element_name</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">source_line</span><span class="plain"> *</span><span class="identifier">element_created_at</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">allow_sharing</span><span class="plain">;</span>
<span class="constant">MEMORY_MANAGEMENT</span>
<span class="plain">} </span><span class="reserved">structure_element</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure structure_element is accessed in 3/tw and here.</p>
<p class="inwebparagraph"><a id="SP2_2_3_6"></a><b>&#167;2.2.3.6. </b><code class="display">
&lt;<span class="cwebmacrodefn">Record the element</span> <span class="cwebmacronumber">2.2.3.6</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="functiontext">Analyser::mark_reserved_word_for_section</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">owning_section</span><span class="plain">, </span><span class="identifier">elname</span><span class="plain">, </span><span class="constant">ELEMENT_COLOUR</span><span class="plain">);</span>
<span class="reserved">structure_element</span><span class="plain"> *</span><span class="identifier">elt</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">structure_element</span><span class="plain">);</span>
<span class="identifier">elt</span><span class="plain">-&gt;</span><span class="element">element_name</span><span class="plain"> = </span><span class="functiontext">Str::duplicate</span><span class="plain">(</span><span class="identifier">elname</span><span class="plain">);</span>
<span class="identifier">elt</span><span class="plain">-&gt;</span><span class="element">allow_sharing</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="identifier">elt</span><span class="plain">-&gt;</span><span class="element">element_created_at</span><span class="plain"> = </span><span class="identifier">L</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">LanguageMethods::share_element</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">main_language</span><span class="plain">, </span><span class="identifier">elname</span><span class="plain">)) </span><span class="identifier">elt</span><span class="plain">-&gt;</span><span class="element">allow_sharing</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="identifier">ADD_TO_LINKED_LIST</span><span class="plain">(</span><span class="identifier">elt</span><span class="plain">, </span><span class="reserved">structure_element</span><span class="plain">, </span><span class="identifier">current_str</span><span class="plain">-&gt;</span><span class="element">elements</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP2_2_3">&#167;2.2.3</a>.</p>
<p class="inwebparagraph"><a id="SP2_3"></a><b>&#167;2.3. Structure dependency. </b>We say that S depends on T if <code class="display"><span class="extract">struct S</span></code> has an element whose type is
<code class="display"><span class="extract">struct T</span></code>. That matters because if so then <code class="display"><span class="extract">struct T</span></code> has to be defined
before <code class="display"><span class="extract">struct S</span></code> in the tangled output.
</p>
<p class="inwebparagraph">It's important to note that <code class="display"><span class="extract">struct S</span></code> merely having a member of type
<code class="display"><span class="extract">struct *T</span></code> does not create a dependency. In the code below, because <code class="display"><span class="extract">%i</span></code>
matches only identifier characters and <code class="display"><span class="extract">*</span></code> is not one of those, a line like
</p>
<pre class="display">
<span class="plain">struct fruit *often_confused_with;</span>
</pre>
<p class="inwebparagraph">will not trip the switch here.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Work out which structs contain which others</span> <span class="cwebmacronumber">2.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">c_structure</span><span class="plain"> *</span><span class="identifier">current_str</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">current_str</span><span class="plain">, </span><span class="reserved">c_structure</span><span class="plain">) {</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">source_line</span><span class="plain"> *</span><span class="identifier">L</span><span class="plain"> = </span><span class="identifier">current_str</span><span class="plain">-&gt;</span><span class="element">typedef_begins</span><span class="plain">;</span>
<span class="plain">((</span><span class="identifier">L</span><span class="plain">) &amp;&amp; (</span><span class="identifier">L</span><span class="plain"> != </span><span class="identifier">current_str</span><span class="plain">-&gt;</span><span class="element">typedef_ends</span><span class="plain">));</span>
<span class="identifier">L</span><span class="plain"> = </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">next_line</span><span class="plain">) {</span>
<span class="reserved">match_results</span><span class="plain"> </span><span class="identifier">mr</span><span class="plain"> = </span><span class="functiontext">Regexp::create_mr</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">text</span><span class="plain">, </span><span class="identifier">L</span><span class="string">" struct (%i+) %i%c*"</span><span class="plain">))</span>
&lt;<span class="cwebmacro">One structure appears to contain a copy of another one</span> <span class="cwebmacronumber">2.3.1</span>&gt;<span class="plain">;</span>
<span class="functiontext">Regexp::dispose_of</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP2">&#167;2</a>.</p>
<p class="inwebparagraph"><a id="SP2_3_1"></a><b>&#167;2.3.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">One structure appears to contain a copy of another one</span> <span class="cwebmacronumber">2.3.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">used_structure</span><span class="plain"> = </span><span class="identifier">mr</span><span class="plain">.</span><span class="identifier">exp</span><span class="plain">[0];</span>
<span class="reserved">c_structure</span><span class="plain"> *</span><span class="identifier">str</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER_LINKED_LIST</span><span class="plain">(</span><span class="identifier">str</span><span class="plain">, </span><span class="reserved">c_structure</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">c_structures</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">str</span><span class="plain"> != </span><span class="identifier">current_str</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="functiontext">Str::eq</span><span class="plain">(</span><span class="identifier">used_structure</span><span class="plain">, </span><span class="identifier">str</span><span class="plain">-&gt;</span><span class="element">structure_name</span><span class="plain">)))</span>
<span class="identifier">ADD_TO_LINKED_LIST</span><span class="plain">(</span><span class="identifier">str</span><span class="plain">, </span><span class="reserved">c_structure</span><span class="plain">, </span><span class="identifier">current_str</span><span class="plain">-&gt;</span><span class="element">incorporates</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP2_3">&#167;2.3</a>.</p>
<p class="inwebparagraph"><a id="SP2_4"></a><b>&#167;2.4. Functions. </b>Second round: we recognise a C function as being a line which takes the form
</p>
<pre class="display">
<span class="plain">type identifier(args...</span>
</pre>
<p class="inwebparagraph">where we parse <code class="display"><span class="extract">type</span></code> only minimally. In InC (only), the identifier can
contain namespace dividers written <code class="display"><span class="extract">::</span></code>. Function declarations, we will assume,
always begin on column 1 of their source files, and we expect them to take
modern ANSI C style, not the long-deprecated late 1970s C style.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Look for a function definition on this line</span> <span class="cwebmacronumber">2.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (!(</span><span class="functiontext">Characters::is_space_or_tab</span><span class="plain">(</span><span class="functiontext">Str::get_first_char</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">text</span><span class="plain">)))) {</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">qualifiers</span><span class="plain">);</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">modified</span><span class="plain">);</span>
<span class="functiontext">Str::copy</span><span class="plain">(</span><span class="identifier">modified</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">text</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Parse past any type modifiers</span> <span class="cwebmacronumber">2.4.1</span>&gt;<span class="plain">;</span>
<span class="reserved">match_results</span><span class="plain"> </span><span class="identifier">mr</span><span class="plain"> = </span><span class="functiontext">Regexp::create_mr</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">modified</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"(%i+) (%**)(%i+)%((%c*)"</span><span class="plain">)) {</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">ftype</span><span class="plain">); </span><span class="functiontext">Str::copy</span><span class="plain">(</span><span class="identifier">ftype</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[0]);</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">asts</span><span class="plain">); </span><span class="functiontext">Str::copy</span><span class="plain">(</span><span class="identifier">asts</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[1]);</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">fname</span><span class="plain">); </span><span class="functiontext">Str::copy</span><span class="plain">(</span><span class="identifier">fname</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[2]);</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">arguments</span><span class="plain">); </span><span class="functiontext">Str::copy</span><span class="plain">(</span><span class="identifier">arguments</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[3]);</span>
&lt;<span class="cwebmacro">A function definition was found</span> <span class="cwebmacronumber">2.4.2</span>&gt;<span class="plain">;</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">ftype</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">asts</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">fname</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">arguments</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">qualifiers</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">modified</span><span class="plain">);</span>
<span class="functiontext">Regexp::dispose_of</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP2">&#167;2</a>.</p>
<p class="inwebparagraph"><a id="SP2_4_1"></a><b>&#167;2.4.1. </b>C has a whole soup of reserved words applying to types, but most of them
can't apply to the return type of a function. We do, however, iterate so that
forms like <code class="display"><span class="extract">static long long int</span></code> will work.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Parse past any type modifiers</span> <span class="cwebmacronumber">2.4.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">modifier_patterns</span><span class="plain">[] = {</span>
<span class="identifier">L</span><span class="string">"(signed )(%C%c*)"</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"(unsigned )(%C%c*)"</span><span class="plain">,</span>
<span class="identifier">L</span><span class="string">"(short )(%C%c*)"</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"(long )(%C%c*)"</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"(static )(%C%c*)"</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain"> };</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">seek_modifiers</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">seek_modifiers</span><span class="plain">) {</span>
<span class="identifier">seek_modifiers</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="reserved">match_results</span><span class="plain"> </span><span class="identifier">mr</span><span class="plain"> = </span><span class="functiontext">Regexp::create_mr</span><span class="plain">();</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">; </span><span class="identifier">modifier_patterns</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]; </span><span class="identifier">i</span><span class="plain">++)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">modified</span><span class="plain">, </span><span class="identifier">modifier_patterns</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">])) {</span>
<span class="functiontext">Str::concatenate</span><span class="plain">(</span><span class="identifier">qualifiers</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[0]);</span>
<span class="functiontext">Str::copy</span><span class="plain">(</span><span class="identifier">modified</span><span class="plain">, </span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[1]);</span>
<span class="identifier">seek_modifiers</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="functiontext">Regexp::dispose_of</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP2_4">&#167;2.4</a>.</p>
<p class="inwebparagraph"><a id="SP2_4_2"></a><b>&#167;2.4.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">A function definition was found</span> <span class="cwebmacronumber">2.4.2</span>&gt; =
</code></p>
<pre class="displaydefn">
&lt;<span class="cwebmacro">Soak up further arguments from continuation lines after the declaration</span> <span class="cwebmacronumber">2.4.2.1</span>&gt;<span class="plain">;</span>
<span class="functiontext">Analyser::mark_reserved_word_for_section</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">owning_section</span><span class="plain">, </span><span class="identifier">fname</span><span class="plain">, </span><span class="constant">FUNCTION_COLOUR</span><span class="plain">);</span>
<span class="reserved">function</span><span class="plain"> *</span><span class="identifier">fn</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">function</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Initialise the function structure</span> <span class="cwebmacronumber">2.4.2.3</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Add the function to its paragraph and line</span> <span class="cwebmacronumber">2.4.2.4</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">main_language</span><span class="plain">-&gt;</span><span class="element">supports_namespaces</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Check that the function has its namespace correctly declared</span> <span class="cwebmacronumber">2.4.2.5</span>&gt;<span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP2_4">&#167;2.4</a>.</p>
<p class="inwebparagraph"><a id="SP2_4_2_1"></a><b>&#167;2.4.2.1. </b>In some cases the function's declaration runs over several lines:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="identifier">World::Subjects::make_adj_const_domain</span><span class="plain">(</span><span class="identifier">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">,|</span>
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">nc</span><span class="plain">, </span><span class="identifier">property</span><span class="plain"> *</span><span class="identifier">prn</span><span class="plain">) {|</span>
</pre>
<p class="inwebparagraph">Having read the first line, <code class="display"><span class="extract">arguments</span></code> would contain <code class="display"><span class="extract">inference_subject *infs,</span></code>
and would thus be incomplete. We continue across subsequent lines until we
reach an open brace <code class="display"><span class="extract">{</span></code>.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">MAX_ARG_LINES</span><span class="plain"> </span><span class="constant">32</span><span class="plain"> </span><span class="comment"> maximum number of lines over which a function's header can extend</span>
</pre>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Soak up further arguments from continuation lines after the declaration</span> <span class="cwebmacronumber">2.4.2.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">source_line</span><span class="plain"> *</span><span class="identifier">AL</span><span class="plain"> = </span><span class="identifier">L</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">arg_lc</span><span class="plain"> = </span><span class="constant">1</span><span class="plain">;</span>
<span class="reserved">while</span><span class="plain"> ((</span><span class="identifier">AL</span><span class="plain">) &amp;&amp; (</span><span class="identifier">arg_lc</span><span class="plain"> &lt;= </span><span class="constant">MAX_ARG_LINES</span><span class="plain">) &amp;&amp; (</span><span class="functiontext">Regexp::find_open_brace</span><span class="plain">(</span><span class="identifier">arguments</span><span class="plain">) == -1)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">AL</span><span class="plain">-&gt;</span><span class="element">next_line</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) {</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">err_mess</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">err_mess</span><span class="plain">, </span><span class="string">"Function '%S' has a malformed declaration"</span><span class="plain">, </span><span class="identifier">fname</span><span class="plain">);</span>
<span class="functiontext">Main::error_in_web</span><span class="plain">(</span><span class="identifier">err_mess</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">err_mess</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">AL</span><span class="plain"> = </span><span class="identifier">AL</span><span class="plain">-&gt;</span><span class="element">next_line</span><span class="plain">;</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">arguments</span><span class="plain">, </span><span class="string">" %S"</span><span class="plain">, </span><span class="identifier">AL</span><span class="plain">-&gt;</span><span class="element">text</span><span class="plain">);</span>
<span class="identifier">arg_lc</span><span class="plain">++;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">n</span><span class="plain"> = </span><span class="functiontext">Regexp::find_open_brace</span><span class="plain">(</span><span class="identifier">arguments</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">n</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">) </span><span class="functiontext">Str::truncate</span><span class="plain">(</span><span class="identifier">arguments</span><span class="plain">, </span><span class="identifier">n</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP2_4_2">&#167;2.4.2</a>.</p>
<p class="inwebparagraph"><a id="SP2_4_2_2"></a><b>&#167;2.4.2.2. </b>Each function definition found results in one of these structures being made:
</p>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">function</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">function_name</span><span class="plain">; </span><span class="comment"> e.g., <code class="display"><span class="extract">"cultivate"</span></code></span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">function_type</span><span class="plain">; </span><span class="comment"> e.g., <code class="display"><span class="extract">"tree *"</span></code></span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">function_arguments</span><span class="plain">; </span><span class="comment"> e.g., <code class="display"><span class="extract">"int rainfall)"</span></code>: note <code class="display"><span class="extract">)</span></code></span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">source_line</span><span class="plain"> *</span><span class="identifier">function_header_at</span><span class="plain">; </span><span class="comment"> where the first line of the header begins</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">within_namespace</span><span class="plain">; </span><span class="comment"> written using InC namespace dividers</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">called_from_other_sections</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">call_freely</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">no_conditionals</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">source_line</span><span class="plain"> *</span><span class="identifier">within_conditionals</span><span class="plain">[</span><span class="constant">MAX_CONDITIONAL_COMPILATION_STACK</span><span class="plain">];</span>
<span class="constant">MEMORY_MANAGEMENT</span>
<span class="plain">} </span><span class="reserved">function</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure function is accessed in 3/tw and here.</p>
<p class="inwebparagraph"><a id="SP2_4_2_3"></a><b>&#167;2.4.2.3. </b>Note that we take a snapshot of the conditional compilation stack as
part of the function structure. We'll need it when predeclaring the function.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Initialise the function structure</span> <span class="cwebmacronumber">2.4.2.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">fn</span><span class="plain">-&gt;</span><span class="element">function_name</span><span class="plain"> = </span><span class="functiontext">Str::duplicate</span><span class="plain">(</span><span class="identifier">fname</span><span class="plain">);</span>
<span class="identifier">fn</span><span class="plain">-&gt;</span><span class="element">function_arguments</span><span class="plain"> = </span><span class="functiontext">Str::duplicate</span><span class="plain">(</span><span class="identifier">arguments</span><span class="plain">);</span>
<span class="identifier">fn</span><span class="plain">-&gt;</span><span class="element">function_type</span><span class="plain"> = </span><span class="functiontext">Str::new</span><span class="plain">();</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">fn</span><span class="plain">-&gt;</span><span class="element">function_type</span><span class="plain">, </span><span class="string">"%S%S %S"</span><span class="plain">, </span><span class="identifier">qualifiers</span><span class="plain">, </span><span class="identifier">ftype</span><span class="plain">, </span><span class="identifier">asts</span><span class="plain">);</span>
<span class="identifier">fn</span><span class="plain">-&gt;</span><span class="element">within_namespace</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="identifier">fn</span><span class="plain">-&gt;</span><span class="element">called_from_other_sections</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="identifier">fn</span><span class="plain">-&gt;</span><span class="element">call_freely</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">fn</span><span class="plain">-&gt;</span><span class="element">function_name</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"isdigit"</span><span class="plain">)) </span><span class="identifier">fn</span><span class="plain">-&gt;</span><span class="element">call_freely</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="identifier">fn</span><span class="plain">-&gt;</span><span class="element">function_header_at</span><span class="plain"> = </span><span class="identifier">L</span><span class="plain">;</span>
<span class="identifier">fn</span><span class="plain">-&gt;</span><span class="element">no_conditionals</span><span class="plain"> = </span><span class="identifier">cc_sp</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">cc_sp</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) </span><span class="identifier">fn</span><span class="plain">-&gt;</span><span class="element">within_conditionals</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = </span><span class="identifier">cc_stack</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">];</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP2_4_2">&#167;2.4.2</a>.</p>
<p class="inwebparagraph"><a id="SP2_4_2_4"></a><b>&#167;2.4.2.4. </b><code class="display">
&lt;<span class="cwebmacrodefn">Add the function to its paragraph and line</span> <span class="cwebmacronumber">2.4.2.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">paragraph</span><span class="plain"> *</span><span class="identifier">P</span><span class="plain"> = </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">owning_paragraph</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">P</span><span class="plain">) </span><span class="identifier">ADD_TO_LINKED_LIST</span><span class="plain">(</span><span class="identifier">fn</span><span class="plain">, </span><span class="reserved">function</span><span class="plain">, </span><span class="identifier">P</span><span class="plain">-&gt;</span><span class="element">functions</span><span class="plain">);</span>
<span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">function_defined</span><span class="plain"> = </span><span class="identifier">fn</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP2_4_2">&#167;2.4.2</a>.</p>
<p class="inwebparagraph"><a id="SP2_4_2_5"></a><b>&#167;2.4.2.5. </b><code class="display">
&lt;<span class="cwebmacrodefn">Check that the function has its namespace correctly declared</span> <span class="cwebmacronumber">2.4.2.5</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">declared_namespace</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">match_results</span><span class="plain"> </span><span class="identifier">mr</span><span class="plain"> = </span><span class="functiontext">Regexp::create_mr</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">fname</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"(%c+::)%c*"</span><span class="plain">)) {</span>
<span class="identifier">declared_namespace</span><span class="plain"> = </span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[0];</span>
<span class="identifier">fn</span><span class="plain">-&gt;</span><span class="element">within_namespace</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">fname</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"main"</span><span class="plain">)) &amp;&amp; (</span><span class="functiontext">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">sect_namespace</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"Main::"</span><span class="plain">)))</span>
<span class="identifier">declared_namespace</span><span class="plain"> = </span><span class="identifier">I</span><span class="string">"Main::"</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Str::ne</span><span class="plain">(</span><span class="identifier">declared_namespace</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">sect_namespace</span><span class="plain">)) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">owning_paragraph</span><span class="plain">-&gt;</span><span class="element">placed_very_early</span><span class="plain"> == </span><span class="constant">FALSE</span><span class="plain">)) {</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">err_mess</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">declared_namespace</span><span class="plain">) == </span><span class="constant">0</span><span class="plain">)</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">err_mess</span><span class="plain">, </span><span class="string">"Function '%S' should have namespace prefix '%S'"</span><span class="plain">,</span>
<span class="identifier">fname</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">-&gt;</span><span class="identifier">sect_namespace</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">-&gt;</span><span class="element">sect_namespace</span><span class="plain">) == </span><span class="constant">0</span><span class="plain">)</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">err_mess</span><span class="plain">, </span><span class="string">"Function '%S' declared in a section with no namespace"</span><span class="plain">,</span>
<span class="identifier">fname</span><span class="plain">);</span>
<span class="reserved">else</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">err_mess</span><span class="plain">, </span><span class="string">"Function '%S' declared in a section with the wrong namespace '%S'"</span><span class="plain">,</span>
<span class="identifier">fname</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">-&gt;</span><span class="identifier">sect_namespace</span><span class="plain">);</span>
<span class="functiontext">Main::error_in_web</span><span class="plain">(</span><span class="identifier">err_mess</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">err_mess</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="functiontext">Regexp::dispose_of</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP2_4_2">&#167;2.4.2</a>.</p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>The following
</p>
<pre class="display">
<span class="reserved">c_structure</span><span class="plain"> *</span><span class="functiontext">CLike::find_structure</span><span class="plain">(</span><span class="reserved">web</span><span class="plain"> *</span><span class="identifier">W</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">name</span><span class="plain">) {</span>
<span class="reserved">c_structure</span><span class="plain"> *</span><span class="identifier">str</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER_LINKED_LIST</span><span class="plain">(</span><span class="identifier">str</span><span class="plain">, </span><span class="reserved">c_structure</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">c_structures</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::eq</span><span class="plain">(</span><span class="identifier">name</span><span class="plain">, </span><span class="identifier">str</span><span class="plain">-&gt;</span><span class="element">structure_name</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">str</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function CLike::find_structure appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. Subcategorisation. </b>The following is called after the parser gives every line in the web a
category; we can, if we wish, change that for a more exotic one. We simply
look for a <code class="display"><span class="extract">#include</span></code> of one of the ANSI C standard libraries.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">CLike::subcategorise_code</span><span class="plain">(</span><span class="reserved">programming_language</span><span class="plain"> *</span><span class="identifier">self</span><span class="plain">, </span><span class="reserved">source_line</span><span class="plain"> *</span><span class="identifier">L</span><span class="plain">) {</span>
<span class="reserved">match_results</span><span class="plain"> </span><span class="identifier">mr</span><span class="plain"> = </span><span class="functiontext">Regexp::create_mr</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">text</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"#include &lt;(%C+)&gt;%c*"</span><span class="plain">)) {</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">library_file</span><span class="plain"> = </span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[0];</span>
<span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">ansi_libs</span><span class="plain">[] = {</span>
<span class="identifier">L</span><span class="string">"assert.h"</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"ctype.h"</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"errno.h"</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"float.h"</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"limits.h"</span><span class="plain">,</span>
<span class="identifier">L</span><span class="string">"locale.h"</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"math.h"</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"setjmp.h"</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"signal.h"</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"stdarg.h"</span><span class="plain">,</span>
<span class="identifier">L</span><span class="string">"stddef.h"</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"stdio.h"</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"stdlib.h"</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"string.h"</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"time.h"</span><span class="plain">,</span>
<span class="identifier">NULL</span>
<span class="plain">};</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">j</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">; </span><span class="identifier">ansi_libs</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">]; </span><span class="identifier">j</span><span class="plain">++)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">library_file</span><span class="plain">, </span><span class="identifier">ansi_libs</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">]))</span>
<span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">category</span><span class="plain"> = </span><span class="constant">C_LIBRARY_INCLUDE_LCAT</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="functiontext">Regexp::dispose_of</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function CLike::subcategorise_code is used in <a href="#SP1">&#167;1</a>.</p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. Tangling extras. </b>"Additional early matter" is used for the inclusions of the ANSI library
files. We need to do that early, because otherwise types declared in them
(such as <code class="display"><span class="extract">FILE</span></code>) won't exist in time for the structure definitions we will
be tangling next.
</p>
<p class="inwebparagraph">It might seem reasonable to move all <code class="display"><span class="extract">#include</span></code> files up front this way,
not just the ANSI ones. But that would defeat any conditional compilation
around the inclusions; which Inform (for instance) needs in order to make
platform-specific details to handle directories without POSIX in Windows.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">CLike::additional_early_matter</span><span class="plain">(</span><span class="reserved">programming_language</span><span class="plain"> *</span><span class="identifier">self</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">OUT</span><span class="plain">, </span><span class="reserved">web</span><span class="plain"> *</span><span class="identifier">W</span><span class="plain">, </span><span class="reserved">tangle_target</span><span class="plain"> *</span><span class="identifier">target</span><span class="plain">) {</span>
<span class="reserved">chapter</span><span class="plain"> *</span><span class="identifier">C</span><span class="plain">;</span>
<span class="reserved">section</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">;</span>
<span class="identifier">LOOP_WITHIN_TANGLE</span><span class="plain">(</span><span class="identifier">C</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">target</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">category</span><span class="plain"> == </span><span class="constant">C_LIBRARY_INCLUDE_LCAT</span><span class="plain">) {</span>
<span class="functiontext">Tags::open_ifdefs</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">owning_paragraph</span><span class="plain">);</span>
<span class="functiontext">Tangler::tangle_code</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">text</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\n"</span><span class="plain">);</span>
<span class="functiontext">Tags::close_ifdefs</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">owning_paragraph</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function CLike::additional_early_matter is used in <a href="#SP1">&#167;1</a>.</p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. Tangling predeclarations. </b>This is where a language gets the chance to tangle predeclarations, early
on in the file. We use it first for the structures, and then the functions &mdash;
in that order since the function types likely involve the typedef names for the
structures.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">CLike::additional_predeclarations</span><span class="plain">(</span><span class="reserved">programming_language</span><span class="plain"> *</span><span class="identifier">self</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">OUT</span><span class="plain">, </span><span class="reserved">web</span><span class="plain"> *</span><span class="identifier">W</span><span class="plain">) {</span>
&lt;<span class="cwebmacro">Predeclare the structures in a well-founded order</span> <span class="cwebmacronumber">6.2</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Predeclare simple typedefs</span> <span class="cwebmacronumber">6.1</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Predeclare the functions</span> <span class="cwebmacronumber">6.4</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function CLike::additional_predeclarations is used in <a href="#SP1">&#167;1</a>.</p>
<p class="inwebparagraph"><a id="SP6_1"></a><b>&#167;6.1. </b>A "simple typedef" here means one that is aliasing something other than
a structure: for example <code class="display"><span class="extract">typedef unsigned int uint;</span></code> would be a simple typedef.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Predeclare simple typedefs</span> <span class="cwebmacronumber">6.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">chapter</span><span class="plain"> *</span><span class="identifier">C</span><span class="plain">;</span>
<span class="reserved">section</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">;</span>
<span class="identifier">LOOP_WITHIN_TANGLE</span><span class="plain">(</span><span class="identifier">C</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">, </span><span class="functiontext">Tangler::primary_target</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">))</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">category</span><span class="plain"> == </span><span class="constant">TYPEDEF_LCAT</span><span class="plain">) {</span>
<span class="functiontext">Tags::open_ifdefs</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">owning_paragraph</span><span class="plain">);</span>
<span class="functiontext">LanguageMethods::tangle_code</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">main_language</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">text</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\n"</span><span class="plain">);</span>
<span class="functiontext">Tags::close_ifdefs</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">owning_paragraph</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP6">&#167;6</a>.</p>
<p class="inwebparagraph"><a id="SP6_2"></a><b>&#167;6.2. </b>It's easy enough to make sure structures are tangled so that inner ones
precede outer, but we need to be careful to be terminating if the source
code we're given is not well founded because of an error by its programmer:
for example, that structure A contains B contains C contains A. We do this
with the <code class="display"><span class="extract">tangled</span></code> flag, which is <code class="display"><span class="extract">FALSE</span></code> if a structure hasn't been
started yet, <code class="display"><span class="extract">NOT_APPLICABLE</span></code> if it's in progress, and <code class="display"><span class="extract">TRUE</span></code> if it's
finished.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Predeclare the structures in a well-founded order</span> <span class="cwebmacronumber">6.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">c_structure</span><span class="plain"> *</span><span class="identifier">str</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER_LINKED_LIST</span><span class="plain">(</span><span class="identifier">str</span><span class="plain">, </span><span class="reserved">c_structure</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">c_structures</span><span class="plain">)</span>
<span class="identifier">str</span><span class="plain">-&gt;</span><span class="element">tangled</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER_LINKED_LIST</span><span class="plain">(</span><span class="identifier">str</span><span class="plain">, </span><span class="reserved">c_structure</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">c_structures</span><span class="plain">)</span>
<span class="functiontext">CLike::tangle_structure</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">self</span><span class="plain">, </span><span class="identifier">str</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP6">&#167;6</a>.</p>
<p class="inwebparagraph"><a id="SP6_3"></a><b>&#167;6.3. </b>Using the following recursion, which is therefore terminating:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">CLike::tangle_structure</span><span class="plain">(</span><span class="constant">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">programming_language</span><span class="plain"> *</span><span class="identifier">self</span><span class="plain">, </span><span class="reserved">c_structure</span><span class="plain"> *</span><span class="identifier">str</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">str</span><span class="plain">-&gt;</span><span class="element">tangled</span><span class="plain"> != </span><span class="constant">FALSE</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
<span class="identifier">str</span><span class="plain">-&gt;</span><span class="element">tangled</span><span class="plain"> = </span><span class="constant">NOT_APPLICABLE</span><span class="plain">;</span>
<span class="reserved">c_structure</span><span class="plain"> *</span><span class="identifier">embodied</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER_LINKED_LIST</span><span class="plain">(</span><span class="identifier">embodied</span><span class="plain">, </span><span class="reserved">c_structure</span><span class="plain">, </span><span class="identifier">str</span><span class="plain">-&gt;</span><span class="element">incorporates</span><span class="plain">)</span>
<span class="functiontext">CLike::tangle_structure</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">self</span><span class="plain">, </span><span class="identifier">embodied</span><span class="plain">);</span>
<span class="identifier">str</span><span class="plain">-&gt;</span><span class="element">tangled</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="functiontext">Tags::open_ifdefs</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">str</span><span class="plain">-&gt;</span><span class="element">typedef_begins</span><span class="plain">-&gt;</span><span class="element">owning_paragraph</span><span class="plain">);</span>
<span class="functiontext">LanguageMethods::insert_line_marker</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">self</span><span class="plain">, </span><span class="identifier">str</span><span class="plain">-&gt;</span><span class="element">typedef_begins</span><span class="plain">);</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">source_line</span><span class="plain"> *</span><span class="identifier">L</span><span class="plain"> = </span><span class="identifier">str</span><span class="plain">-&gt;</span><span class="element">typedef_begins</span><span class="plain">; </span><span class="identifier">L</span><span class="plain">; </span><span class="identifier">L</span><span class="plain"> = </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">next_line</span><span class="plain">) {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%S\n"</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">text</span><span class="plain">);</span>
<span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">suppress_tangling</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">L</span><span class="plain"> == </span><span class="identifier">str</span><span class="plain">-&gt;</span><span class="element">typedef_ends</span><span class="plain">) </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="functiontext">Tags::close_ifdefs</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">str</span><span class="plain">-&gt;</span><span class="element">typedef_begins</span><span class="plain">-&gt;</span><span class="element">owning_paragraph</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function CLike::tangle_structure is used in <a href="#SP6_2">&#167;6.2</a>.</p>
<p class="inwebparagraph"><a id="SP6_4"></a><b>&#167;6.4. </b>Functions are rather easier to deal with. In general, if a function was
defined within some number of nested <code class="display"><span class="extract">#ifdef</span></code> or <code class="display"><span class="extract">#ifndef</span></code> directives, then
we reproduce those around the predeclaration: except, as a special trick,
if the line contains a particular comment. For example:
</p>
<pre class="display">
<span class="plain">#ifdef SOLARIS /* inweb: always predeclare */</span>
</pre>
<p class="inwebparagraph">That exempts any functions inside this condition from meeting the condition
in order to be predeclared. It's a trick used in the foundation module just
a couple of times: the idea is that although a definition of the functions
is given which only works under SOLARIS, an external piece of code will
provide alternative function definitions which would work without SOLARIS.
The functions therefore need predeclaration regardless, because they will
exist either way.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Predeclare the functions</span> <span class="cwebmacronumber">6.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">chapter</span><span class="plain"> *</span><span class="identifier">C</span><span class="plain">;</span>
<span class="reserved">section</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">;</span>
<span class="identifier">LOOP_WITHIN_TANGLE</span><span class="plain">(</span><span class="identifier">C</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">, </span><span class="functiontext">Tangler::primary_target</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">))</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">function_defined</span><span class="plain">) &amp;&amp; (</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="identifier">owning_paragraph</span><span class="plain">-&gt;</span><span class="element">placed_very_early</span><span class="plain"> == </span><span class="constant">FALSE</span><span class="plain">)) {</span>
<span class="reserved">function</span><span class="plain"> *</span><span class="identifier">fn</span><span class="plain"> = </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">function_defined</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">to_close</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">fn</span><span class="plain">-&gt;</span><span class="element">no_conditionals</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="reserved">match_results</span><span class="plain"> </span><span class="identifier">mr</span><span class="plain"> = </span><span class="functiontext">Regexp::create_mr</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (!(</span><span class="functiontext">Regexp::match</span><span class="plain">(&amp;</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">fn</span><span class="plain">-&gt;</span><span class="element">within_conditionals</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]-&gt;</span><span class="element">text</span><span class="plain">,</span>
<span class="identifier">L</span><span class="string">"%c*inweb: always predeclare%c*"</span><span class="plain">))) {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%S\n"</span><span class="plain">, </span><span class="identifier">fn</span><span class="plain">-&gt;</span><span class="element">within_conditionals</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]-&gt;</span><span class="element">text</span><span class="plain">);</span>
<span class="identifier">to_close</span><span class="plain">++;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="functiontext">Tags::open_ifdefs</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">owning_paragraph</span><span class="plain">);</span>
<span class="functiontext">LanguageMethods::insert_line_marker</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">main_language</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%S "</span><span class="plain">, </span><span class="identifier">fn</span><span class="plain">-&gt;</span><span class="element">function_type</span><span class="plain">);</span>
<span class="functiontext">LanguageMethods::tangle_code</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">main_language</span><span class="plain">, </span><span class="identifier">fn</span><span class="plain">-&gt;</span><span class="element">function_name</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"(%S;\n"</span><span class="plain">, </span><span class="identifier">fn</span><span class="plain">-&gt;</span><span class="element">function_arguments</span><span class="plain">);</span>
<span class="functiontext">Tags::close_ifdefs</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">owning_paragraph</span><span class="plain">);</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">to_close</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"#endif\n"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP6">&#167;6</a>.</p>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. Overriding regular code weaving. </b>We have the opportunity here to sidestep the regular weaving algorithm, and do
our own thing. We decline.
</p>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. Analysis. </b>This implements the additional information in the <code class="display"><span class="extract">-structures</span></code> and <code class="display"><span class="extract">-functions</span></code>
fprms of section catalogue.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">CLike::catalogue</span><span class="plain">(</span><span class="reserved">programming_language</span><span class="plain"> *</span><span class="identifier">self</span><span class="plain">, </span><span class="reserved">section</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">functions_too</span><span class="plain">) {</span>
<span class="reserved">c_structure</span><span class="plain"> *</span><span class="identifier">str</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">str</span><span class="plain">, </span><span class="reserved">c_structure</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">str</span><span class="plain">-&gt;</span><span class="element">typedef_begins</span><span class="plain">-&gt;</span><span class="element">owning_section</span><span class="plain"> == </span><span class="identifier">S</span><span class="plain">)</span>
<span class="identifier">PRINT</span><span class="plain">(</span><span class="string">" %S "</span><span class="plain">, </span><span class="identifier">str</span><span class="plain">-&gt;</span><span class="element">structure_name</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">functions_too</span><span class="plain">) {</span>
<span class="reserved">function</span><span class="plain"> *</span><span class="identifier">fn</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">fn</span><span class="plain">, </span><span class="reserved">function</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fn</span><span class="plain">-&gt;</span><span class="element">function_header_at</span><span class="plain">-&gt;</span><span class="element">owning_section</span><span class="plain"> == </span><span class="identifier">S</span><span class="plain">)</span>
<span class="identifier">PRINT</span><span class="plain">(</span><span class="string">"\n %S"</span><span class="plain">, </span><span class="identifier">fn</span><span class="plain">-&gt;</span><span class="element">function_name</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function CLike::catalogue is used in <a href="#SP1">&#167;1</a>.</p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. </b>Having found all those functions and structure elements, we make sure they
are all known to Inweb's hash table of interesting identifiers:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">CLike::analyse_code</span><span class="plain">(</span><span class="reserved">programming_language</span><span class="plain"> *</span><span class="identifier">self</span><span class="plain">, </span><span class="reserved">web</span><span class="plain"> *</span><span class="identifier">W</span><span class="plain">) {</span>
<span class="reserved">function</span><span class="plain"> *</span><span class="identifier">fn</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">fn</span><span class="plain">, </span><span class="reserved">function</span><span class="plain">)</span>
<span class="functiontext">Analyser::find_hash_entry_for_section</span><span class="plain">(</span><span class="identifier">fn</span><span class="plain">-&gt;</span><span class="element">function_header_at</span><span class="plain">-&gt;</span><span class="element">owning_section</span><span class="plain">,</span>
<span class="identifier">fn</span><span class="plain">-&gt;</span><span class="element">function_name</span><span class="plain">, </span><span class="constant">TRUE</span><span class="plain">);</span>
<span class="reserved">c_structure</span><span class="plain"> *</span><span class="identifier">str</span><span class="plain">;</span>
<span class="reserved">structure_element</span><span class="plain"> *</span><span class="identifier">elt</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER_LINKED_LIST</span><span class="plain">(</span><span class="identifier">str</span><span class="plain">, </span><span class="reserved">c_structure</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">c_structures</span><span class="plain">)</span>
<span class="identifier">LOOP_OVER_LINKED_LIST</span><span class="plain">(</span><span class="identifier">elt</span><span class="plain">, </span><span class="reserved">structure_element</span><span class="plain">, </span><span class="identifier">str</span><span class="plain">-&gt;</span><span class="element">elements</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">elt</span><span class="plain">-&gt;</span><span class="element">allow_sharing</span><span class="plain"> == </span><span class="constant">FALSE</span><span class="plain">)</span>
<span class="functiontext">Analyser::find_hash_entry_for_section</span><span class="plain">(</span><span class="identifier">elt</span><span class="plain">-&gt;</span><span class="element">element_created_at</span><span class="plain">-&gt;</span><span class="element">owning_section</span><span class="plain">,</span>
<span class="identifier">elt</span><span class="plain">-&gt;</span><span class="element">element_name</span><span class="plain">, </span><span class="constant">TRUE</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function CLike::analyse_code is used in <a href="#SP1">&#167;1</a>.</p>
<p class="inwebparagraph"><a id="SP10"></a><b>&#167;10. </b>The following is an opportunity for us to scold the author for any
specifically C-like errors. We're going to look for functions named
<code class="display"><span class="extract">Whatever::name()</span></code> whose definitions are not in the <code class="display"><span class="extract">Whatever::</span></code> section;
in other words, we police the rule that functions actually are defined in the
namespace which their names imply. This can be turned off with a special
bibliographic variable, but don't do that.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">CLike::post_analysis</span><span class="plain">(</span><span class="reserved">programming_language</span><span class="plain"> *</span><span class="identifier">self</span><span class="plain">, </span><span class="reserved">web</span><span class="plain"> *</span><span class="identifier">W</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">check_namespaces</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::eq_wide_string</span><span class="plain">(</span><span class="functiontext">Bibliographic::get_datum</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">-&gt;</span><span class="element">md</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Namespaces"</span><span class="plain">), </span><span class="identifier">L</span><span class="string">"On"</span><span class="plain">)) </span><span class="identifier">check_namespaces</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">function</span><span class="plain"> *</span><span class="identifier">fn</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">fn</span><span class="plain">, </span><span class="reserved">function</span><span class="plain">) {</span>
<span class="reserved">hash_table_entry</span><span class="plain"> *</span><span class="identifier">hte</span><span class="plain"> =</span>
<span class="functiontext">Analyser::find_hash_entry_for_section</span><span class="plain">(</span><span class="identifier">fn</span><span class="plain">-&gt;</span><span class="element">function_header_at</span><span class="plain">-&gt;</span><span class="element">owning_section</span><span class="plain">,</span>
<span class="identifier">fn</span><span class="plain">-&gt;</span><span class="element">function_name</span><span class="plain">, </span><span class="constant">FALSE</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">hte</span><span class="plain">) {</span>
<span class="reserved">hash_table_entry_usage</span><span class="plain"> *</span><span class="identifier">hteu</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER_LINKED_LIST</span><span class="plain">(</span><span class="identifier">hteu</span><span class="plain">, </span><span class="reserved">hash_table_entry_usage</span><span class="plain">, </span><span class="identifier">hte</span><span class="plain">-&gt;</span><span class="element">usages</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">hteu</span><span class="plain">-&gt;</span><span class="identifier">form_of_usage</span><span class="plain"> &amp; </span><span class="constant">FCALL_USAGE</span><span class="plain">) || (</span><span class="identifier">fn</span><span class="plain">-&gt;</span><span class="element">within_namespace</span><span class="plain">))</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">hteu</span><span class="plain">-&gt;</span><span class="identifier">usage_recorded_at</span><span class="plain">-&gt;</span><span class="element">under_section</span><span class="plain"> != </span><span class="identifier">fn</span><span class="plain">-&gt;</span><span class="element">function_header_at</span><span class="plain">-&gt;</span><span class="element">owning_section</span><span class="plain">)</span>
<span class="identifier">fn</span><span class="plain">-&gt;</span><span class="element">called_from_other_sections</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">fn</span><span class="plain">-&gt;</span><span class="element">within_namespace</span><span class="plain"> != </span><span class="identifier">fn</span><span class="plain">-&gt;</span><span class="identifier">called_from_other_sections</span><span class="plain">)</span>
<span class="plain">&amp;&amp; (</span><span class="identifier">check_namespaces</span><span class="plain">)</span>
<span class="plain">&amp;&amp; (</span><span class="identifier">fn</span><span class="plain">-&gt;</span><span class="element">call_freely</span><span class="plain"> == </span><span class="constant">FALSE</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">fn</span><span class="plain">-&gt;</span><span class="element">within_namespace</span><span class="plain">)</span>
<span class="functiontext">Main::error_in_web</span><span class="plain">(</span>
<span class="identifier">I</span><span class="string">"Being internally called, this function mustn't belong to a :: namespace"</span><span class="plain">,</span>
<span class="identifier">fn</span><span class="plain">-&gt;</span><span class="element">function_header_at</span><span class="plain">);</span>
<span class="reserved">else</span>
<span class="functiontext">Main::error_in_web</span><span class="plain">(</span>
<span class="identifier">I</span><span class="string">"Being externally called, this function must belong to a :: namespace"</span><span class="plain">,</span>
<span class="identifier">fn</span><span class="plain">-&gt;</span><span class="element">function_header_at</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function CLike::post_analysis is used in <a href="#SP1">&#167;1</a>.</p>
<hr class="tocbar">
<ul class="toc"><li><a href="4-tp.html">Back to 'The Painter'</a></li><li><a href="4-is.html">Continue with 'InC Support'</a></li></ul><hr class="tocbar">
<!--End of weave-->
</main>
</body>
</html>