1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-06-30 22:14:58 +03:00
inform7/docs/core-module/3-pm.html
2022-04-28 17:37:28 +01:00

303 lines
42 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Plugin Manager</title>
<link href="../docs-assets/Breadcrumbs.css" rel="stylesheet" rev="stylesheet" type="text/css">
<meta name="viewport" content="width=device-width initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="../docs-assets/Contents.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Progress.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Navigation.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Fonts.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Base.css" rel="stylesheet" rev="stylesheet" type="text/css">
<script>
function togglePopup(material_id) {
var popup = document.getElementById(material_id);
popup.classList.toggle("show");
}
</script>
<link href="../docs-assets/Popups.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Colours.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Preform-Colours.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body class="commentary-font">
<nav role="navigation">
<h1><a href="../index.html">
<img src="../docs-assets/Inform.png" height=72">
</a></h1>
<ul><li><a href="../index.html">home</a></li>
</ul><h2>Compiler</h2><ul>
<li><a href="../structure.html">structure</a></li>
<li><a href="../inbuildn.html">inbuild</a></li>
<li><a href="../inform7n.html">inform7</a></li>
<li><a href="../intern.html">inter</a></li>
<li><a href="../services.html">services</a></li>
<li><a href="../secrets.html">secrets</a></li>
</ul><h2>Other Tools</h2><ul>
<li><a href="../inblorbn.html">inblorb</a></li>
<li><a href="../indocn.html">indoc</a></li>
<li><a href="../inform6.html">inform6</a></li>
<li><a href="../inpolicyn.html">inpolicy</a></li>
<li><a href="../inrtpsn.html">inrtps</a></li>
</ul><h2>Resources</h2><ul>
<li><a href="../extensions.html">extensions</a></li>
<li><a href="../kits.html">kits</a></li>
</ul><h2>Repository</h2><ul>
<li><a href="https://github.com/ganelson/inform"><img src="../docs-assets/github.png" height=18> github</a></li>
</ul><h2>Related Projects</h2><ul>
<li><a href="../../../inweb/index.html">inweb</a></li>
<li><a href="../../../intest/index.html">intest</a></li>
</ul>
</nav>
<main role="main">
<!--Weave of 'Plugin Manager' generated by Inweb-->
<div class="breadcrumbs">
<ul class="crumbs"><li><a href="../index.html">Home</a></li><li><a href="../inform7n.html">Inform7</a></li><li><a href="index.html">core</a></li><li><a href="index.html#3">Chapter 3: Plugins</a></li><li><b>Plugin Manager</b></li></ul></div>
<p class="purpose">Creating, activating or deactivating plugins.</p>
<p class="commentary firstcommentary"><a id="SP1" class="paragraph-anchor"></a><b>&#167;1. </b>Plugins are optional extras for the Inform compiler: additions which can be
active or inactive on any given compilation run.
</p>
<p class="commentary">Except for one not-really-a-plugin called "core", each plugin is a piece of
functionality that can be "activated" or "deactivated". Plugins have an
ability to tweak or extend what the compiler does, giving it, for example,
an ability to reason about spatial relationships when the compiler is being
used for interactive fiction; or not, when it isn't.
</p>
<p class="commentary">There is no harm in this hard-wired maximum, since plugins are not things an
author can create in source text; we know exactly how many there are.
</p>
<pre class="definitions code-font"><span class="definition-keyword">define</span> <span class="constant-syntax">MAX_PLUGINS</span><span class="plain-syntax"> </span><span class="constant-syntax">32</span>
</pre>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">typedef</span><span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">plugin</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="identifier-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">textual_name</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">wording_name</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">plugin</span><span class="plain-syntax"> *</span><span class="identifier-syntax">parent_plugin</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">void</span><span class="plain-syntax"> (*</span><span class="identifier-syntax">activation_function</span><span class="plain-syntax">)(</span><span class="reserved-syntax">void</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">active</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">permanently_active</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">CLASS_DEFINITION</span>
<span class="plain-syntax">} </span><span class="reserved-syntax">plugin</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">plugin</span><span class="plain-syntax"> *</span><span class="function-syntax">PluginManager::new</span><button class="popup" onclick="togglePopup('usagePopup1')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup1">Usage of <span class="code-font"><span class="function-syntax">PluginManager::new</span></span>:<br/>Core Module - <a href="1-cm.html#SP2">&#167;2</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax"> (*</span><span class="identifier-syntax">starter</span><span class="plain-syntax">)(</span><span class="reserved-syntax">void</span><span class="plain-syntax">), </span><span class="identifier-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">tname</span><span class="plain-syntax">, </span><span class="reserved-syntax">plugin</span><span class="plain-syntax"> *</span><span class="identifier-syntax">set</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">plugin</span><span class="plain-syntax"> *</span><span class="identifier-syntax">P</span><span class="plain-syntax"> = </span><span class="identifier-syntax">CREATE</span><span class="plain-syntax">(</span><span class="reserved-syntax">plugin</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">P</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">textual_name</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Str::duplicate</span><span class="plain-syntax">(</span><span class="identifier-syntax">tname</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">P</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">wording_name</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Feeds::feed_text</span><span class="plain-syntax">(</span><span class="identifier-syntax">tname</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">P</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">activation_function</span><span class="plain-syntax"> = </span><span class="identifier-syntax">starter</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">P</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">active</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">P</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">parent_plugin</span><span class="plain-syntax"> = </span><span class="identifier-syntax">set</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">P</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">allocation_id</span><span class="plain-syntax"> &gt;= </span><span class="constant-syntax">MAX_PLUGINS</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"Too many plugins"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">P</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<ul class="endnotetexts"><li>The structure plugin is private to this section.</li></ul>
<p class="commentary firstcommentary"><a id="SP2" class="paragraph-anchor"></a><b>&#167;2. </b>An inactive plugin does nothing; it's as if that section of code were not in
the compiler at all.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">PluginManager::active</span><span class="plain-syntax">(</span><span class="reserved-syntax">plugin</span><span class="plain-syntax"> *</span><span class="identifier-syntax">P</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">P</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">active</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">PluginManager::list_plugins</span><span class="plain-syntax">(</span><span class="identifier-syntax">OUTPUT_STREAM</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">state</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">plugin</span><span class="plain-syntax"> *</span><span class="identifier-syntax">P</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">c</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_OVER</span><span class="plain-syntax">(</span><span class="identifier-syntax">P</span><span class="plain-syntax">, </span><span class="reserved-syntax">plugin</span><span class="plain-syntax">) </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">P</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">active</span><span class="plain-syntax"> == </span><span class="identifier-syntax">state</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">c</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">", "</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"%S"</span><span class="plain-syntax">, </span><span class="identifier-syntax">P</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">textual_name</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">c</span><span class="plain-syntax">++;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP3" class="paragraph-anchor"></a><b>&#167;3. </b>In the code above, plugins are set up as inactive by default &mdash; even "core",
which the compiler absolutely cannot live without. So <a href="../supervisor-module/5-ps2.html" class="internal">Project Services (in supervisor)</a>
calls the following before switching on optional things that it wants.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">PluginManager::activate_bare_minimum</span><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">plugin</span><span class="plain-syntax"> *</span><span class="identifier-syntax">P</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_OVER</span><span class="plain-syntax">(</span><span class="identifier-syntax">P</span><span class="plain-syntax">, </span><span class="reserved-syntax">plugin</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">P</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">permanently_active</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">P</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">active</span><span class="plain-syntax"> == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><a href="3-pm.html#SP4" class="function-link"><span class="function-syntax">PluginManager::activate</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">P</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">PluginManager::make_permanently_active</span><button class="popup" onclick="togglePopup('usagePopup2')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup2">Usage of <span class="code-font"><span class="function-syntax">PluginManager::make_permanently_active</span></span>:<br/>Core Module - <a href="1-cm.html#SP2">&#167;2</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">plugin</span><span class="plain-syntax"> *</span><span class="identifier-syntax">P</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">P</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"no plugin"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">P</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">permanently_active</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP4" class="paragraph-anchor"></a><b>&#167;4. </b>Most plugins are subordinate to a parent plugin: for example, a dozen more
specific IF-related plugins are subordinate to the "interactive fiction" one.
Activating or deactivating a parent like that automatically activates
or deactivates its children.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">PluginManager::activate</span><button class="popup" onclick="togglePopup('usagePopup3')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup3">Usage of <span class="code-font"><span class="function-syntax">PluginManager::activate</span></span>:<br/><a href="3-pm.html#SP3">&#167;3</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">plugin</span><span class="plain-syntax"> *</span><span class="identifier-syntax">P</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">P</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">P</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">active</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">plugin</span><span class="plain-syntax"> *</span><span class="identifier-syntax">Q</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_OVER</span><span class="plain-syntax">(</span><span class="identifier-syntax">Q</span><span class="plain-syntax">, </span><span class="reserved-syntax">plugin</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Q</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">parent_plugin</span><span class="plain-syntax"> == </span><span class="identifier-syntax">P</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><a href="3-pm.html#SP4" class="function-link"><span class="function-syntax">PluginManager::activate</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">Q</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">PluginManager::deactivate</span><span class="plain-syntax">(</span><span class="reserved-syntax">plugin</span><span class="plain-syntax"> *</span><span class="identifier-syntax">P</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">P</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">P</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">permanently_active</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="3-pm.html#SP4_1" class="named-paragraph-link"><span class="named-paragraph">Issue problem for trying to remove the core</span><span class="named-paragraph-number">4.1</span></a></span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">P</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">active</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">plugin</span><span class="plain-syntax"> *</span><span class="identifier-syntax">Q</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_OVER</span><span class="plain-syntax">(</span><span class="identifier-syntax">Q</span><span class="plain-syntax">, </span><span class="reserved-syntax">plugin</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Q</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">parent_plugin</span><span class="plain-syntax"> == </span><span class="identifier-syntax">P</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><a href="3-pm.html#SP4" class="function-link"><span class="function-syntax">PluginManager::deactivate</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">Q</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP4_1" class="paragraph-anchor"></a><b>&#167;4.1. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Issue problem for trying to remove the core</span><span class="named-paragraph-number">4.1</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">problem_count</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">StandardProblems::sentence_problem</span><span class="plain-syntax">(</span><a href="1-wtc.html#SP6" class="function-link"><span class="function-syntax">Task::syntax_tree</span></a><span class="plain-syntax">(), </span><span class="identifier-syntax">_p_</span><span class="plain-syntax">(</span><span class="identifier-syntax">Untestable</span><span class="plain-syntax">),</span>
<span class="plain-syntax"> </span><span class="string-syntax">"the core of the Inform language cannot be removed"</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="string-syntax">"because then what should we do? What should we ever do?"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="3-pm.html#SP4">&#167;4</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP5" class="paragraph-anchor"></a><b>&#167;5. </b>Every active plugin gets to run its start function, if it provides one.
</p>
<p class="commentary">It's kind of incredible that C's grammar for round brackets is unambiguous.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">PluginManager::start_plugins</span><button class="popup" onclick="togglePopup('usagePopup4')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup4">Usage of <span class="code-font"><span class="function-syntax">PluginManager::start_plugins</span></span>:<br/>What To Compile - <a href="1-wtc.html#SP3">&#167;3</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">plugin</span><span class="plain-syntax"> *</span><span class="identifier-syntax">P</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_OVER</span><span class="plain-syntax">(</span><span class="identifier-syntax">P</span><span class="plain-syntax">, </span><span class="reserved-syntax">plugin</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">P</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">active</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">void</span><span class="plain-syntax"> (*</span><span class="identifier-syntax">start</span><span class="plain-syntax">)() = (</span><span class="reserved-syntax">void</span><span class="plain-syntax"> (*)()) </span><span class="identifier-syntax">P</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">activation_function</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">start</span><span class="plain-syntax">) (*</span><span class="identifier-syntax">start</span><span class="plain-syntax">)();</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP6" class="paragraph-anchor"></a><b>&#167;6. </b>The names of the great plugins are hard-wired into the compiler rather
than being stored in Preform grammar, and they therefore cannot be translated
out of English. But this is intentional, for now at least. Authors are not
intended to be aware of plugins; it is really kits of Inter code which choose
which plugins are active.
</p>
<p class="commentary">However, because it is possible to have headings in Inform source text which
restrict material according to whether a plugin is active, we do need a
Preform nonterminal to parse them, and here it is.
</p>
<pre class="Preform-displayed-code all-displayed-code code-font">
<span class="Preform-function-syntax">&lt;language-element&gt;</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">internal</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">{</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">plugin</span><span class="Preform-plain-syntax"> *</span><span class="Preform-identifier-syntax">P</span><span class="Preform-plain-syntax">;</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-identifier-syntax">LOOP_OVER</span><span class="Preform-plain-syntax">(</span><span class="Preform-identifier-syntax">P</span><span class="Preform-plain-syntax">, </span><span class="Preform-reserved-syntax">plugin</span><span class="Preform-plain-syntax">)</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">if</span><span class="Preform-plain-syntax"> (</span><span class="Preform-identifier-syntax">Wordings::match</span><span class="Preform-plain-syntax">(</span><span class="Preform-identifier-syntax">P</span><span class="Preform-plain-syntax">-&gt;</span><span class="Preform-element-syntax">wording_name</span><span class="Preform-plain-syntax">, </span><span class="Preform-identifier-syntax">W</span><span class="Preform-plain-syntax">)) {</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">if</span><span class="Preform-plain-syntax"> (</span><span class="Preform-identifier-syntax">P</span><span class="Preform-plain-syntax">-&gt;</span><span class="Preform-element-syntax">active</span><span class="Preform-plain-syntax"> == </span><span class="Preform-identifier-syntax">FALSE</span><span class="Preform-plain-syntax">) {</span>
<span class="Preform-plain-syntax"> ==&gt; { </span><span class="Preform-identifier-syntax">FALSE</span><span class="Preform-plain-syntax">, </span><span class="Preform-identifier-syntax">P</span><span class="Preform-plain-syntax"> };</span>
<span class="Preform-plain-syntax"> } </span><span class="Preform-reserved-syntax">else</span><span class="Preform-plain-syntax"> {</span>
<span class="Preform-plain-syntax"> ==&gt; { </span><span class="Preform-identifier-syntax">TRUE</span><span class="Preform-plain-syntax">, </span><span class="Preform-identifier-syntax">P</span><span class="Preform-plain-syntax"> };</span>
<span class="Preform-plain-syntax"> }</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">return</span><span class="Preform-plain-syntax"> </span><span class="Preform-identifier-syntax">TRUE</span><span class="Preform-plain-syntax">;</span>
<span class="Preform-plain-syntax"> }</span>
<span class="Preform-plain-syntax"> ==&gt; { </span><span class="Preform-identifier-syntax">fail</span><span class="Preform-plain-syntax"> </span><span class="Preform-identifier-syntax">nonterminal</span><span class="Preform-plain-syntax"> };</span>
<span class="Preform-plain-syntax">}</span>
</pre>
<ul class="endnotetexts"><li>This is <a href="../words-module/4-ap.html" class="internal">Preform grammar</a>, not regular C code.</li></ul>
<p class="commentary firstcommentary"><a id="SP7" class="paragraph-anchor"></a><b>&#167;7. </b>It's convenient also to provide:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">plugin</span><span class="plain-syntax"> *</span><span class="function-syntax">PluginManager::parse</span><span class="plain-syntax">(</span><span class="identifier-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">S</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">plugin</span><span class="plain-syntax"> *</span><span class="identifier-syntax">P</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_OVER</span><span class="plain-syntax">(</span><span class="identifier-syntax">P</span><span class="plain-syntax">, </span><span class="reserved-syntax">plugin</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Str::eq_insensitive</span><span class="plain-syntax">(</span><span class="identifier-syntax">P</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">textual_name</span><span class="plain-syntax">, </span><span class="identifier-syntax">S</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">P</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP8" class="paragraph-anchor"></a><b>&#167;8. </b>Plugins affect the running of the compiler by inserting functions called plugs
into the following "plugin rulebooks" &mdash; there's a mixed metaphor here, but
the idea is that they behave like Inform rulebooks. When a rulebook is called,
the compiler works through each plug until one of them returns something other
than <span class="extract"><span class="extract-syntax">FALSE</span></span>.
</p>
<p class="commentary">Plugins should add plugs in their activation functions, by calling
<a href="3-pm.html#SP8" class="internal">PluginManager::plug</a>, which has an interestingly vague type. The next
screenful of code looks like something of a workout for the C typechecker, but
it compiles under <span class="extract"><span class="extract-syntax">clang</span></span> without even the <span class="extract"><span class="extract-syntax">-Wpedantic</span></span> warning, and honestly
you're barely living as a C programmer if you never generate that one.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="identifier-syntax">linked_list</span><span class="plain-syntax"> *</span><span class="identifier-syntax">plugin_rulebooks</span><span class="plain-syntax">[</span><span class="identifier-syntax">NO_DEFINED_PLUG_VALUES</span><span class="plain-syntax">+1]; </span><span class="comment-syntax"> of </span><span class="extract"><span class="extract-syntax">void</span></span><span class="comment-syntax">, reprehensibly</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">PluginManager::start</span><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax">=0; </span><span class="identifier-syntax">i</span><span class="plain-syntax">&lt;=</span><span class="identifier-syntax">NO_DEFINED_PLUG_VALUES</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</span><span class="plain-syntax">++)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">plugin_rulebooks</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">] = </span><span class="identifier-syntax">NEW_LINKED_LIST</span><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">PluginManager::plug</span><span class="plain-syntax">(</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">code</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> (*</span><span class="identifier-syntax">R</span><span class="plain-syntax">)()) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">code</span><span class="plain-syntax"> &gt; </span><span class="identifier-syntax">NO_DEFINED_PLUG_VALUES</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"not a plugin call"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">void</span><span class="plain-syntax"> *</span><span class="identifier-syntax">vR</span><span class="plain-syntax"> = (</span><span class="reserved-syntax">void</span><span class="plain-syntax"> *) </span><span class="identifier-syntax">R</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">ADD_TO_LINKED_LIST</span><span class="plain-syntax">(</span><span class="identifier-syntax">vR</span><span class="plain-syntax">, </span><span class="reserved-syntax">void</span><span class="plain-syntax">, </span><span class="identifier-syntax">plugin_rulebooks</span><span class="plain-syntax">[</span><span class="identifier-syntax">code</span><span class="plain-syntax">]);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP9" class="paragraph-anchor"></a><b>&#167;9. </b>The functions in <a href="3-pc.html" class="internal">Plugin Calls</a> then make use of these macros, which are
the easiest way to persuade the C typechecker to allow variable arguments to
be passed in a portable way. Similarly, there are two macros not one because
C does not allow a void variable argument list.
</p>
<p class="commentary">We must take care that the variables introduced in the macro body do not mask
existing variables used in the arguments; the only way to do this is to give
them implausible names.
</p>
<pre class="definitions code-font"><span class="definition-keyword">define</span> <span class="identifier-syntax">PLUGINS_CALL</span><span class="plain-syntax">(</span><span class="identifier-syntax">code</span><span class="plain-syntax">, </span><span class="identifier-syntax">args</span><span class="plain-syntax">...) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">void</span><span class="plain-syntax"> *</span><span class="identifier-syntax">R_plugin_pointer_XYZZY</span><span class="plain-syntax">; </span><span class="comment-syntax"> no argument can have this name</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_OVER_LINKED_LIST</span><span class="plain-syntax">(</span><span class="identifier-syntax">R_plugin_pointer_XYZZY</span><span class="plain-syntax">, </span><span class="reserved-syntax">void</span><span class="plain-syntax">, </span><span class="identifier-syntax">plugin_rulebooks</span><span class="plain-syntax">[</span><span class="identifier-syntax">code</span><span class="plain-syntax">]) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> (*</span><span class="identifier-syntax">R_plugin_rule_ZOOGE</span><span class="plain-syntax">)() = (</span><span class="reserved-syntax">int</span><span class="plain-syntax"> (*)()) </span><span class="identifier-syntax">R_plugin_pointer_XYZZY</span><span class="plain-syntax">; </span><span class="comment-syntax"> or this one</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">Q_plugin_return_PLUGH</span><span class="plain-syntax"> = (*</span><span class="identifier-syntax">R_plugin_rule_ZOOGE</span><span class="plain-syntax">)(</span><span class="identifier-syntax">args</span><span class="plain-syntax">); </span><span class="comment-syntax"> or this</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Q_plugin_return_PLUGH</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">Q_plugin_return_PLUGH</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="definition-keyword">define</span> <span class="identifier-syntax">PLUGINS_CALLV</span><span class="plain-syntax">(</span><span class="identifier-syntax">code</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">void</span><span class="plain-syntax"> *</span><span class="identifier-syntax">R_plugin_pointer_XYZZY</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_OVER_LINKED_LIST</span><span class="plain-syntax">(</span><span class="identifier-syntax">R_plugin_pointer_XYZZY</span><span class="plain-syntax">, </span><span class="reserved-syntax">void</span><span class="plain-syntax">, </span><span class="identifier-syntax">plugin_rulebooks</span><span class="plain-syntax">[</span><span class="identifier-syntax">code</span><span class="plain-syntax">]) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> (*</span><span class="identifier-syntax">R_plugin_rule_ZOOGE</span><span class="plain-syntax">)() = (</span><span class="reserved-syntax">int</span><span class="plain-syntax"> (*)()) </span><span class="identifier-syntax">R_plugin_pointer_XYZZY</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">Q_plugin_return_PLUGH</span><span class="plain-syntax"> = (*</span><span class="identifier-syntax">R_plugin_rule_ZOOGE</span><span class="plain-syntax">)();</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Q_plugin_return_PLUGH</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">Q_plugin_return_PLUGH</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<nav role="progress"><div class="progresscontainer">
<ul class="progressbar"><li class="progressprev"><a href="2-kp.html">&#10094;</a></li><li class="progresschapter"><a href="P-wtmd.html">P</a></li><li class="progresschapter"><a href="1-cm.html">1</a></li><li class="progresschapter"><a href="2-up.html">2</a></li><li class="progresscurrentchapter">3</li><li class="progresscurrent">pm</li><li class="progresssection"><a href="3-pc.html">pc</a></li><li class="progressnext"><a href="3-pc.html">&#10095;</a></li></ul></div>
</nav><!--End of weave-->
</main>
</body>
</html>