Commits

Jason McKesson committed 1c34245

Guide: Most of the header is finished.

  • Participants
  • Parent commits 087cb87

Comments (0)

Files changed (8)

File docs/Load Docs.xpr

         <file name="Common_Extension_Files.xml"/>
         <file name="Extension_Files.xml"/>
         <file name="Home.xml"/>
+        <file name="New_Style_Step_By_Step.xml"/>
         <file name="Structure_Reference.xml"/>
         <file name="Style_Creation.xml"/>
         <file name="Style_No_Load_CPP.xml"/>

File docs/New_Style_Step_By_Step.xml

+<?xml version="1.0" encoding="UTF-8"?>
+<?oxygen RNGSchema="http://docbook.org/xml/5.0/rng/docbookxi.rng" type="xml"?>
+<?oxygen SCHSchema="http://docbook.org/xml/5.0/rng/docbookxi.rng"?>
+<article xmlns="http://docbook.org/ns/docbook" xmlns:xi="http://www.w3.org/2001/XInclude"
+    xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0">
+    <title>New Style Step By Step</title>
+    <para>Making a style is a somewhat complex process. This will be a step-by-step guide to using
+        the system to make a part of a style. The style we will create will be a simple C-style
+        function loader.</para>
+    <para><phrase role="toc"/></para>
+    <section>
+        <title>Initial setup</title>
+        <para>All of the Lua scripts should go in the <filename>modules</filename> folder. For this
+            demonstration, we will create two files: one for the style and one for the structure.
+            The style will go into a file called <filename>StyleTest.lua</filename>, while the
+            structure will go into <filename>StructTest.lua</filename>.</para>
+        <para>The basic boilerplate for the structure is very simple:</para>
+        <programlisting>local struct = require "Structure"
+local common = require "CommonStruct"
+
+local my_struct = 
+{
+}
+
+my_struct = struct.BuildStructure(my_struct)
+return my_struct</programlisting>
+        <para>The first two statements include the <literal>Structure</literal> module, which allows
+            us to build our structure, and the <literal>CommonStruct</literal> module, which
+            provides some commonly used structural elements.</para>
+        <para><literal>my_struct</literal> is the base table for our structure. It's currently
+            empty, but we'll work on that as we progress.</para>
+        <para>Notice that what is returned is the built structure, which is a table. Lua's module
+            loading system will store this, so that the structure will only be built once.</para>
+        <para>The boilerplate for our style is fairly simple as well:</para>
+        <programlisting>local util = require "util"
+local struct = require "StructTest"
+local common = require "CommonStyle"
+
+local my_style = {}
+
+local function Create()
+    return util.DeepCopyTable(my_style), struct
+end
+
+return { Create = Create }</programlisting>
+        <para>The <literal>util</literal> module contains some basic utility functions that we will
+            use. The style is what decides which structure it uses, so we include our structure's
+            module table. And the <literal>CommonStyle</literal> are functions commonly used by
+            styles.</para>
+        <para><literal>my_style</literal> is the base style table. It's empty; we will fill it in
+            through this demonstration.</para>
+        <para>The return value is a table that exports a single function: <literal>Create</literal>.
+            The processing system expects <literal>Create</literal> to return both a style and a
+            structure. So we perform a table copy of our style and return the structure as
+            presented.</para>
+        <para>There is one final step before we begin: we must hook our style into the glLoadGen
+            system. To do this, open up the <literal>Styles.lua</literal> file. You will see a
+            declaration of the <literal>style_registry</literal> variable as a table, with several
+            different styles already in that table. Simply add your own to this table; the string
+            name you use will be the name you use on the command line.</para>
+        <para>In our case, we will do this:</para>
+        <programlisting>local style_registry =
+{
+	pointer_c = require("StylePointerC"),
+	pointer_cpp = require("StylePointerCPP"),
+	glload = require("StyleGLLoad"),
+	noload_cpp = require("StyleNoloadCpp"),
+	test = require("StyleTest"),
+}</programlisting>
+        <para>On the command line, to execute our style, simply use
+            <literal>-style=test</literal>.</para>
+    </section>
+    <section>
+        <title>Header</title>
+        <para>Our C-style loader will generate two files: a header and a source file. So our first
+            major step is to generate the header file.</para>
+        <para>The header file and source files will have to do two very different things. The header
+            file will generate function pointers, extension variables and #defines for enumerators
+            that the user will use. But since this is C, variables in headers must be declared with
+                <literal>extern</literal>. So the declaration in the headers has to be different
+            from the definitions in the source files.</para>
+        <para>Therefore, we are going to split our main style (<literal>my_style</literal>) into two
+            sub-styles: <literal>hdr</literal> and <literal>src</literal>. <literal>hdr</literal>
+            contains the writing logic for header-specific issues, and the same goes for
+                <literal>src</literal> for source-specific issues.</para>
+        <para>So let's start doing that. In our style file, we now have this:</para>
+        <programlisting>local my_style = {}
+
+local hdr = {}
+my_style.hdr = hdr
+
+local src = {}
+my_style.src = src</programlisting>
+        <para>Everything before and after this looks the same as before. <literal>my_style</literal>
+            will contain functions that both the <literal>src</literal> and <literal>hdr</literal>
+            sub-styles share.</para>
+        <para>Now that we have divided our style, we now must start building our structure. We need
+            to generate a header file. So we use the <literal>file</literal> structure
+            action:</para>
+        <programlisting>local my_struct = 
+{
+  { type="file", style="hdr", name="GetFilename(basename, spec, options)",
+  },
+}</programlisting>
+        <para>The <literal>style</literal> attribute in the <literal>file</literal> action says to
+            use the substyle named <literal>hdr</literal>, which we have defined in our main style.
+            The function <literal>GetFilename</literal> now must be placed into our style. We could
+            put it in either <literal>my_style</literal> or <literal>hdr</literal> and the system
+            would find it. But since it is header-specific, it should go into
+            <literal>hdr</literal>; that's the whole point of splitting them up to begin
+            with.</para>
+        <para>So, in our style, we add a function to get the appropriate filename:</para>
+        <programlisting>local hdr = {}
+my_style.hdr = hdr
+
+function hdr.GetFilename(basename, spec, options)
+  return basename .. ".h"
+end</programlisting>
+        <para>The variable <literal>basename</literal> contains all of the pathing information, as
+            well as the specific name that the user requested. All we need to do is add an
+            appropriate extension. We could decorate the name with anything as we see fit, but we
+            only need to add an extension.</para>
+        <para>You should be able to run this and have an empty file be generated.</para>
+        <para>Every header in C or C++ should have include guards; this is standard practice and is
+            very important. Include guards effectively have scope: the
+                <literal>#ifndef/#define</literal> at the top, and the <literal>#endif</literal> at
+            the bottom. So we will handle this in our structure using the <literal>block</literal>
+            action:</para>
+        <programlisting>local my_struct = 
+{
+  { type="file", style="hdr", name="GetFilename(basename, spec, options)",
+    { type="block", name="IncludeGuard",
+    },
+  },
+}</programlisting>
+        <para>Here, we don't provide a parameter list, so the block's default parameter list is
+            used. Which amounts to <literal>(hFile, spec, options)</literal>.</para>
+        <para><literal>block</literal> actions will call two different functions. In our case, it
+            will call <literal>WriteBlockBeginIncludeGuard</literal> before executing any child
+            actions, and <literal>WriteBlockEndIncludeGuard</literal> after writing all child
+            actions. There are no child actions as of yet, so we will just see include-guards
+            guarding nothing.</para>
+        <para>To actually write our beginning and ending include guards, we need some style code.
+            The first code we need is a function that will compute the include guard name.</para>
+        <programlisting>local function GetIncludeGuard(spec, options)
+  local temp = 
+    options.prefix .. spec.GetIncludeGuardString() .. "_THIS_IS_A_TEST_H"
+  return temp:upper()
+end</programlisting>
+        <para>Note that this function takes <literal>spec</literal> and <literal>options</literal>,
+            and that it uses both of them. The reason for this goes back to some of the <link
+                xlink:href="Style_Creation">responsibilities that styles must fulfill</link>.
+            Remember that styles must allow the user to specify a prefix to allow two different
+            invocations of the same style with the same specification to coexist in a program. So
+            our include guard need to incorporate the user's specified prefix. Also it includes a
+            string generated by the <literal>spec</literal>, which will differ between OpenGL, WGL,
+            and GLX. That way, you can include the GL generated header in the same source file as
+            the WGL generated one.</para>
+        <para>Now that we have a function that computes the include guard, we simply need to write
+            it:</para>
+        <programlisting>function hdr.GetFilename(basename, spec, options)
+  return basename .. ".h"
+end
+
+function hdr.WriteBlockBeginIncludeGuard(hFile, spec, options)
+  local guard = GetIncludeGuard(spec, options)
+  hFile:fmt("#ifndef %s\n", guard)
+  hFile:fmt("#define %s\n", guard)
+end
+
+function hdr.WriteBlockEndIncludeGuard(hFile, spec, options)
+  hFile:fmt("#endif /*%s*/\n", GetIncludeGuard(spec, options))
+end</programlisting>
+        <para>Note the use of <literal>hFile:fmt</literal>, which works like a form of
+                <literal>printf</literal> for Lua files. This is provided by the
+                <literal>TabbedFile.lua</literal> module.</para>
+        <section>
+            <title>Header preamble</title>
+            <para>The next steps are very specific to writing OpenGL loading systems. If your intent
+                is to generate something else with this system, then you won't need this preamble
+                stuff.</para>
+            <para>First, we need to recognize the intent of our loading system. Like most <link
+                    xlink:href="http://www.opengl.org/wiki/OpenGL_Loading_Library">OpenGL loading
+                    libraries,</link> we expect our header to <emphasis>completely
+                    replace</emphasis>
+                <filename>gl.h</filename> (though not WGL or GLX's headers). Because of that, we
+                need to make sure that the user has not included them <filename>gl.h</filename>
+                first. Also, if they try to include <filename>gl.h</filename> afterwards, we want it
+                to not be included correctly.</para>
+            <para>Similarly, there are <filename>wglext.h</filename> and
+                    <filename>glxext.h</filename> files (available from the OpenGL.org registry)
+                that do the same job as our loaders. We want to stop users from including them
+                too.</para>
+            <para>To do this, we need to put some <literal>#define</literal>s into our header. What
+                we want to do is <literal>#define</literal> the include guards that these file use,
+                so that they think they've already been included. And if we detect that they were
+                already defined, we issue a <literal>#error</literal> to halt compilation.</para>
+            <para>The hard work has been done for us; the function
+                    <literal>spec.GetHeaderInit()</literal> will get the appropriate header
+                    <literal>#define</literal>s that perform these tricks. All we need to do is
+                write what this function returns.</para>
+            <para>To do that, we add a <literal>write</literal> action to our structure:</para>
+            <programlisting>local my_struct = 
+{
+  { type="file", style="hdr", name="GetFilename(basename, spec, options)",
+    { type="block", name="IncludeGuard",
+      { type="write", name="Guards(hFile, spec, options)", },
+    },
+  },
+}</programlisting>
+            <para>The function <literal>WriteGuards</literal> will be called. As a header-specific
+                function, it goes into <literal>hdr</literal>. To write it, we simply do this in our
+                style:</para>
+            <programlisting>function hdr.WriteGuards(hFile, spec, options)
+  hFile:rawwrite(spec.GetHeaderInit())
+end</programlisting>
+            <para>The <literal>rawwrite</literal> command ignores all indentation in the
+                    <literal>TabbedFile</literal> and simply directly writes the block of text to
+                the output.</para>
+            <para>The next step is to write some necessary definitions. Our system is designed to
+                replace <filename>gl.h</filename> and the platform-specific extension headers.
+                However, these headers do more than just declare some functions. They also define
+                typedefs, things like <literal>GLuint</literal>, <literal>GLenum</literal>, and so
+                forth. These are crucial, and they must be defined before you can start declaring
+                function pointers and such. If you're writing a C++ loader, it's probably best to
+                    <emphasis>not</emphasis> stick them in a namespace.</para>
+            <para>OpenGL versions have increased the number of typedefs over the years. And we will
+                need to write these typedefs into our headers. If you were writing a non C/C++-based
+                loader, you would have quite a time figuring out how to define these typedefs and
+                such for your platform of interest, since the .spec files are geared towards C/C++.
+                But you would work something out, based on the definitions in the OpenGL
+                specification and your platform of interest.</para>
+            <para>Given that we're writing a C loader, we have an easier time; the hard work has
+                been done for us. The typedefs exists as blocks of text waiting to be thrown into a
+                header. The only thing we need is to simply regurgitate the information into the
+                file of interest.</para>
+            <para>To do this, we need to add another <literal>write</literal> action to our
+                style:</para>
+            <programlisting>local my_struct = 
+{
+  { type="file", style="hdr", name="GetFilename(basename, spec, options)",
+    { type="block", name="IncludeGuard",
+      { type="write", name="Guards(hFile, spec, options)", },
+      { type="blank" },
+      { type="write", name="Typedefs(hFile, specData, spec, options)",},
+    },
+  },
+}</programlisting>
+            <para>Note that <literal>WriteTypedefs</literal> takes the <literal>specData</literal>
+                parameter. That's because some of the data we need to write lives in the
+                specification data and some of it lives in the <literal>spec</literal>.</para>
+            <para>Also, note that we use a <literal>blank</literal> to insert a blank line between
+                them. This is just for clarity.</para>
+            <para>As for writing the data, here is how we do it in the style:</para>
+            <programlisting>function hdr.WriteTypedefs(hFile, specData, spec, options)
+  local defArray = common.GetStdTypedefs()
+	
+  --Use include-guards for the typedefs, since they're common among
+  --headers in this style.
+  hFile:write("#ifndef GL_LOAD_GEN_BASIC_OPENGL_TYPEDEFS\n")
+  hFile:write("#define GL_LOAD_GEN_BASIC_OPENGL_TYPEDEFS\n")
+  hFile:write("\n")
+  hFile:inc()
+	
+  for _, def in ipairs(defArray) do
+    hFile:write(def)
+  end
+	
+  hFile:dec()
+  hFile:write("\n")
+  hFile:write("#endif /*GL_LOAD_GEN_BASIC_OPENGL_TYPEDEFS*/\n")
+  hFile:write("\n")
+
+  common.WritePassthruData(hFile, specData.funcData.passthru)
+end</programlisting>
+            <para>This is a bit complicated. <literal>common.GetStdTypedefs()</literal> is where the
+                standard typedefs for the OpenGL 1.1 types live. We wrap them in their own set of
+                include guards to ensure that they never get defined multiple times; this will be
+                used for our OpenGL, WGL, and GLX headers, which need to co-exist with one
+                another.</para>
+            <para>Once we have that, we use the function <literal>common.WritePassthruData</literal>
+                to write the spec-specific typedefs, passing it the <literal>passthru</literal>
+                table loaded from the specification files.</para>
+            <para>You should be able to run the code generation process and get a header with a
+                bunch of type definitions in it.</para>
+        </section>
+        <section>
+            <title>Extension variables</title>
+            <para>With that task out of the way, we can now proceed to write our extension variable
+                declarations. However, if we want this file to co-exist with C and C++ (ie: you can
+                include the header from C++ code, even though the source code for it is C), then we
+                need to wrap all of our real C code in an <literal>extern "C"</literal>
+                block.</para>
+            <para>Since this is a block in terms of C logic, we use the <literal>block</literal> for
+                it in our structure:</para>
+            <programlisting>local my_struct = 
+{
+  { type="file", style="hdr", name="GetFilename(basename, spec, options)",
+    { type="block", name="IncludeGuard",
+      { type="write", name="Guards(hFile, spec, options)", },
+      { type="blank" },
+      { type="write", name="Typedefs(hFile, specData, spec, options)",},
+      { type="blank" },
+      { type="block", name="Extern(hFile)",
+      },
+    },
+  },
+}</programlisting>
+            <para>Our style needs two functions. Since both of these are header specific, they both
+                go into the <literal>hdr</literal> table:</para>
+            <programlisting>function hdr.WriteBlockBeginExtern(hFile)
+  common.WriteExternCStart(hFile)
+end
+
+function hdr.WriteBlockEndExtern(hFile)
+  common.WriteExternCEnd(hFile)
+end</programlisting>
+            <para>Because of how common this is, there are functions in the
+                    <literal>common</literal> table for doing exactly this task. Indeed, we can
+                shorten this by directly copying those functions into our table:</para>
+            <programlisting>hdr.WriteBlockBeginExtern = common.WriteExternCStart
+hdr.WriteBlockEndExtern = common.WriteExternCEnd</programlisting>
+            <para>Now that we have an extern block, we need to write an extension variable for every
+                extension that we were told to export. Since this is plain C, we don't have access
+                to <literal>bool</literal>, so we'll use <literal>int</literal> for the type instead
+                with the usual boolean semantics.</para>
+            <para>To iterate over extensions and write them, we use the <literal>ext-iter</literal>
+                iterator in our structure:</para>
+            <programlisting>{ type="block", name="Extern(hFile)",
+  { type="ext-iter",
+    { type="write", name="Extension(hFile, extName, spec, options)", },
+  },
+},</programlisting>
+            <para>For each extension, we will call <literal>WriteExtension</literal> in the style,
+                passing it the name of the extension via <literal>extName</literal>.</para>
+            <para>To write the extension variable declaration, we first need a function to compute
+                the name of the extension variable. We need this as a separate function because we
+                will need to write the variable definitions in the source file, and it would be best
+                not to copy-and-paste code. So we need a <literal>local</literal> function to
+                generate this:</para>
+            <programlisting>local function GetExtensionVarName(extName, spec, options)
+	return options.prefix .. spec.DeclPrefix() .. "ext_" .. extName
+end</programlisting>
+            <para>Notice that we again decorate the name with the user-defined prefix as well as a
+                specification-defined prefix. <literal>spec.DeclPrefix()</literal> is a common
+                prefix used for user-created variables and functions. The <literal>spec</literal>
+                also has functions for getting canonical prefixes (<literal>GL_</literal>,
+                    <literal>WGL_</literal>, etc), as we will see later.</para>
+            <para>Armed with this function, we can now add the writing function to
+                    <literal>hdr</literal>:</para>
+            <programlisting>function my_style.header.WriteExtension(hFile, extName, spec, options)
+  hFile:fmt("extern int %s;\n", GetExtensionVarName(extName, spec, options));
+end</programlisting>
+            <para>You should be able to run this and get a number of <literal>extern</literal>
+                declarations in the header now.</para>
+        </section>
+        <section>
+            <title>Enumerators</title>
+            <para>Wasn't that easy? Well, it won't be quite so easy anymore.</para>
+            <para>Now it's time to generate our enumerators. Since this is a C-style loader, we will
+                use the standard convention in C for enumerators: <literal>#define</literal>s. We
+                could define an actual C enumeration, but we'll go with the common way it's done,
+                for now.</para>
+            <para>Iterating over all of the extensions was simple. However, enumerators can come
+                from one of three sources:</para>
+            <itemizedlist>
+                <listitem>
+                    <para>Extensions the user asked for.</para>
+                </listitem>
+                <listitem>
+                    <para>OpenGL extensions that are core for the version the user asked for, but
+                        the user didn't specifically ask for that extension.</para>
+                </listitem>
+                <listitem>
+                    <para>The version of OpenGL the user asked for, outside of any core
+                        extensions.</para>
+                </listitem>
+            </itemizedlist>
+            <para>And we must iterate over each of these individually.</para>
+            <para>Compounding this is the fact that we also need to <emphasis>avoid</emphasis>
+                writing the same enumerator <literal>#define</literal> twice (sometimes an enum will
+                be in a version and an extension). This problem is easily solved via special
+                structure actions.</para>
+            <para>So, the first step with our structure is to introduce an
+                    <literal>enum-seen</literal> action. Any enumeration that is iterated over by
+                any child action will be captured. Later iterations that produce the same enumerator
+                can detect it and choose not write the <literal>#define</literal> statement.</para>
+            <programlisting>{ type="block", name="Extern(hFile)",
+  { type="ext-iter",
+    { type="write", name="Extension(hFile, extName, spec, options)", },
+  },
+  { type="enum-seen",
+  },
+},</programlisting>
+            <para>In order to iterate over every enum in every extension the user requested, we must
+                do exactly that: iterate over each extension, then iterate over every enumerator in
+                that extension. For the former, we use the <literal>ext-iter</literal> as before;
+                for the latter, we use <literal>enum-iter</literal>:</para>
+            <programlisting>{ type="enum-seen",
+  { type="ext-iter",
+    {type="enum-iter",
+      { type="write", name="Enumerator(hFile, enum, enumTable, spec, options, enumSeen)", },
+      { type="blank", last=true },
+    },
+  },
+},</programlisting>
+            <para>This will call the <literal>WriteEnumerator</literal> function for every
+                enumerator in every extension. The <literal>blank</literal> action here uses the
+                attribute <literal>last</literal>, which means that it will only insert a blank line
+                on the last iteration of the inner-most enumerator. So this puts a space between
+                every extension's enumerator. But it <emphasis>doesn't</emphasis> insert a space if
+                the extension had no enumerators at all. This is because
+                    <literal>enum-iter</literal> doesn't execute any of its children if there are no
+                enumerators, much like a for-loop over an empty list.</para>
+            <para>So, how do we write an enumerator in our style? That's kind of complicated. First,
+                we need a function to generate an enumerator name.</para>
+            <programlisting>local function GetEnumName(enum, spec, options)
+	return spec.EnumNamePrefix() .. enum.name
+end</programlisting>
+            <para>Note that the enumerator does <emphasis>not</emphasis> prefix the enum name with
+                the user-specified prefix <literal>options.prefix</literal>. This is a concession to
+                the purpose of this loader: it's trying to emulate the common OpenGL style as much
+                as possible. Furthermore, multiply-defined enums are usually a warning, not an
+                error, so it isn't too big of a problem. Of course, it <emphasis>could</emphasis>
+                prefix them if we so desired.</para>
+            <para>To write the enumerator, we use this function:</para>
+            <programlisting>function hdr.WriteEnumerator(hFile, enum, enumTable, spec, options, enumSeen)
+  if(enumSeen[enum.name]) then return end
+
+  hFile:fmt("#define %s %s\n",
+    GetEnumName(enum, spec, options),
+    common.ResolveEnumValue(enum, enumTable))
+end</programlisting>
+            <para>The <literal>if</literal> statement checks to see if the enum has been processed
+                before. If not, we generate a <literal>#define</literal>. Note that it is
+                    <emphasis>not</emphasis> this function's responsibility to actually store a
+                value in the <literal>enumSeen</literal> table. That is done by the
+                    <literal>enum-iter</literal> internally.</para>
+            <para>The value of the enumerator is stored oddly. One enum can reference another, so
+                resolving the value requires recursively going from enum to enum until you find one
+                with a real value. That is the job of <literal>common.ResolveEnumValue</literal>,
+                which uses the <literal>enumTable</literal>.</para>
+            <para>You can run this code, and you will get a file that contains enumerator
+                definitions for the requested extensions. But not for any core versions.</para>
+            <para>To get them, we need to augment our structure a bit. We need to iterate over every
+                version the user requested; we do that with a <literal>version-iter</literal>
+                action:</para>
+            <programlisting>{ type="enum-seen",
+  { type="ext-iter",
+    {type="enum-iter",
+      { type="write", name="Enumerator(hFile, enum, enumTable, spec, options, enumSeen)", },
+      { type="blank", last=true },
+    },
+  },
+  { type="version-iter",
+  },
+},</programlisting>
+            <para>Within that iterator, we need to iterate over all extensions that were
+                    <emphasis>not</emphasis> explicitly requested. There is a special extension
+                iterator for this: <literal>core-ext-cull-iter</literal>. It only works in the
+                presence of a <literal>version-iter</literal>. Once in place, we do our previous
+                enumeration iteration code:</para>
+            <programlisting>{ type="enum-seen",
+  { type="ext-iter",
+    {type="enum-iter",
+      { type="write", name="Enumerator(hFile, enum, enumTable, spec, options, enumSeen)", },
+      { type="blank", last=true },
+    },
+  },
+  { type="version-iter",
+    { type="core-ext-cull-iter",
+      {type="enum-iter",
+        { type="write", name="Enumerator(hFile, enum, enumTable, spec, options, enumSeen)", },
+        { type="blank", last=true },
+      },
+    },
+  },
+},</programlisting>
+            <para>This time, we don't even have to touch the style; this will now print the
+                enumerators for any core extensions not asked for explicitly.</para>
+            <para>To add in the enumerators for a version that aren't in core extensions from that
+                version, we make one more <literal>enum-iter</literal> pass, directly beneath the
+                    <literal>version-iter</literal>. <literal>enum-iter</literal> iterates over an
+                extension if an extension iterator is in use, but if none is in use, it looks for a
+                version iterator:</para>
+            <programlisting>{ type="enum-seen",
+  { type="ext-iter",
+    {type="enum-iter",
+      { type="write", name="Enumerator(hFile, enum, enumTable, spec, options, enumSeen)", },
+      { type="blank", last=true },
+    },
+  },
+  { type="version-iter",
+    { type="core-ext-cull-iter",
+      {type="enum-iter",
+        { type="write", name="Enumerator(hFile, enum, enumTable, spec, options, enumSeen)", },
+        { type="blank", last=true },
+      },
+    },
+    {type="enum-iter",
+      { type="write", name="Enumerator(hFile, enum, enumTable, spec, options, enumSeen)", },
+      { type="blank", last=true },
+    },
+  },
+},</programlisting>
+            <para>Again, no style changes are necessary.</para>
+            <para>Now, you might be thinking that maybe this should all just be one big
+                    <quote>iterate over all of the enumerators</quote> action, rather than a bunch
+                of little ones. While that is not available, there is the next best thing: the
+                common structural elements in the <literal>common</literal> table we created in our
+                    <literal>StructTest.lua</literal> file. It has a number of useful structural
+                elements, and this is one of them:</para>
+            <programlisting>{ type="block", name="Extern(hFile)",
+  { type="ext-iter",
+    { type="write", name="Extension(hFile, extName, spec, options)", },
+  },
+  common.Enumerators(),
+},</programlisting>
+            <para>This is almost exactly equivalent to the above block, right down to the name of
+                the function it calls (<literal>Enumerator</literal>) and the parameters it uses.
+                The only difference is that it adds some optional function calls to print headers
+                (naming each extension and version number), but that's unimportant. And
+                optional.</para>
+        </section>
+        <section>
+            <title>Functions</title>
+            <para>Functions work more or less like enumerators, and you have to iterate over them
+                like enumerators. In fact, they work <emphasis>so much</emphasis> like enumerators
+                that the only difference between the final version of the structure for enums and
+                for functions is the use of <literal>func-seen</literal>,
+                    <literal>func-iter</literal>, and writing with a call to
+                    <literal>Function(hFile, func, typemap, spec, options, funcSeen)</literal>. So
+                let's not waste time and skip to the end:</para>
+            <programlisting>{ type="func-seen",
+  { type="ext-iter",
+    {type="func-iter",
+      { type="write", name="Function(hFile, func, typemap, spec, options, funcSeen)", },
+      { type="blank", last=true },
+    },
+  },
+  { type="version-iter",
+    { type="core-ext-cull-iter",
+      {type="func-iter",
+        { type="write", name="Function(hFile, func, typemap, spec, options, funcSeen)", },
+        { type="blank", last=true },
+      },
+    },
+    {type="func-iter",
+      { type="write", name="Function(hFile, func, typemap, spec, options, funcSeen)", },
+      { type="blank", last=true },
+    },
+  },
+},</programlisting>
+            <para>As before, there is a common structural element to replace this:
+                    <literal>common.Functions()</literal>. And as before, it calls the same
+                    <literal>Function</literal> with the same arguments.</para>
+            <para>The biggest issue here is the writing of the actual functions. First, we need a
+                function to compute the name of the function pointer variable we want to
+                declare:</para>
+            <programlisting>local function GetFuncPtrName(func, spec, options)
+  return options.prefix .. "_testc_".. spec.FuncNamePrefix() .. func.name
+end</programlisting>
+            <para>Here, we actually need to prefix the variable name; otherwise linker errors could
+                occur. We also apply spec-based decoration, as well as a fixed string based on this
+                particular generator.</para>
+            <para>The usual method of writing function pointers would involve creating typedefs for
+                the function pointer types. You may have seen some
+                    <quote>PFNGLVERTEXATTRIBPOINTERPROC</quote>-kind of things. We won't be doing
+                that.</para>
+            <para>We still need a function to build a string containing the full function pointer
+                definition.</para>
+            <programlisting>local function GetFuncPtrDef(hFile, func, typemap, spec, options)
+  return string.format("%s (%s *%s)(%s)",
+    common.GetFuncReturnType(func, typemap),
+    spec.GetCodegenPtrType(),
+    GetFuncPtrName(func, spec, options),
+    common.GetFuncParamList(func, typemap))
+end</programlisting>
+            <para>This function calls a lot of things. Functions use types, for parameter types and
+                return types. Resolving these into the actual GL types is a non-trivial process, so
+                    <literal>common.GetFuncReturnType</literal> and
+                    <literal>common.GetFuncParamList</literal> are used to get the return type and
+                parameter list respectively. If you want the parameter names for the function
+                parameter list, pass <literal>true</literal> for a third parameter to the
+                function.</para>
+            <para>The <literal>spec.GetCodegenPtrType()</literal> part is very much <emphasis>not
+                    optional.</emphasis> It adds an important modifier to the function pointer,
+                which is needed on some systems (Windows). Without it, bad things happen.</para>
+            <programlisting>function hdr.WriteFunction(hFile, func, typemap, spec, options, funcSeen)
+  if(funcSeen[func.name]) then return end
+
+  hFile:fmt("extern %s;\n",
+    GetFuncPtrDef(hFile, func, typemap, spec, options))
+
+  hFile:fmt("#define %s %s\n",
+    common.GetOpenGLFuncName(func, spec),
+    GetFuncPtrName(func, spec, options))
+end</programlisting>
+            <para>After checking to see if the pointer has been written before, we get down to
+                business. We write an extern declaration for our function pointer with that type.
+                Then we write a <literal>#define</literal> statement, which effectively aliases the
+                name. This is a common tactic when dealing with function pointers and OpenGL
+                loaders: the pointer is given an innocuous name to avoid conflicting with user code,
+                and a <literal>#define</literal> is used to map it to the actual OpenGL function
+                name. That's what <literal>common.GetOpenGLFuncName</literal> returns.</para>
+        </section>
+        <section>
+            <title>Loaders</title>
+            <para/>
+        </section>
+    </section>
+    <section>
+        <title>Source</title>
+        <para/>
+        <section>
+            <title>Extension variables</title>
+            <para/>
+        </section>
+        <section>
+            <title>Functions</title>
+            <para/>
+        </section>
+        <section>
+            <title>Loaders</title>
+            <para/>
+        </section>
+    </section>
+</article>

