1095 lines
130 KiB
HTML
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">§1. </a></li><li><a href="#SP2">§2. Parsing</a></li><li><a href="#SP2_2">§2.2. Structures</a></li><li><a href="#SP2_3">§2.3. Structure dependency</a></li><li><a href="#SP2_4">§2.4. Functions</a></li><li><a href="#SP4">§4. Subcategorisation</a></li><li><a href="#SP5">§5. Tangling extras</a></li><li><a href="#SP6">§6. Tangling predeclarations</a></li><li><a href="#SP7">§7. Overriding regular code weaving</a></li><li><a href="#SP8">§8. Analysis</a></li></ul><hr class="tocbar">
|
|
|
|
<p class="inwebparagraph"><a id="SP1"></a><b>§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">§7.2</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP2"></a><b>§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>
|
|
<<span class="cwebmacro">Find every typedef struct in the tangle</span> <span class="cwebmacronumber">2.2</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Work out which structs contain which others</span> <span class="cwebmacronumber">2.3</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">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">-></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">-></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">-></span><span class="element">category</span><span class="plain"> == </span><span class="constant">CONT_DEFINITION_LCAT</span><span class="plain">)) {</span>
|
|
<<span class="cwebmacro">Look for conditional compilation on this line</span> <span class="cwebmacronumber">2.1</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Look for a function definition on this line</span> <span class="cwebmacronumber">2.4</span>><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"> > </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">§1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP2_1"></a><b>§2.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Look for conditional compilation on this line</span> <span class="cwebmacronumber">2.1</span>> =
|
|
</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">(&</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">-></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">(&</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">-></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"> >= </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">(&</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">-></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">(&</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">-></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"> <= </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">§2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP2_2"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Find every typedef struct in the tangle</span> <span class="cwebmacronumber">2.2</span>> =
|
|
</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">(&</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">-></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>
|
|
<<span class="cwebmacro">Attach a structure to this source line</span> <span class="cwebmacronumber">2.2.2</span>><span class="plain">;</span>
|
|
<span class="functiontext">Tags::add_by_name</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">-></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">-></span><span class="element">text</span><span class="plain">) == </span><span class="character">'}'</span><span class="plain">) && (</span><span class="identifier">current_str</span><span class="plain">)) {</span>
|
|
<span class="identifier">current_str</span><span class="plain">-></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">) && (</span><span class="identifier">current_str</span><span class="plain">-></span><span class="element">typedef_ends</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)) {</span>
|
|
<<span class="cwebmacro">Work through the a line in the structure definition</span> <span class="cwebmacronumber">2.2.3</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">Regexp::match</span><span class="plain">(&</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">-></span><span class="element">text</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"typedef %c+"</span><span class="plain">)) &&</span>
|
|
<span class="plain">(</span><span class="functiontext">Regexp::match</span><span class="plain">(&</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">-></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">-></span><span class="element">owning_paragraph</span><span class="plain">-></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">-></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">(&</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">§2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP2_2_1"></a><b>§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>§2.2.2. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Attach a structure to this source line</span> <span class="cwebmacronumber">2.2.2</span>> =
|
|
</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>
|
|
<<span class="cwebmacro">Initialise the C structure structure</span> <span class="cwebmacronumber">2.2.2.1</span>><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">-></span><span class="element">owning_section</span><span class="plain">, </span><span class="identifier">str</span><span class="plain">-></span><span class="element">structure_name</span><span class="plain">, </span><span class="constant">RESERVED_COLOUR</span><span class="plain">);</span>
|
|
<<span class="cwebmacro">Add this to the lists for its web and its paragraph</span> <span class="cwebmacronumber">2.2.2.2</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Insertion-sort this into the alphabetical list of all structures found</span> <span class="cwebmacronumber">2.2.2.3</span>><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">§2.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP2_2_2_1"></a><b>§2.2.2.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Initialise the C structure structure</span> <span class="cwebmacronumber">2.2.2.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">str</span><span class="plain">-></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">-></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">-></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">-></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">-></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">-></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">§2.2.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP2_2_2_2"></a><b>§2.2.2.2. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Add this to the lists for its web and its paragraph</span> <span class="cwebmacronumber">2.2.2.2</span>> =
|
|
</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">-></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">-></span><span class="element">owning_paragraph</span><span class="plain">-></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">§2.2.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP2_2_2_3"></a><b>§2.2.2.3. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Insertion-sort this into the alphabetical list of all structures found</span> <span class="cwebmacronumber">2.2.2.3</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">str</span><span class="plain">-></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">-></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">-></span><span class="element">structure_name</span><span class="plain">, </span><span class="identifier">seq</span><span class="plain">-></span><span class="element">structure_name</span><span class="plain">) < </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">-></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">-></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">-></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">-></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">§2.2.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP2_2_3"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Work through the a line in the structure definition</span> <span class="cwebmacronumber">2.2.3</span>> =
|
|
</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">-></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>
|
|
<<span class="cwebmacro">Remove C type modifiers from the front of p</span> <span class="cwebmacronumber">2.2.3.1</span>><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>
|
|
<<span class="cwebmacro">Move pos past the type name</span> <span class="cwebmacronumber">2.2.3.2</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Move pos past any typographical type modifiers</span> <span class="cwebmacronumber">2.2.3.3</span>><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>
|
|
<<span class="cwebmacro">Copy the element name into elname</span> <span class="cwebmacronumber">2.2.3.4</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Record the element</span> <span class="cwebmacronumber">2.2.3.6</span>><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">(&</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">§2.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP2_2_3_1"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Remove C type modifiers from the front of p</span> <span class="cwebmacronumber">2.2.3.1</span>> =
|
|
</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">(&</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">§2.2.3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP2_2_3_2"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Move pos past the type name</span> <span class="cwebmacronumber">2.2.3.2</span>> =
|
|
</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">)) && (</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">§2.2.3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP2_2_3_3"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Move pos past any typographical type modifiers</span> <span class="cwebmacronumber">2.2.3.3</span>> =
|
|
</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">§2.2.3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP2_2_3_4"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Copy the element name into elname</span> <span class="cwebmacronumber">2.2.3.4</span>> =
|
|
</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">(&</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">§2.2.3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP2_2_3_5"></a><b>§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>§2.2.3.6. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Record the element</span> <span class="cwebmacronumber">2.2.3.6</span>> =
|
|
</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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">§2.2.3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP2_3"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Work out which structs contain which others</span> <span class="cwebmacronumber">2.3</span>> =
|
|
</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">-></span><span class="element">typedef_begins</span><span class="plain">;</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">current_str</span><span class="plain">-></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">-></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">(&</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">-></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>
|
|
<<span class="cwebmacro">One structure appears to contain a copy of another one</span> <span class="cwebmacronumber">2.3.1</span>><span class="plain">;</span>
|
|
<span class="functiontext">Regexp::dispose_of</span><span class="plain">(&</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">§2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP2_3_1"></a><b>§2.3.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">One structure appears to contain a copy of another one</span> <span class="cwebmacronumber">2.3.1</span>> =
|
|
</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">-></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">) &&</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">-></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">-></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">§2.3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP2_4"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Look for a function definition on this line</span> <span class="cwebmacronumber">2.4</span>> =
|
|
</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">-></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">-></span><span class="element">text</span><span class="plain">);</span>
|
|
<<span class="cwebmacro">Parse past any type modifiers</span> <span class="cwebmacronumber">2.4.1</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">(&</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>
|
|
<<span class="cwebmacro">A function definition was found</span> <span class="cwebmacronumber">2.4.2</span>><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">(&</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">§2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP2_4_1"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Parse past any type modifiers</span> <span class="cwebmacronumber">2.4.1</span>> =
|
|
</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">(&</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">(&</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">§2.4</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP2_4_2"></a><b>§2.4.2. </b><code class="display">
|
|
<<span class="cwebmacrodefn">A function definition was found</span> <span class="cwebmacronumber">2.4.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<<span class="cwebmacro">Soak up further arguments from continuation lines after the declaration</span> <span class="cwebmacronumber">2.4.2.1</span>><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">-></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>
|
|
<<span class="cwebmacro">Initialise the function structure</span> <span class="cwebmacronumber">2.4.2.3</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Add the function to its paragraph and line</span> <span class="cwebmacronumber">2.4.2.4</span>><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">W</span><span class="plain">-></span><span class="element">main_language</span><span class="plain">-></span><span class="element">supports_namespaces</span><span class="plain">)</span>
|
|
<<span class="cwebmacro">Check that the function has its namespace correctly declared</span> <span class="cwebmacronumber">2.4.2.5</span>><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP2_4">§2.4</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP2_4_2_1"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Soak up further arguments from continuation lines after the declaration</span> <span class="cwebmacronumber">2.4.2.1</span>> =
|
|
</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">) && (</span><span class="identifier">arg_lc</span><span class="plain"> <= </span><span class="constant">MAX_ARG_LINES</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">) == -1)) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">AL</span><span class="plain">-></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">-></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">-></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"> >= </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">§2.4.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP2_4_2_2"></a><b>§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>§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">
|
|
<<span class="cwebmacrodefn">Initialise the function structure</span> <span class="cwebmacronumber">2.4.2.3</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">fn</span><span class="plain">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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"><</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">-></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">§2.4.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP2_4_2_4"></a><b>§2.4.2.4. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Add the function to its paragraph and line</span> <span class="cwebmacronumber">2.4.2.4</span>> =
|
|
</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">-></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">-></span><span class="element">functions</span><span class="plain">);</span>
|
|
<span class="identifier">L</span><span class="plain">-></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">§2.4.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP2_4_2_5"></a><b>§2.4.2.5. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Check that the function has its namespace correctly declared</span> <span class="cwebmacronumber">2.4.2.5</span>> =
|
|
</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">(&</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">-></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">)) && (</span><span class="functiontext">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">-></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">-></span><span class="element">sect_namespace</span><span class="plain">)) &&</span>
|
|
<span class="plain">(</span><span class="identifier">L</span><span class="plain">-></span><span class="element">owning_paragraph</span><span class="plain">-></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">-></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">-></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">-></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">(&</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">§2.4.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP3"></a><b>§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">-></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">-></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>§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">(&</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">-></span><span class="element">text</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"#include <(%C+)>%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">-></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">(&</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">§1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP5"></a><b>§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">-></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">-></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">-></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">-></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">§1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP6"></a><b>§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 —
|
|
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>
|
|
<<span class="cwebmacro">Predeclare the structures in a well-founded order</span> <span class="cwebmacronumber">6.2</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Predeclare simple typedefs</span> <span class="cwebmacronumber">6.1</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Predeclare the functions</span> <span class="cwebmacronumber">6.4</span>><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">§1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP6_1"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Predeclare simple typedefs</span> <span class="cwebmacronumber">6.1</span>> =
|
|
</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">-></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">-></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">-></span><span class="element">main_language</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">-></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">-></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">§6</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP6_2"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Predeclare the structures in a well-founded order</span> <span class="cwebmacronumber">6.2</span>> =
|
|
</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">-></span><span class="element">c_structures</span><span class="plain">)</span>
|
|
<span class="identifier">str</span><span class="plain">-></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">-></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">§6</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP6_3"></a><b>§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">-></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">-></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">-></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">-></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">-></span><span class="element">typedef_begins</span><span class="plain">-></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">-></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">-></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">-></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">-></span><span class="element">text</span><span class="plain">);</span>
|
|
<span class="identifier">L</span><span class="plain">-></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">-></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">-></span><span class="element">typedef_begins</span><span class="plain">-></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">§6.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP6_4"></a><b>§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">
|
|
<<span class="cwebmacrodefn">Predeclare the functions</span> <span class="cwebmacronumber">6.4</span>> =
|
|
</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">-></span><span class="element">function_defined</span><span class="plain">) && (</span><span class="identifier">L</span><span class="plain">-></span><span class="identifier">owning_paragraph</span><span class="plain">-></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">-></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"><</span><span class="identifier">fn</span><span class="plain">-></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">(&</span><span class="identifier">mr</span><span class="plain">, </span><span class="identifier">fn</span><span class="plain">-></span><span class="element">within_conditionals</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]-></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">-></span><span class="element">within_conditionals</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]-></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">-></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">-></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">-></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">-></span><span class="element">main_language</span><span class="plain">, </span><span class="identifier">fn</span><span class="plain">-></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">-></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">-></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"><</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">§6</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP7"></a><b>§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>§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">-></span><span class="element">typedef_begins</span><span class="plain">-></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">-></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">-></span><span class="element">function_header_at</span><span class="plain">-></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">-></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">§1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP9"></a><b>§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">-></span><span class="element">function_header_at</span><span class="plain">-></span><span class="element">owning_section</span><span class="plain">,</span>
|
|
<span class="identifier">fn</span><span class="plain">-></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">-></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">-></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">-></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">-></span><span class="element">element_created_at</span><span class="plain">-></span><span class="element">owning_section</span><span class="plain">,</span>
|
|
<span class="identifier">elt</span><span class="plain">-></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">§1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP10"></a><b>§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">-></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">-></span><span class="element">function_header_at</span><span class="plain">-></span><span class="element">owning_section</span><span class="plain">,</span>
|
|
<span class="identifier">fn</span><span class="plain">-></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">-></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">-></span><span class="identifier">form_of_usage</span><span class="plain"> & </span><span class="constant">FCALL_USAGE</span><span class="plain">) || (</span><span class="identifier">fn</span><span class="plain">-></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">-></span><span class="identifier">usage_recorded_at</span><span class="plain">-></span><span class="element">under_section</span><span class="plain"> != </span><span class="identifier">fn</span><span class="plain">-></span><span class="element">function_header_at</span><span class="plain">-></span><span class="element">owning_section</span><span class="plain">)</span>
|
|
<span class="identifier">fn</span><span class="plain">-></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">-></span><span class="element">within_namespace</span><span class="plain"> != </span><span class="identifier">fn</span><span class="plain">-></span><span class="identifier">called_from_other_sections</span><span class="plain">)</span>
|
|
<span class="plain">&& (</span><span class="identifier">check_namespaces</span><span class="plain">)</span>
|
|
<span class="plain">&& (</span><span class="identifier">fn</span><span class="plain">-></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">-></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">-></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">-></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">§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>
|
|
|