Source

glLoadGen / docs / New_Style_Step_By_Step.xml

Full commit
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
<?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><literal>PFNGLVERTEXATTRIBPOINTERPROC</literal></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>Main loader</title>
            <para/>
        </section>
    </section>
    <section>
        <title>Source</title>
        <para/>
        <section>
            <title>Extension variables</title>
            <para/>
        </section>
        <section>
            <title>Functions</title>
            <para/>
        </section>
        <section>
            <title>Function loaders</title>
            <para/>
        </section>
        <section>
            <title>Main loader</title>
            <para/>
        </section>
    </section>
</article>