File docs/Structure_Reference.xml

             </glossentry>
         </glosslist>
     </section>
+    <section>
+        <title>Common Structure</title>
+        <para>The module <literal>CommonStruct</literal> represents reuseable components for your
+            structure. You can use them as you see fit. Each of the following is a function within
+            the <literal>CommonStruct</literal> table. These are useful for more complex iteration
+            mechanism than what the standard structure iterators provide. They call functions with
+            specific names, but you can use the style scoping mechanism to put the right styles into
+            position to make them work.</para>
+        <glosslist>
+            <glossentry>
+                <glossterm>Extensions</glossterm>
+                <glossdef>
+                    <para>This function takes no arguments and returns a group of actions will
+                        iterate over every extension the user asked to export. For each extension,
+                        it will call a function named <literal>WriteExtension(hFile, extName, spec,
+                            options)</literal> to write each component.</para>
+                    <para>Obviously, since it is writing things, it needs to be used within a
+                            <literal>file</literal> action. Also, since it uses the
+                            <literal>ext-iter</literal> action, it cannot be used
+                            <emphasis>within</emphasis> an <literal>ext-iter</literal>
+                        action.</para>
+                </glossdef>
+            </glossentry>
+            <glossentry>
+                <glossterm>Enumerators</glossterm>
+                <glossdef>
+                    <para>This function takes no arguments and returns a group of actions that will
+                        iterate over every enumerator in every extension and version that the user
+                        asked to export. This will respect core/compatibility. For each enumerator,
+                        it will call a function named <literal>WriteEnumerator(hFile, enum,
+                            enumTable, spec, options, enumSeen)</literal> to write each
+                        enumerator.</para>
+                    <para>It will first iterate over the enumerators in extensions that the user
+                        asked for. Each extension will be in its own group, optionally writing a
+                        header for each using <literal>WriteSmallHeader(hFile, value,
+                            options)</literal> (so if you wish to suppress the header, make this an
+                        empty function on the current style). Then it will iterate over all of the
+                        versions. For each version, it will iterate over any core extension enums
+                        that were <emphasis>not</emphasis> explicitly requested (writing a header
+                        for each). Then it will iterate over that version's non-core-extension
+                        enums.</para>
+                    <para>This must be used within the scope of <literal>hFile</literal>, and since
+                        it uses extension, version, and enumerator iterators, it can't be in scope
+                        of any of those. It also uses <literal>enum-seen</literal>.</para>
+                </glossdef>
+            </glossentry>
+            <glossentry>
+                <glossterm>Functions</glossterm>
+                <glossdef>
+                    <para>This function optionally takes one argument and returns a group of actions
+                        that will iterate over every function in every extension and version that
+                        the user asked to export. This will respect core/compatibility. For each
+                        function, it will call a function named <literal>WriteFunction(hFile, func,
+                            typemap, spec, options, funcSeen)</literal> to write each
+                        function.</para>
+                    <para>It will iterate over functions in the same group order as with
+                        enumerators. It will write headers where appropriate, which can be
+                        omitted.</para>
+                    <para>This must be used within the scope of <literal>hFile</literal>, and since
+                        it uses extension, version, and function iterators, it can't be in scope of
+                        any of those. It also uses <literal>func-seen</literal>.</para>
+                </glossdef>
+            </glossentry>
+        </glosslist>
+    </section>
 </article>

File docs/Style_Creation.xml

     <para>In general, a style and a structure are created in tandem; if a structure is to be used in
         multiple styles, then the structure can be created first. But it's much easier to make part
         of a structure, implement enough style functions to use it, then expand on it.</para>
-    <para><phrase role="toc"/></para>
+    <para>There are two documents available to help you learn about making styles. The first is a
+        step-by-step guide to making a new style and structure. The second is a <link
+            xlink:href="Structure_Reference">reference manual for the structure
+        system</link>.</para>
     <section>
-        <title>Making the Structure</title>
-        <para>This page will provide a basic overview for making a simple structure. <link
-                xlink:href="Structure_Reference">The reference page</link> has more in-depth
-            documentation about all aspects of structure creation.</para>
-        <para/>
-        <para/>
-    </section>
-    <section>
-        <title>Library functions</title>
-        <para>There are a number of common operations that different styles will share. The
-                <literal>CommonStyle</literal> module returns a table containing these operations.
-            They are defined as follows:</para>
-    </section>
-    <section>
-        <title>Resolving conflicts</title>
-        <para>Your style may create global definitions and so forth that come into conflict with
-            other things. Here are the rules you need to follow:</para>
+        <title>Responsibilities</title>
+        <para>Your style may create global definitions and so forth. In C/C++, definitions in one
+            source file can come into conflict with definitions in another. Here are the rules that
+            the system expects new styles to follow when creating such definitions:</para>
         <itemizedlist>
             <listitem>
                 <para>The user should be able to use different specs with the same style and link
                     should coexist. This effectively means that you need to make sure that your
                     names are prefixed with something spec-specific. The <literal>spec</literal>
                     table has functions to get an appropriate prefix; the
-                        <literal>spec.DeclPrefix</literal> is the general prefix for
+                        <literal>spec.DeclPrefix()</literal> function is the general prefix for
                     declaration/definitions of things that can conflict at link time.</para>
             </listitem>
             <listitem>
                     against the empty string.</para>
             </listitem>
         </itemizedlist>
-        <para>So prefix names that can conflict with the user-prefix <emphasis>and</emphasis> the
-            spec's prefix.</para>
-    </section>
-    <section>
-        <title>Style function reference</title>
-        <para>The file <filename>modules/SampleStyle.lua</filename> contains a file that you can
-            simply copy and paste to start making a style. Every function you need to define is
-            listed, as well as comments explaining exactly what they should do. Coupled with this
-            documentation, you should be well on your way to getting a style working.</para>
+        <para>So decorate names that can conflict with the user-prefix <emphasis>and</emphasis> the
+            spec's prefix. In C, you'll have to prefix the actual names.</para>
     </section>
 </article>

File docs/Style_No_Load_CPP.xml

         don't need to call a function to load all of the function pointers; instead, you simply call
         the GL functions as normal. If it hasn't been loaded, it will be. This makes it among the
         most user-friendly of the loader styles.</para>
-    <para>As a C++ style, it follows the naming conventions of the <link><literal
-                xlink:href="Style_Pointer_CPP">pointer_cpp</literal></link> style. Everything is
-        scoped into namespaces. The enumerators don't have the <literal>GL_</literal> prefix on
-        them, and so forth.</para>
+    <para>As a C++ style, it follows the naming conventions of the <literal
+            xlink:href="Style_Pointer_CPP">pointer_cpp</literal> style. Everything is scoped into
+        namespaces. The enumerators don't have the <literal>GL_</literal> prefix on them, and so
+        forth.</para>
     <para>The system is designed to be automatic, responding to your application's needs. However,
         calling a function that the implementation does not provide will result in a crash, just as
         it would for the previous system.</para>
             <literal>sys::CheckExtensions</literal> to initialize them. This function only
         initializes the extension variables, so it cannot report on the number of functions that
         failed to load.</para>
+    <section>
+        <title>Versions</title>
+        <para>When you use this system and provide a version number of OpenGL,
+                <literal>noload_cpp</literal> will assume that you are <emphasis>serious</emphasis>
+            about that version number. Which means that if you create a 3.3 header, and you do not
+            supply a context that claims support for at least OpenGL version 3.3, <emphasis>crashing
+                may occur</emphasis>.</para>
+        <para>In particular, OpenGL changed the mechanism to check for the presence/absence of
+            extensions in version 3.0. Therefore, <literal>noload_cpp</literal> will also change how
+            it checks for the presence/absence of extensions based on that. If you provide a version
+            3.0 or greater, it will use the new style. Thus, if your context is only version 2.1,
+            then this style will be unable to function and will likely crash when it fails to load
+            an appropriate function pointer.</para>
+    </section>
 </article>

File docs/Style_Pointer_C.xml

     <para>Also, this style will generate functions to query the version of the OpenGL
         context.</para>
     <section>
+        <title>Versions</title>
+        <para>When you use this system and provide a version number of OpenGL,
+                <literal>pointer_c</literal> will assume that you are <emphasis>serious</emphasis>
+            about that version number. Which means that if you create a 3.3 header, and you do not
+            supply a context that claims support for at least OpenGL version 3.3, loading failure
+            may occur.</para>
+        <para>In particular, OpenGL changed the mechanism to check for the presence/absence of
+            extensions in version 3.0. Therefore, <literal>pointer_c</literal> will also change how
+            it checks for the presence/absence of extensions based on that. If you provide a version
+            3.0 or greater, it will use the new style. Thus, if your context is only version 2.1,
+            then this style will be unable to function and will return
+                <literal>LOAD_FAILED</literal>.</para>
+    </section>
+    <section>
         <title>Compatibility</title>
         <para>This style is intended to be maximally compatible with regular OpenGL programs. You
             should be able to take this header and include it into a standard GL program and use it

File docs/Style_Pointer_CPP.xml

         The number of functions that failed to load refers to the core functions (and core extension
         functions).</para>
     <section>
+        <title>Versions</title>
+        <para>When you use this system and provide a version number of OpenGL,
+                <literal>pointer_cpp</literal> will assume that you are <emphasis>serious</emphasis>
+            about that version number. Which means that if you create a 3.3 header, and you do not
+            supply a context that claims support for at least OpenGL version 3.3, loading failure
+            may occur.</para>
+        <para>In particular, OpenGL changed the mechanism to check for the presence/absence of
+            extensions in version 3.0. Therefore, <literal>pointer_cpp</literal> will also change
+            how it checks for the presence/absence of extensions based on that. If you provide a
+            version 3.0 or greater, it will use the new style. Thus, if your context is only version
+            2.1, then this style will be unable to function and will return
+                <literal>LOAD_FAILED</literal>.</para>
+    </section>
+    <section>
         <title>Compatibility</title>
         <para>These headers are "compatible" with headers from other libraries (FreeGLUT, GLFW,
             etc), but only in the sense that they define the appropriate typedefs globally. If any

File modules/StyleNoloadCpp.lua

 
 
 local function Create()
-	return common.DeepCopyTable(my_style), struct
+	return util.DeepCopyTable(my_style), struct
 end
 
 return { Create = Create }