[
  {
    "path": ".gitignore",
    "content": "/build/\n/src/*.autogen.*\n/src/ConstList.txt\n/script/configure\n/script/config-defs.h.in\n/script/autom4te.cache\n/dist/\n"
  },
  {
    "path": "Changes",
    "content": "Version 2.1.0 - 2024-01-02\n  * New option \"--geometry\"\n  * Documentation improvements\n\nVersion 2.0.0 - 2018-03-25\n  * Replace homebrew font support with ftgl library API\n  * Rewrote most parsing code to eliminate some buggy edge cases\n  * New quoting syntax for command arguments\n  * New Divisor syntax and cglPushDivisor replace cglFixedPt\n  * Each type of named object is now in its own namespace\n  * Use SDL_image in cglLoadImage for broader image format support\n  * Stricter parsing of OpenGL calls with open-end argument lists\n  * Default projection sets model farther from near clipping plane\n  * Option to disable default projection matrix or viewport\n  * Notification for window status events\n  * Manual page\n  * Converted static hash table generator to perl\n  * Overhaul of build scripts, mostly borrowed from daemonproxy\n\nVersion 1.1.0 - 2006-04-05\n  * Added font support\n  * Added version numbering\n  * Many more examples and bug fixes\n\nVersion 1.0.0 - 2006-01-27\n  * Converted from GLUT to SDL\n  * Able to compile on Win32\n"
  },
  {
    "path": "LICENSE",
    "content": "BSD 3-Clause License\n\nCopyright (c) 2018, M Conrad\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n  list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n  this list of conditions and the following disclaimer in the documentation\n  and/or other materials provided with the distribution.\n\n* Neither the name of the copyright holder nor the names of its\n  contributors may be used to endorse or promote products derived from\n  this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "Makefile",
    "content": "MAKE = make\nPROVE = prove\nPERL = perl\n\nall: build\n\t$(MAKE) -C build all\n\nclean: build\n\t$(MAKE) -C build clean\n\ninstall: build\n\t$(MAKE) -C build install\n\nbuild:\n\t[ -f script/configure ] || { cd script; autoheader; autoconf; }\n\t[ -d build ] || ./configure\n\n.PHONY: test all clean dist install\n"
  },
  {
    "path": "README.md",
    "content": "CmdlineGL\n=========\n\nCmdlineGL is an interpreter for a \"text-friendly\" variation of a subset of the\nOpenGL 1.4 API, Glut API, and FTGL \"C\" API.\n\nIt reads API calls on stdin, and writes events on stdout, while reporting\nerrors to stderr.  You can find a description of the available commands and\nevents in the manual page, and get a list of the functions and constants\nsupported by a particular build of CmdlineGL using the\n``--showcmds`` and ``--showconstants`` options.\n\nDependencies\n============\n\nBefore you can build CmdlineGL, you need: SDL, SDL_image, OpenGL, GLU, FTGL,\nand the development headers for each.  On Debian/Ubuntu/Mint, these are:\n\n    sudo apt-get install \\\n        libsdl1.2-dev libsdl-image1.2-dev \\\n        libgl1-mesa-dev libftgl-dev\n\nand on Fedora they are\n\n    sudo yum install \\\n        SDL-devel SDL_image-devel \\\n        mesa-libGL-devel mesa-libGLU-devel ftgl-devel\n\nThe autoconf script is still very new, so it might not detect locations of\nheaders and libraries on other systems.  Patches are welcome.\n\nBuilding and Installing\n=======================\n\nThis is almost but not quite a standard autoconf distribution.  All the\nautoconf files live in the ./script directory, and the top level project has\na pass-through Makefile and ./configure script that set up an out-of-tree\n(well, technically still in the project tree) build in a directory named\n\"./build\".  Anyway, you can just run\n\n    make && sudo make install\n\nfrom the root of the project and maybe everything will just work.  If you are\nrunning from the distribution tarball, this will create a \"production build\",\nbut if you are running it from a git checkout, it will create a \"dev build\"\nwith assertions enabled and some extra logging.\n\nYou can also invoke autoconf directly:\n\n    mkdir work\n    cd work\n    $PROJDIR/script/configure [OPTIONS]\n    make\n    make install\n\nUsage\n=====\n\nSee the manual page (built during 'make' process) for details about the commands\nsupported. There is also the [online manual], and [examples directory].\n\n[examples directory]: ./share/examples\n[online manual]: https://www.nrdvana.net/cmdlinegl/release/current/CmdlineGL.html\n"
  },
  {
    "path": "configure",
    "content": "#! /bin/sh\n\n# This configure script is just a place-holder that sets up an out-of-tree\n# build in a directory named \"build\".  The real autoconf configure script is\n# located in ./script/\n#\n# When checked out of git, this enables options \"--enable-dev\" and\n# \"--enable-debug\" by default.  When distributed as a tarball, this script is\n# altered to remove those options.\n\n# if run from outside proj root, inform user whats going on\nif [ ! -d script -o ! -d src ]; then\n\techo \"For out-of-tree builds, run ./script/configure directly.\"\n\texit 1;\nfi\n\nmkdir -p build && cd build && ../script/configure --enable-dev --enable-debug \"$@\"\n"
  },
  {
    "path": "doc/Design.txt",
    "content": "\n\n\tNew design:\n\n\t\tServer.c\n\t\t\tEverything to do with setting up the window and watching file descriptors.\n\n\t\tProcessInput.c\n\t\t\tEverything to do with reading input from a file descriptor, and sending it to the ParseGL\n\t\t\tmodule for execution.\n\n\t\tParseGL.c\n\t\t\tEverything to do with taking a parsed line of text, and determining whether it can be\n\t\t\texecuted, and executing it.\n\n\t\tSymbolHash.c\n\t\t\tAll the hash table stuff.\n"
  },
  {
    "path": "doc/Fonts.html",
    "content": "<html>\n<head>\n\t<title>Working with CmdlineGL Fonts</title>\n</head>\n\n<body>\n\t<h3>Preface</h3>\n\t<p>In CmdlineGL, I wanted some simple kind of font system that wouldn't be dependant on\n\tlibraries installed on the system, and also not dependant on which SDL modules were\n\tinstalled.  So, I went and pulled an old idea (which I've probably seen somewhere)\n\tmaking use of control pixels in a bitmap to denote the size/spacing of font characters\n\tand wrote it up.\n\t<p>This font system allows you to &quot;make a font&quot; using a plain old bitmap editor,\n\tor even convert a font from trueType to bitmap by using the text-tool in those same editors\n\tand then marking the boundaries of the characters.  It expects the ascii characters from 0x20\n\t(space) up to 0x7F (DEL), 96 characters in total.  This is likely only usable by\n\tEnglish-speaking folks, unfortunately.  I'd love to extend it to handle a variable number\n\tof characters, and read UTF8 unicode, but I didn't see any easy way to do this.\n\tMaybe people with more experience in this area would like to contribute.\n\t\n\t<h3>Using the commands</h3>\n\t<p>I added 2 &quot;GL-ish&quot; commands to work with fonts:\n\tcglNewFont, and cglText.\n\t<p>cglNewFont takes three parameters: the type of font, the symbolic name for it, and the file name.\n\tThe type currently must be CGL_BMPFONT, the symbolic name can be any <a href=\"NamedObjects.html\">valid name</a>,\n\tand the file name is any valid system-dependant file path.\n\n\t<p>cglText takes two parameters as well: the name of the font to use, and the text string to render with it.\n\tAs of now, the rendering is very dumb, and only renders lines as they are given.\n\tI might, in a future version, start handling things like tabs and newlines, or even\n\tadd some options for wrapping.\n</body>\n"
  },
  {
    "path": "doc/Intro.html",
    "content": "<html>\n<head>\n\t<style>\n\tBODY { background-color:black; color:#55FF55; font-family:\"Courier New\", monospace, sans-serif; }\n\tH1,H2 { color:white; font-weight:bold; }\n\tH4 { color:white; font-weight:normal; }\n\tA { color:#AAFFAA; text-decoration:underline; }\n\tA.hover { color:white; }\n\tDIV.code { color:white; background-color:#555555; border:1px solid blue; margin:0.5em; padding:0.5em; }\n\tDIV.warning { color:#FFBBBB; background-color:#222222; border:2px solid red; margin:0.5em; padding:0.5em; }\n\tSPAN.note { color:gray; font-size:70%; font-style:italic; }\n\t</style>\n</head>\n<body>\n\t<center>\n\t<h2>Introducing</h2>\n \t<h1>OpenGL Bindings for BASH</h1>\n\t</center>\n\t<h2>\"What???\"</h2>\n\t<p>A while back, I came accross a game called <a href=\"http://www.frozen-bubble.org\">Frozen Bubble</a>, which is a <a href=\"http://www.snood.com\">Snood</a>\n\tclone written in Perl using the OpenGL bindings.  I was rather offended by the\n\twhole concept, and said something like \"Arg! Thats almost as bad as writing a 3D\n\tgame in Bash!\".  So, this December during winter break, when I was trying to think\n\tof something to do for <i>Mike's Abuse of Technology</i> #6....\n\t</p>\n\t<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\"><tr><td><h2>\"Oh, God!&nbsp;&nbsp;No!!\"</h2></td><td><span class=\"note\">&nbsp;&nbsp;&lt;-- (common actual quote)</span></td></tr></table>\n\t<p>But here it is!  Bwa-Ha-Ha! All the normal languages have OpenGL support,\n\tand some scripting languages like Perl, Python, and PHP have OpenGL bindings,\n \tand now Bash does too!\n\t</p>\n\t<h2>\"BUT WHY, DAMNIT? WHY??\"</h2>\n\t<p>If you have to ask why, you are not a member of the intended audience.  Please\n\tgo on about your business and accept my apologies for this distraction.\n\t<br/><span class=\"note\">(tribute to Bob Zimbinski <a href=\"#credits\">[1]</a>)</span>\n\t</p>\n\t<h2>\"But how?  Bash doesn't support modules...\"</h2>\n\t<p>Right.  So I gave it an interface just like all the others it uses:\n\ta simple command that can be given parameters and fed commands on standatd input.</p>\n\tWhen invoked, CmdlineGL starts a server which creates an OpenGL window, and then either\n\treads input from a file or from standard-in.  To deliver commands to it, a script can\n\tpipe standard-out to the program, or write to a fifo, or other creative methods.\n\tThe script sends lines of text to the server that tell it to execute any of the\n\tsupported OpenGL, GLU, or GLUT API calls.  CmdlineGL supports textures, display lists,\n\tquadrics, and just about all of the usual gl calls.\n\t</p>\n\t<h2>\"This sounds <a href=\"http://www.catb.org/esr/jargon/html/B/Bad-and-Wrong.html\">Bad and Wrong</a>\"</h2>\n\t<p>I'd argue for Bad and Right.  Keep reading.\n\t</p>\n\t<h2>\"So, how bad does the performance suck?\"</h2>\n\t<p>Its definately slower than games written in C, but might not be as slow as you think:\n\tCmdlineGL is written in straight C with as little overhead as possible, to the point\n\tof doing all text operations on the same character buffer filled by the call to 'read',\n\tand sacraficing reusability for performance (and wow, was it ever liberating!).\n\tIt also uses a statically defined hash table to map command names to function pointers.\n\tTo top things off, it uses a <a href=\"http://gauss.ececs.uc.edu/RedBlack/redblack.html\">Red/Black Tree</a> to manage the names of objects\n\tlike display lists, quadrics, textures, and fonts.\n\t</p>\n\t<p>Because of the support for display lists, any part of your game that doesn't move\n\tcan be compiled into the OpenGL end and replayed as a single line of text.\n\tAnd, in a 3D application, most of the time is spent drawing pixels and texturing them,\n\tand this is probably done by the graphics card,\n\tso there's plenty of CPU time left over for running data through a pipe and a socket,\n\tand running string-to-float conversions,\n \tand repeatedly forking hundreds of times per frame per second,\n\tespecially with the speed of today's computers ;-)\n\t</p>\n\t<h2>\"And you actually wrote a game using this kluge?\"</h2>\n\t<p>Well, mostly just demos, but a game engine of sorts, yes.\n\t<br><span class=\"note\">(I never finished the flight simulator)</span>\n\t</p>\n\t<p>Lets review some of the obstacles\n\tinvolved with a real-time game, and our old friend/nemesis Bash:\n\t<ul>\n\t<li><h4>Bash needs to receive key/mouse activity from the server.  There are no RPCs</h4>\n\t\t<p>The only natural way bash has to receive feedback from the user is a text stream.\n\t\tOne other possibility is for it to call a special program which would contact the\n\t\tserver, get some information, and give it back to bash in the form of a integer result\n\t\tcode, but this seemed particularly slow.  So, I came up with the idea that the server\n\t\tcould simply write user actions to stdout, and this could be piped to the stdin of the\n\t\tscript.\n\t\t</p>\n\t\t<p>I formed this cyclic stream using a fifo:</p>\n<div class=\"code\">\n$ mkfifo /tmp/CmdlineGL_fifo<br/>\n$ Script.sh &lt; /tmp/CmdlineGL_fifo | CmdlineGL &gt; /tmp/CmdlineGL_fifo\n</div>\n\t\t<p>And then the rest was simple:  script reads user input from stdin, script generates\n\t\tframe of output commands to stdout, and repeat.\n\t\t</p>\n\t</li>\n\t<li><h4>Bash does not support asynchronous IO</h4>\n\t\t<p>The next problem of course, was that if the user doesn't type anything, a call\n \t\tto \"read\" will block.\n\t\tRead actually does have a timeout feature, but in granularity of seconds,\n\t\tand a timeout of 0 doesn't seem to work.  So, I just changed my design a little\n\t\tto ensure that there is always a line to read from stdin. Thus the existance of the\n\t\t\"cglEcho\" command.  At the beginning of the script, and after reading user input on\n\t\teach frame, I write \"cglEcho&nbsp;_____\".  CmdlineGL sees the echo command, and echoes\n\t\tthe argument back to me.  Then, next time I read through stdin I stop after seeing\n\t\t\"_____\" because it means I've processed a whole frame's worth of user input.\n\t\t</p>\n\t\t<p>The cglEcho command actually became obsolete, with the arrival of cglGetTime, as you\n\t\twill see in my next point.  I left cglEcho as it was, though.\n\t\t</p>\n\t</li>\n\t<li><h4>Keeping pace with the processor</h4>\n\t\t<p>One of the more classic video game problems is making sure that the game runs the\n\t\tsame speed on all machines.  When playing a video, you need to keep the frame rate\n\t\tsteady, and when running a game engine you need to make sure that the framerate\n\t\tdoesn't affect the speed of the gameplay.\n\t\t</p>\n\t\t<p>Since Bash doesn't really have a way of keeping time (other than 'date', haha)\n\t\tI decided to put frame-limiting and time counting on the CmdlineGL side.\n\t\tWhen CmdlineGL starts it marks the current time, and thereafter can subtract that from\n\t\tthe current time to get elapsed game-time.  There are two ways to take advantage\n\t\tof game-time:  The first is using \"cglSync&nbsp;T\" which tells CmdlineGL to wait until\n\t\ttime T before processing any more commands.  The second is \"cglGetTime\", which causes\n\t\tCmdlineGL to write the current time (in milliseconds) to stdout.  The script can then\n\t\tprocess time differences to adjust the progress it displays in each frame.\n\t\t</p>\n\t\t<p>Additionally, there is a cglSleep function, which causes CmdlineGL to sleep for a\n\t\tnumber of milliseconds.  This would be useful in animated text movies to put a pause\n\t\tat certian points regardless of the frame rate.\n\t\t</p>\n\t</li>\n\t<li><h4>Math.. or lack thereof</h4>\n\t\t<p>So, one of the first major obstacles I hit when porting my walking robot demo from C\n\t\tto bash was the lack of floating point support.\n\t\tIt seemed obvious that calling bc for all my math operations would be a bit slow.\n\t\tAt first, I tried writing functions that would string-manipulate a floating point number\n\t\tto fixed point, perform the calculation, and then string-manipulate back.  This involved\n\t\ta lot of back-quote substitutions, and was slow.  So, I needed a way to use integers.\n\t\tWhy not just use glScale?  Well, mainly because that won't scale the angles of the\n\t\tglRotate command, and the robot was looking a little jerky with whole degree rotations.\n\t\t</p>\n\t\t<p>So... against my instincts for good design, I added a 'feature' to CmdlineGL that\n\t\tcauses it to look for fixed-point numbers any place it would normally expect floating point.\n\t\tImplementing this was rather simple, though: I made a \"cglFixedPt &lt;x&gt;\" function that\n\t\ttakes a parameter X, calculates 1/X, and multiplies all future floating point numbers\n\t\tby this amount.  The fact that the script is sending integers is then irrelevant.\n\t\t</p>\n\t\t<p>\n\t</li>\n\t</ul>\n\t<h2>\"How much time did you waste on this??\"</h2>\n\t<p>Less time than I wasted on World of Warcraft</p>\n\t<h2>\"So, what can I do to... 'Repay' you for this?\"</h2>\n\t<p>If you were thinking along the lines of thanks: bug fixes, implementing more of\n\tthe OpenGL commands, bug reports, money, pizza, sending Morrowgrain to Zellin\n\ton Earthen Ring (if you don't know what that means, don't worry about it), etc.\n\t</p>\n\t<p>If you were thinking more along the lines of revenge, you could try using CmdlineGL\n \tto write a multiplayer racing game (like a Mario Cart clone or something) in Prolog.\n\t</p>\n\t<h2>\"Where's the Windows version?\"</h2>\n\t<p>The Windows version is the same as the Linux version.\n\tYou'll just need to edit the source code a little before you can run it.  ;-)\n\t</p>\n\t<p>At the moment, the unix-specific things in this code are the asynchronous IO,\n\tthe fifo's, and the timing.  If you replace all the 'open' and 'read' with CreateFile and\n\tReadFile, comment out the fifo stuff, and replace gettimeofday and usleep with GetCurrentTime\n\tand Sleep (remember that it'll change microseconds to milliseconds), it just might work on\n\tWindows.  Then all you need is bash, which can be gotten from Cygwin.  You will still need\n\tsome way of creating the stdin/stdout loop between the script and CmdlineGL, and I'm not\n\tgoing to even investigate that.\n\t</p>\n\t<p>I really can't see any reason why you'd want to do this on Windows (unless\n\tperhaps your graphics card isn't accelerated under X).  One alternative is to\n\tinstall Cygwin and then export the display of your script to the windows box.\n\tThat only works of you have two machines, of course.  Anyway, it's your time,\n\tbut if you get a windows version working I'll gladly host it.\n\t</p>\n\t<h2 id=\"credits\">Credits</h2>\n\t<ul><li>Bob Zimbinski, for <a href=\"https://web.archive.org/web/20100127215948/http://webpages.mr.net/bobz/ttyquake/\">inspiring the format</a> of this page.</li>\n\t<li>Jeff Molofee, of <a href=\"http://nehe.gamedev.net/\">nehe.gamedev.net</a>, for providing an excellent OpenGL resource to the community.</li>\n\t<li>All the fellow nerds at (the former) UC's Labratory for Recreational Computing whose looks of pure horror and disgust inspired me to finish the project.</li>\n\t</ul>\n</body>\n</html>\n"
  },
  {
    "path": "script/Makefile.in",
    "content": "SHELL = /bin/sh\nPERL = perl\nPOD2MAN = pod2man\nPROVE = prove\nGZIP = gzip\nINSTALL = install\nCURRENT_UNIX_TIMESTAMP = $(shell date \"+%s\")\n\nall: CmdlineGL CmdlineGL.1\n\n.SUFFIXES:\n.SUFFIXES: .c .o\n\nprefix = @prefix@\nexec_prefix = @exec_prefix@\nbindir = @bindir@\nprojroot= @srcdir@/..\nsrcdir = @srcdir@/../src\nscriptdir = @srcdir@\ndocdir = @srcdir@/../doc\ndatarootdir = @datarootdir@\nsysconfdir = @sysconfdir@\nlocalstatedir = @localstatedir@\nrunstatedir = $(localstatedir)/run\nmandir = @mandir@\n\nOBJ_FILES=SymbolHash.o Server.o ProcessInput.o ParseGL.o Global.o Contained_RBTree.o IntConstHash.autogen.o CmdHash.autogen.o ImageLoader.o Font.o\nAUTOGEN_SRC=IntConstHash.autogen.c CmdHash.autogen.c Version.autogen.c ConstList.txt\nCOMMAND_SOURCES:=$(shell grep -l COMMAND $(srcdir)/*.c | sort -r )\n\nCFLAGS = @CFLAGS@ -MMD -MP -Wall\nCPPFLAGS = @CPPFLAGS@ -I. -I$(srcdir)\nLDFLAGS = @LDFLAGS@\nLIBS = @LIBS@\n\nDEP_FILES := $(shell touch _empty.d; echo *.d)\ninclude $(DEP_FILES) @dev_include_makefile@\n\n%.autogen.o: %.autogen.c\n\t$(CC) -o $@ $(CPPFLAGS) -c $< $(CFLAGS)\n\n%.o: $(srcdir)/%.c\n\t$(CC) -o $@ $(CPPFLAGS) -c $< $(CFLAGS)\n\nCmdlineGL: $(AUTOGEN_SRC) $(OBJ_FILES)\n\t$(CC) -o $@ $(CPPFLAGS) -DCURRENT_UNIX_TIMESTAMP=$(CURRENT_UNIX_TIMESTAMP) $(OBJ_FILES) Version.autogen.c $(CFLAGS) $(LDFLAGS) $(LIBS)\n\n# no deps for ConstList.txt because users might need to edit it by hand\nConstList.txt:\n\t@echo \"-> Attempting to get the useful #define'd constants from your GL headers...\"\n\tPROJROOT=\"$(projroot)\" CPP=\"$(CPP)\" CFLAGS=\"$(CFLAGS)\" CPPFLAGS=\"$(CPPFLAGS)\" $(scriptdir)/build-constlist.sh <$(srcdir)/ConstList.works_for_me >$@.tmp && mv $@.tmp $@\n\nIntConstHash.autogen.o: IntConstHash.autogen.c\n\nIntConstHash.autogen.c: ConstList.txt $(scriptdir)/build-consthash.pl\n\t@echo \"-> Regenerating IntConstHash.autogen.c from the names in ConstList.txt\"\n\t$(PERL) $(scriptdir)/build-consthash.pl <ConstList.txt >$@.tmp && mv $@.tmp $@\n\nCmdHash.autogen.o: CmdHash.autogen.c\n\nCmdHash.autogen.c: $(COMMAND_SOURCES) $(scriptdir)/build-cmdhash.pl\n\t@echo \"-> Regenerating CmdHash.autogen.c from the \\\"COMMAND\\\" functions in *.c\"\n\tcat $(COMMAND_SOURCES) | $(PERL) $(scriptdir)/build-cmdhash.pl >$@.tmp && mv $@.tmp $@\n\nVersion.autogen.c: $(projroot)/Changes $(scriptdir)/build-version.sh\n\tPROJROOT=\"$(projroot)\" $(scriptdir)/build-version.sh >$@.tmp && mv $@.tmp $@\n\nCmdlineGL.lib: $(srcdir)/\n\nCmdlineGL.1: $(srcdir)/manual.head.pod $(COMMAND_SOURCES) $(srcdir)/manual.tail.pod Version.autogen.c\n\t$(PERL) $(scriptdir)/build-manual.pl --as=man --version=\"`sed -n '/CGLVER_String=/s/.*=\"\\(.*\\)\".*/\\1/p' Version.autogen.c`\" $^ >$@.tmp && mv $@.tmp $@\n\nCmdlineGL.html: CmdlineGL.1\n\tman ./$^ | man2html >$@.tmp && mv $@.tmp $@\n\nCmdlineGL.1.gz: CmdlineGL.1\n\t$(GZIP) < CmdlineGL.1 > $@.tmp && mv $@.tmp $@\n\ninstall: CmdlineGL CmdlineGL.1.gz\n\t$(INSTALL) -d \"$(DESTDIR)$(bindir)/\"\n\t$(INSTALL) -d \"$(DESTDIR)$(mandir)/man1/\"\n\t$(INSTALL) -d \"$(DESTDIR)$(datarootdir)/CmdlineGL/\"\n\t$(INSTALL) -m 755 CmdlineGL \"$(DESTDIR)$(bindir)/\"\n\t$(INSTALL) -m 644 CmdlineGL.1.gz \"$(DESTDIR)$(mandir)/man1/\"\n\ttouch \"$(DESTDIR)$(datarootdir)/CmdlineGL/something\" && rm -r \"$(DESTDIR)$(datarootdir)/CmdlineGL/\"*\n\tcp -r \"$(projroot)/share/\"* \"$(DESTDIR)$(datarootdir)/CmdlineGL/\"\n\tsed -e 's|@share_path@|$(DESTDIR)$(datarootdir)/CmdlineGL|g' <'$(projroot)/share/CmdlineGL.lib' >'$(DESTDIR)$(datarootdir)/CmdlineGL/CmdlineGL.lib'\n\tln -sf \"$(DESTDIR)$(datarootdir)/CmdlineGL/CmdlineGL.lib\" \"$(DESTDIR)$(bindir)/\"\n\nMakefile: config.status $(scriptdir)/Makefile.in $(scriptdir)/config.h.in $(scriptdir)/config-defs.h.in\n\t./config.status && touch Makefile\n\nconfig.status: $(scriptdir)/configure $(scriptdir)/config-defs.h.in\n\t$(scriptdir)/configure $$(./config.status --config)\n\ntest: CmdlineGL\n\t$(PROVE) -j4 $(srcdir)/../test\n\nclean:\n\trm -f -- *.o\n\trm -f -- *.d\n\trm -f -- CmdlineGL*\n\trm -f -- *.tmp\n\n.PHONY: install test clean\n"
  },
  {
    "path": "script/build-cmdhash.pl",
    "content": "#! /usr/bin/env perl\n\n=head1 DESCRIPTION\n\nGenerates static hash table of commands by parsing C source.\n\n=cut\n\nuse strict;\nuse warnings;\n\nmy @commands;\n\nwhile (<STDIN>) {\n\t# Look for COMMAND(cmd, \"args\")\n\tpush @commands, { name => $1, arg_format => $2 }\n\t\tif ($_ =~ m|^\\s*COMMAND\\s*\\(\\s*(\\S+)\\s*,\\s*\"(\\S*)\"\\s*\\)|);\n}\n@commands= sort { $a->{name} cmp $b->{name} } @commands;\n\n# table size is 1.5 x number of entries rounded up to power of 2.\nmy $mask= int(2 * @commands);\n$mask |= $mask >> 1;\n$mask |= $mask >> 2;\n$mask |= $mask >> 4;\n$mask |= $mask >> 8;\n$mask |= $mask >> 16;\nmy $scan_dist= 1;\nmy $table_size= $mask+1+$scan_dist;\n\nsub build_table {\n\tmy ($mul, $shift)= @_;\n\tmy @table= (0) x $table_size;\n\tname: for my $ci (0..$#commands) {\n\t\tmy $bucket= hash_fn($commands[$ci]{name}, $mul, $shift);\n\t\tfor (0..$scan_dist) {\n\t\t\tif (!$table[$bucket+$_]) {\n\t\t\t\t$table[$bucket+$_]= $ci+1; # 1-based\n\t\t\t\tnext name;\n\t\t\t}\n\t\t}\n\t\treturn undef;\n\t}\n\treturn \\@table;\n}\n\nsub find_collisionless_hash_params {\n\t# pick factors for the hash function until each command has a unique bucket\n\tfor (my $mul= 1; $mul < $table_size*$table_size; $mul++) {\n\t\tfor (my $shift= 1; $shift < 11; $shift++) {\n\t\t\tmy $table= build_table($mul, $shift);\n\t\t\treturn ( $table, $mul, $shift )\n\t\t\t\tif $table;\n\t\t}\n\t}\n\tdie \"No value of \\$shift / \\$mul results in unique codes for each command\\n\";\n}\n\nmy ($table, $mul, $shift)= find_collisionless_hash_params();\n\nmy $cmd_prototypes= join '', map \"extern bool cmd_$_->{name}(struct ParseParamsResult *parsed);\\n\", @commands;\nmy $i= 1;\nmy $list_items=     join '', map sprintf(qq|/* %4d */ { \"%s\", \"%s\", cmd_%s },\\n|, $i++, $_->{name}, $_->{arg_format}, $_->{name}), @commands;\nmy $hash_entries= '';\nfor (0..$#$table) {\n\t$hash_entries .= \"\\n\" if $_ && !($_ & 0xF);\n\t$hash_entries .= sprintf(\" %4d,\", $table->[$_]);\n}\n\n# This must be kept in sync with the C version.\n# Use a mask similar to a 32-bit register's effect to make sure Perl\n# behaves the same way as C regardless of Perl's integer width, and\n# then tell C to explicitly use 32-bit math.\nsub hash_fn {\n\tmy ($string, $mul, $shift)= @_;\n\tuse integer;\n\tmy $i32_mask= (1<<(32-$shift))-1;\n\tmy $x= 0;\n\tfor (unpack( 'C' x length($string), $string )) {\n\t\t$x= ((($x * $mul) >> $shift) & $i32_mask) + $_;\n\t}\n\treturn $x & $mask;\n}\n\nprint <<END;\n// File generated by $0\n//\n// ${\\scalar @commands} commands\n// table size is $table_size, mul is $mul, shift is $shift\n#include \"config.h\"\n#include <inttypes.h>\n#include <string.h>\n#include \"ProcessInput.h\"\n#include \"SymbolHash.h\"\n\nint CmdHashFunc(const char *name) {\n\tuint32_t x= 0;\n\twhile (*name)\n\t\tx= ((x * $mul) >> $shift) + (*name++ & 0xFF);\n\treturn x & $mask;\n}\n\n$cmd_prototypes\n\nconst int CmdListCount= ${\\scalar @commands};\nconst CmdListEntry CmdList[]= {\n\t{ NULL, NULL, NULL },\n$list_items\n\t{ NULL, NULL, NULL },\n};\nconst int CmdHashTableSize= $table_size;\nconst uint16_t CmdHashTable[]= {\n$hash_entries\n\t0\n};\n\nconst CmdListEntry *GetCmd(const char *Name) {\n\tint code= CmdHashFunc(Name);\n\tint lim= code + $scan_dist + 1;\n\t/* scan forward at most $scan_dist table entries looking for the given Name.\n\t * No need to wrap, because the table is longer than the hash function mask. */\n\twhile (code < lim) {\n\t\tif (CmdHashTable[code] && strcmp(CmdList[CmdHashTable[code]].Name, Name) == 0)\n\t\t\treturn &CmdList[CmdHashTable[code]];\n\t\tcode++;\n\t}\n\treturn NULL;\n}\n\nEND\n"
  },
  {
    "path": "script/build-consthash.pl",
    "content": "#! /usr/bin/env perl\n\n=head1 DESCRIPTION\n\nGenerates static hash table of commands by parsing C source.\n\n=cut\n\nuse strict;\nuse warnings;\n\nmy %consts;\n\nwhile (<STDIN>) {\n\t$_ =~ /(\\w+)/ and $consts{$1}= 1;\n}\nmy @constlist= sort keys %consts;\n\n# table size is 2 x number of entries rounded up to power of 2.\nmy $mask= int(2 * @constlist);\n$mask |= $mask >> 1;\n$mask |= $mask >> 2;\n$mask |= $mask >> 4;\n$mask |= $mask >> 8;\n$mask |= $mask >> 16;\nmy $scan_dist= 4;\nmy $table_size= $mask+1+$scan_dist;\n\nsub build_table {\n\tmy ($mul, $shift)= @_;\n\tmy @table= (0) x $table_size;\n\tname: for my $ci (0..$#constlist) {\n\t\tmy $bucket= hash_fn($constlist[$ci], $mul, $shift);\n\t\tfor (0..$scan_dist) {\n\t\t\tif (!$table[$bucket+$_]) {\n\t\t\t\t$table[$bucket+$_]= $ci+1; # 1-based index\n\t\t\t\tnext name;\n\t\t\t}\n\t\t}\n\t\treturn undef;\n\t}\n\treturn \\@table;\n}\n\nsub find_collisionless_hash_params {\n\t# pick factors for the hash function until each command has a unique bucket\n\tfor (my $mul= 1; $mul < $table_size*$table_size; $mul++) {\n\t\tfor (my $shift= 1; $shift < 5; $shift++) {\n\t\t\tmy $table= build_table($mul, $shift);\n\t\t\treturn ( $table, $mul, $shift )\n\t\t\t\tif $table;\n\t\t}\n\t}\n\tdie \"No value of \\$shift / \\$mul results in unique codes for each command\\n\";\n}\n\nmy ($table, $mul, $shift)= find_collisionless_hash_params();\n\nmy $i= 1;\nmy $const_entries= join(\"\\n\", map sprintf(' /* %4d */ { \"%s\", (long)(%s) },', $i++, $_, $_), @constlist);\n\nmy $hash_entries= '';\nfor (0..$#$table) {\n\t$hash_entries .= \"\\n\" if $_ && !($_ & 0xF);\n\t$hash_entries .= sprintf(\" %4d,\", $table->[$_]);\n}\n\n# This must be kept in sync with the C version.\n# Use a mask similar to a 32-bit register's effect to make sure Perl\n# behaves the same way as C regardless of Perl's integer width, and\n# then tell C to explicitly use 32-bit math.\nsub hash_fn {\n\tmy ($string, $mul, $shift)= @_;\n\tuse integer;\n\tmy $i32_mask= (1<<(32-$shift))-1;\n\tmy $result= 0;\n\t$result= ((($result * $mul) >> $shift) & $i32_mask) + ($_ << 4)\n\t\tfor unpack( 'C' x length($string), $string );\n\treturn $result & $mask;\n}\n\nprint <<END;\n// File generated by $0\n//\n// ${\\scalar @constlist} constants\n// table size is $table_size, mul is $mul, shift is $shift, scan_dist is $scan_dist\n#define INCLUDE_SDL\n#define INCLUDE_GL\n#include \"config.h\"\n#include \"ProcessInput.h\"\n#include \"SymbolHash.h\"\n\nint IntConstHashFunc(const char *name) {\n\tuint32_t x= 0;\n\twhile (*name)\n\t\tx= ((x * $mul) >> $shift) + ((*name++ & 0xFF) << 4);\n\t\n\treturn x & $mask;\n}\n\nconst int IntConstListCount= ${\\scalar @constlist};\nconst IntConstListEntry IntConstList[]= {\n\t{ NULL, 0 },\n$const_entries\n\t{ NULL, 0 }\n};\nconst int IntConstHashTableSize= $table_size;\nconst uint16_t IntConstHashTable[]= {\n$hash_entries\n};\n\nconst IntConstListEntry *GetIntConst(const char *Name) {\n\tint code= IntConstHashFunc(Name);\n\tint lim= code + $scan_dist + 1;\n\t/* scan forward at most $scan_dist table entries looking for the given Name.\n\t * No need to wrap, because the table is longer than the hash function mask. */\n\twhile (code < lim) {\n\t\tif (IntConstHashTable[code] && strcmp(IntConstList[IntConstHashTable[code]].Name, Name) == 0)\n\t\t\treturn &IntConstList[IntConstHashTable[code]];\n\t\tcode++;\n\t}\n\treturn NULL;\n}\n\nEND\n"
  },
  {
    "path": "script/build-constlist.sh",
    "content": "#! /bin/sh\nset -eu\n\n[ -n \"${CPP}\" ] && [ -n \"$PROJROOT\" ] \\\n\t|| { echo \"Require variables PROJROOT, CPP, CFLAGS, CPPFLAGS\" >&2; exit 1; }\n\n{\n\techo \"#define INCLUDE_SDL\";\n\techo \"#define INCLUDE_GL\";\n\techo \"#include \\\"config.h\\\"\";\n\twhile read ConstName; do\n\t\t\techo \"#ifdef $ConstName\";\n\t\t\techo \"validconst_$ConstName\";\n\t\t\techo \"#endif\";\n\tdone;\n} | ${CPP} ${CFLAGS} ${CPPFLAGS} - | grep validconst_ \\\n  | sed -e 's/validconst_\\(.*\\)$/\\1/'\n\n(\necho\necho \"  ConstList.txt has been generated by taking my own machine's valid list of\"\necho \"  constants and running it through your preprocessor.  Hopefully it works\"\necho \"  for you.  If not, try grepping your GL header files for #define GL*, and\"\necho \"  put the name of every constant you'd like to have at runtime into the\"\necho \"  ConstList.txt file.\"\necho \"  Note that CmdlineGL can only use integer constants, and not all GL_* are.\"\necho \"  Also beware: 'make clean' will remove it!\"\necho\n) >&2\n"
  },
  {
    "path": "script/build-dist.pl",
    "content": "#! /usr/bin/perl\nuse strict;\nuse warnings;\nopen(STDERR, '>&STDOUT');\n\n# Run a command like 'make', but capture the output, and show the output if it fails.\nsub run {\n\tmy ($out, $cmd_fh);\n\tlocal $/= undef;\n\tunless (open($cmd_fh, '-|', @_) and do { $out= <$cmd_fh>; close $cmd_fh }) {\n\t\t$|= 1;\n\t\tprint $out;\n\t\tmy $exitreason= $? == -1? \"exec: $!\" : $? & 0x7F? \"died on signal \".($?&0x7F) : \"exited with code \".($?>>8);\n\t\tdie \"Command failed: \\\"\".join('\" \"', @_).\"\\\": $exitreason\\n\";\n\t}\n\t$out;\n}\n\nmy $proj_root= $ENV{PROJROOT};\n-d \"$proj_root/src\" and -d \"$proj_root/script\"\n\tor die \"Incorrect PROJROOT \\\"$proj_root\\\"\\n\";\n\n# Verify we have all changes checked in\n\nmy $uncommitted= run('git',\"--git-dir=$proj_root/.git\",\"--work-tree=$proj_root\",'status','--porcelain');\n$uncommitted =~ /\\S/\n\tand die \"Uncommitted git changes!\";\n\n# Git HEAD should be tagged same as Changes file\n\nchomp(my $git_head= run('git','log','-n','1','--format=format:%H%d'));\n$git_head =~ /tag: v([^,) ]+)/ or die \"HEAD lacks a tag: \\\"$git_head\\\"\\n\";\nmy $git_ver= $1;\nopen(my $changes_fh, '<', \"$proj_root/Changes\") or die \"open(Changes): $!\";\nmy $changes_ver_line= <$changes_fh>;\n$changes_ver_line =~ /Version ([^. ]+\\.[^. ]+\\.[^. ]+) / or die \"Unexpected format in Changes: \\\"$changes_ver_line\\\"\\n\";\nmy $changes_ver= $1;\n\n$git_ver eq $changes_ver or die \"Version Mismatch between git ($git_ver) and Changes ($changes_ver)\\n\";\n\n# Clone project into a temporary directory\n\nrun('rm', '-rf', \"$proj_root/dist/next\");\nmkdir \"$proj_root/dist\";\nmkdir \"$proj_root/dist/next\";\nmy $dest_dir= \"$proj_root/dist/next\";\n\nmy $out;\n$out= run('git',\"--work-tree=$dest_dir\",\"--git-dir=$proj_root/.git\",'checkout','.');\n\n# Remove debug and dev configuration that we added by default\n\nrun('sed', '-i', '-e', 's/--enable-debug/--disable-debug/', \"$dest_dir/configure\");\n\n# Test that we can compile and build it\n\nrun('make','-C',$dest_dir,'all');\nrun('make','-C',\"$dest_dir/build\",'test');\n\n# If that worked, wipe the build dir and zip it!\n\nmy $distname= \"CmdlineGL-$changes_ver\";\nrun('rm', '-rf', \"$dest_dir/build\");\nrename $dest_dir, \"$proj_root/dist/$distname\" or die \"rename to \\\"$proj_root/dist/$distname\\\" failed: $!\";\nrun('tar', '-C', \"$proj_root/dist\", '-cjf', \"$proj_root/dist/$distname.tar.bz2\", $distname);\n\nprint \"\\nBuilt $proj_root/dist/$distname.tar.bz2\\n\\n\";\n\n"
  },
  {
    "path": "script/build-manual.pl",
    "content": "#! /usr/bin/env perl\nuse strict;\nuse warnings;\nuse Pod::Man;\nuse Getopt::Long;\n\nGetOptions(\n\t'as=s'      => \\(my $opt_as),\n\t'version=s' => \\(my $opt_version),\n\t'help|h'    => sub { print \"Usage:  $0 [--as=pod|man] header.pod *.c footer.pod\\n\\n\"; exit 1; },\n) or die;\n\n# Merge all identically named head1 and head2 sections.  This allows multiple source files\n# to contribute to the same section of documentation without needing to rearrange the code\n# to match, and lets the manual.head.pod determine where everything will go in the document.\nmy @head1;\nmy %head1_by_name;\nmy $current_h1;\nmy $current_h2;\nmy $current_pod;\nwhile (<>) { # there are nicer ways to do this, but I'm aiming for no non-core deps\n\tif ($_ =~ m{^(/\\*)?=(\\w+)\\s*(.*?)\\s*$}) {\n\t\t$_= substr($_, 2) if $1;\n\t\tif ($2 eq 'head1') {\n\t\t\t$current_h2= undef;\n\t\t\t$current_h1= $head1_by_name{$3} ||= do {\n\t\t\t\tmy $h1= { name => $3, pod => '', head2 => [], head2_by_name => {} };\n\t\t\t\tpush @head1, $h1;\n\t\t\t\t$h1;\n\t\t\t};\n\t\t\t$current_pod= \\$current_h1->{pod};\n\t\t}\n\t\telsif ($2 eq 'head2') {\n\t\t\tdefined $current_h1 or die \"got head2 before head1\";\n\t\t\t$current_h2= $current_h1->{head2_by_name}{$3} ||= do {\n\t\t\t\tmy $h2= { name => $3, pod => '', items => [] };\n\t\t\t\tpush @{ $current_h1->{head2} }, $h2;\n\t\t\t\t$h2;\n\t\t\t};\n\t\t\t$current_pod= \\$current_h2->{pod};\n\t\t}\n\t\telsif ($2 eq 'item' and $current_h1->{name} eq 'COMMANDS' && defined $current_h2) { # only capture =item if it was part of COMMAND section\n\t\t\tmy $i= { name => $3, pod => '' };\n\t\t\tpush @{ $current_h2->{items} }, $i;\n\t\t\t$current_pod= \\$i->{pod};\n\t\t}\n\t\t# if \"cut\", end the current part\n\t\telsif ($2 eq 'cut') {\n\t\t\t$current_pod= undef;\n\t\t}\n\t\telsif (!defined $current_pod) {\n\t\t\tdie \"Found POD directive with no current head1/head2/item: $_\";\n\t\t}\n\t\telse {\n\t\t\t$$current_pod .= $_;\n\t\t}\n\t}\n\telsif ($current_pod) {\n\t\t$$current_pod .= $_;\n\t}\n}\n\n# Now re-flatten the sections into a document\nmy $doc= '';\nfor my $h1 (@head1) {\n\t$doc .= \"=head1 $h1->{name}\\n\\n$h1->{pod}\\n\\n\";\n\tfor my $h2 (@{ $h1->{head2} }) {\n\t\t$doc .= \"=head2 $h2->{name}\\n\\n$h2->{pod}\\n\\n\";\n\t\tif (@{ $h2->{items} }) {\n\t\t\t$doc .= \"=over\\n\\n\";\n\t\t\tfor my $item (@{ $h2->{items} }) {\n\t\t\t\t$doc .= \"=item $item->{name}\\n\\n$item->{pod}\\n\\n\";\n\t\t\t}\n\t\t\t$doc .= \"=back\\n\\n\";\n\t\t}\n\t}\n}\n\n# remove redundant empty lines\n$doc =~ s/\\n\\n\\n+/\\n\\n/g;\n\n# Either output POD or run it through Pod::Man\nif (lc($opt_as) eq 'pod') {\n\tprint $doc;\n}\nelsif (lc($opt_as) eq 'man') {\n\topen( my $doc_fh, '<', \\$doc ) or die;\n\tPod::Man->new(\n\t\tname => 'CmdlineGL',\n\t\trelease => $opt_version,\n\t\tsection => 1,\n\t\tcenter => 'General Commands',\n\t\terrors => 'die',\n\t)->parse_from_file($doc_fh);\n}\nelsif (lc($opt_as) eq 'html') {\n\trequire Pod::Html;\n\trequire File::Temp;\n\tmy $tmp= File::Temp->new;\n\t$tmp->print($doc);\n\t$tmp->seek(0,0);\n\tmy $html_tmp= File::Temp->new;\n\tPod::Html::pod2html(\"--infile=$tmp\", \"--outfile=$html_tmp\", \"--title=CmdlineGL\");\n\t$html_tmp->seek(0,0);\n\tlocal $/= undef;\n\tmy $html= <$html_tmp>;\n\tmy $html_head= <<END;\n<!DOCTYPE html>\n<html>\n<head>\n  <title>CmdlineGL</title>\n  <link rel=\"stylesheet\" href=\"yamb.css\" type=\"text/css\" />\n  <meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />\n  <style>\n  html { margin: 0 2%; }\n  body { margin: .5em auto 2em auto; max-width: 60em; }\n  dl { margin: 0 .5em 0 0; }\n  dt { margin: 0; font-family: \"Consolas\", \"Inconsolata\", \"Courier New\", monospace; }\n  dd { margin: .5em 1em 1em 2em; }\n  ul, ol { padding-left: 2.5em; list-style-position: outside; }\n  #index { float: right; margin: 2em 1em;}\n  #index, #index ul { list-style-type: none; padding-left: 1em; }\n  code { max-width: 50em; }\n  pre { margin: .5em 0; }\n  </style>\n</head>\nEND\n\t$html =~ s,.*?</head>,$html_head,s;\n\tprint $html;\n}\nelse {\n\tdie \"Unknown format $opt_as\"\n}\n"
  },
  {
    "path": "script/build-version.sh",
    "content": "#! /bin/sh\n\n[ -n \"$PROJROOT\" ] || { echo \"Require environment var PROJROOT\" >&2; exit 1; }\n\necho \" -> Checking Version\" >&2\nversion_parts=$(grep -i version $PROJROOT/Changes | head -n 1 | sed -ne 's/Version *\\([0-9]*\\)\\.\\([0-9]*\\)\\.\\([0-9]*\\)[^0-9]*\\([-0-9]*\\)/\\1 \\2 \\3 \\4/p')\nread major minor release date <<END\n$version_parts\nEND\nextra=''\nif [ -z \"$major\" -o -z \"$date\" ]; then\n\techo \"Can't get version from ./Changes\" >&2\n\texit 1\nfi\necho \"    Changes version is $major.$minor.$release ($date)\" >&2\n\nif [ -d \"$PROJROOT/.git\" ]; then\n\texport GIT_DIR=\"$PROJROOT/.git\"\n\texport GIT_WORK_TREE=\"$PROJROOT\"\n\thead_hash=$(git log -n 1 --format=format:%h)\n\ttag_hash=$(git log -n 1 --format=format:%h v$major.$minor.$release -- 2>/dev/null)\n\tgit_dirty=$(git status --porcelain | wc -l)\n\tif [ \"$git_dirty\" -gt 0 -o \"$tag_hash\" != \"$head_hash\" ]; then\n\t\techo \"    Git state differs from ./Changes\" >&2\n\t\textra=\"$head_hash\"\n\t\tdate=\"$(git log -n 1 --format=format:%ci | sed -e 's/ /T/;s/ //')\"\n\t\tif [ \"$git_dirty\" -gt 0 ]; then\n\t\t\textra=\"$extra+changes\"\n\t\t\tdate=`date \"+%Y-%m-%dT%H:%M:%S\"`;\n\t\tfi\n\tfi\nfi\n\necho \"    Version is $major $minor $release $extra $date\" >&2;\n\n[ -n \"$extra\" ] && suffix=\"-$extra\" || suffix='';\n\necho \" -> Regenerating Version.c\" >&2\ncat <<END\n/* Generated by build-version.sh */\n\nconst int CGLVER_Major=$major;\nconst int CGLVER_Minor=$minor;\nconst int CGLVER_Release=$release;\nconst char* CGLVER_Extra=\"$extra\";\nconst char* CGLVER_Date=\"$date\";\nconst char* CGLVER_String=\"$major.$minor.$release$suffix\";\n\nEND\n"
  },
  {
    "path": "script/config.h.in",
    "content": "/* This header pulls in everything system-dependent.  No other files in the project\n * should depend on any header other than this and the headers in the src/ directory.\n */\n\n/* contains autoconf -D equivalents */\n#include <config-defs.h>\n\n/* ------------------------------------\n * Basics\n */\n\n#ifdef _WIN32\n#  define WIN32_LEAN_AND_MEAN\n#  include <windows.h>\n#else\n#  ifndef _GNU_SOURCE\n#    define _GNU_SOURCE\n#  endif\n#  include <sys/un.h>\n#  include <sys/types.h>\n#  include <sys/stat.h>\n#  include <unistd.h>\n#  include <fcntl.h>\n#  include <errno.h>\n#endif\n\n#include <stdint.h>\n#include <stdio.h>\n#include <string.h>\n#include <ctype.h>\n#include <stdlib.h>\n#include <string.h>\n#include <assert.h>\n#include <stdarg.h>\n\n/* ------------------------------------\n * Caller can set INCLUDE_GL before config.h to pull in all the GL headers\n */\n\n#include <@gl_header@>\n#include <@glu_header@>\n\n/* These were missing on some platforms and this worked to solve it... */\n#ifndef GL_BGR\n#  define GL_BGR GL_BGR_EXT\n#  define GL_BGRA GL_BGRA_EXT\n#endif\n\n#ifdef HAVE_LIBFTGL\n#  include <@ftgl_header@>\n#endif\n\n/* ------------------------------------\n * Caller can set INCLUDE_SDL before config.h to pull in SDL headers\n */\n\n#ifdef INCLUDE_SDL\n#  include <@sdl_header@>\n#  ifdef HAVE_LIBSDL_IMAGE\n#    include <@sdl_image_header@>\n#  endif\n#endif\n\n/* ------------------------------------\n * Now muck around with things we shouldn't, since we're not including\n * any more system headers beyond this point.\n */\n\n#ifndef NULL\n#  define NULL ((void*)0)\n#endif\n\n#if HAVE_STDBOOL\n#  include <stdbool.h>\n#else\n#  ifndef bool\n#    define bool int\n#  endif\n#  ifndef true\n#    define true 1\n#  endif\n#  ifndef false\n#    define false 0\n#  endif\n#endif\n"
  },
  {
    "path": "script/configure.ac",
    "content": "AC_PREREQ([2.68])\nAC_INIT([CmdlineGL])\nAC_CONFIG_SRCDIR([config.h.in])\nAC_CONFIG_HEADER([config-defs.h])\n\nAC_ARG_ENABLE(debug,  AS_HELP_STRING([debug], [enable assertions and debug symbols]),\n [ if test \"$enableval\" != \"no\"; then CFLAGS=\"$CFLAGS -O0 -g3\"; else CFLAGS=\"$CFLAGS -O2 -DNDEBUG\"; fi; ],\n [ CFLAGS=\"$CFLAGS -O0 -g3\"; ])\n\nAC_ARG_ENABLE(dev,    AS_HELP_STRING([dev], [enable source generators (requires perl)]),\n [ if test \"$enableval\" != \"no\"; then dev_include_makefile=\"\\$(scriptdir)/dev-rules.mak\"; fi; ],\n [ dev_include_makefile=\"\"; ])\nAC_SUBST(dev_include_makefile)\n\n# Checks for programs.\nAC_PROG_CC\n\n# Checks for libraries.\nAC_CHECK_LIB(GL,glBegin)\nAC_CHECK_LIB(GLU,gluNewQuadric)\nAC_CHECK_LIB(ftgl,ftglCreateTextureFont)\nLDFLAGS=\"${LDFLAGS} `sdl-config --libs`\"\nAC_CHECK_LIB(SDL,SDL_Init)\nAC_CHECK_LIB(SDL_image,IMG_Load)\n\n# Checks for header files.\nAC_PATH_X\nif test \"X${x_includes}\" != \"X\"; then\n\tCFLAGS=\"${CFLAGS} -I${x_includes}\"\nfi\nAC_HEADER_STDC\nAC_CHECK_HEADERS([fcntl.h stdlib.h unistd.h stdbool.h stdint.h])\nAC_CHECK_HEADERS([GL/gl.h GL/glu.h],[AC_SUBST(gl_header,GL/gl.h) AC_SUBST(glu_header,GL/glu.h)],[AC_CHECK_HEADERS([OpenGL/gl.h OpenGL/glu.h],[AC_SUBST(gl_header,OpenGL/gl.h) AC_SUBST(glu_header,OpenGL/glu.h)],[AC_MSG_ERROR([Can't find OpenGL headers])])])\nCFLAGS=\"${CFLAGS} `sdl-config --cflags`\"\nAC_CHECK_HEADERS([SDL/SDL.h],[AC_SUBST(sdl_header,SDL/SDL.h)],[AC_MSG_ERROR([Can't find SDL header (apt-get install libsdl1.2-dev)])])\nAC_CHECK_HEADERS([SDL/SDL_image.h],[AC_SUBST(sdl_image_header,SDL/SDL_image.h)],[AC_MSG_ERROR([Can't find SDL_image header (apt-get install libsdl-image1.2-dev)])])\nCFLAGS=\"${CFLAGS} -I/usr/include/freetype2\"\nCPPFLAGS=\"${CPPFLAGS} -I/usr/include/freetype2\"\nAC_CHECK_HEADERS([FTGL/ftgl.h],[AC_SUBST(ftgl_header,FTGL/ftgl.h)],[AC_MSG_ERROR([Can't find FTGL header (apt-get install libftgl-dev)])])\n\n# Checks for typedefs, structures, and compiler characteristics.\nAC_HEADER_STDBOOL\nAC_C_CONST\nAC_C_INLINE\n\n# Checks for library functions.\nAC_CHECK_FUNCS([snprintf])\n\nAC_CONFIG_FILES([Makefile config.h])\nAC_OUTPUT\n"
  },
  {
    "path": "script/dev-rules.mak",
    "content": "# These rules are only needed for authoring CmdlineGL and don't need to be\n# active in the release tarball.  I wanted the auto-generated C files to\n# go here as well, but the hash tables depend on the available libraries\n# on the host system, so can't be generated in advance.\n\n$(scriptdir)/config-defs.h.in: $(scriptdir)/configure.ac\n\tcd $(scriptdir) && autoheader && touch $(scriptdir)/config-defs.h.in\n\n$(scriptdir)/configure: $(scriptdir)/configure.ac\n\tcd $(scriptdir) && autoconf\n\nautogen_files: $(scriptdir)/config-defs.h.in $(scriptdir)/configure\n\ndist: $(srcdir)/../.git\n\tenv PROJROOT=$(srcdir)/.. $(PERL) $(scriptdir)/build-dist.pl\n\n.PHONY: autogen_files dist\n"
  },
  {
    "path": "share/CmdlineGL.lib",
    "content": "#! /bin/bash\n# This script is a trampoline to detect shells and versions\n# ...but only Bash 3+ is supported at the moment.\n\n# First, make sure this script is being sourced\ncase \"$0\" in\n*/CmdlineGL.lib)\n\techo \"Usage: source /path/to/CmdlineGL.lib\"\n\texit 1\n\t;;\nesac\n\n# Then figure out where the lib path is\nCmdlineGL_SharePath=\"@share_path@\" # set by \"make install\"\nif [ ! -d \"@share_path@\" ]; then\n\t# Running from project dir, before \"make install\"\n\tCmdlineGL_SharePath=\"${BASH_SOURCE%/*}\"\nfi\nif [ ! -d \"$CmdlineGL_SharePath/lib-bash\" ]; then\n\techo \"Can't determine CmdlineGL share path (checked for '$CmdlineGL_SharePath/lib-bash')\"\n\treturn 1\nfi\n\n# Force safe defaults for paths.  Caller can modify these afterward.\nCmdlineGL_TexPath=\"$CmdlineGL_SharePath/textures\"\nCmdlineGL_FontPath=\"$CmdlineGL_SharePath/fonts\"\n# Then load the lib appropriate for this shell.  Right now bash is the only supported shell.\nif [ -n \"$BASH_VERSION\" ]; then\n\tCmdlineGL_LibPath=\"$CmdlineGL_SharePath/lib-bash\"\n\tsource \"$CmdlineGL_SharePath/lib-bash/CmdlineGL.lib\"\nelse\n\techo \"You must source this libary from bash.\"\n\techo \"No other shells are currently supported.\"\n\treturn 1;\nfi\n"
  },
  {
    "path": "share/examples/BrowseFonts.sh",
    "content": "#! /bin/bash\n#\n#  This example displays each font in the /usr/share directory by\n#  rendering it as an extruded font.  Iterate through the list with\n#  '[' and ']' keys.\n#\ntext=\"$1\";\nset -eu\n\nsource \"${BASH_SOURCE%/*}/../CmdlineGL.lib\" || die \"Can't find CmdlineGL.lib (${BASH_SOURCE%/*}/../CmdlineGL.lib)\";\nCmdlineGL_LoadLib RenderLoop ModelViewer\n\nfonts=( `find /usr/share -name '*.ttf' | grep -i mono` )\nfont_n=${#fonts[@]}\nfont_i=\n\nswap_font() {\n\tif [[ -n \"$font_i\" ]]; then ftglDestroyFont font1; else font_i=0; true; fi\n\techo \"$font_i/$font_n  ${fonts[font_i]}\"\n\t# Load font file and configure font rendering parameters\n\tftglCreateExtrudeFont font1 \"${fonts[font_i]}\"\n\tftglSetFontFaceSize   font1 72 72\n\tftglSetFontDepth      font1 20\n}\n\nnext_font() {\n\tif (( font_i + 1 < font_n )); then\n\t\tlet ++font_i\n\t\tswap_font\n\tfi\n}\nprev_font() {\n\tif (( font_i > 0 )); then\n\t\tlet font_i--\n\t\tswap_font\n\tfi\n}\n\nInit() {\n\t# Initialize CmdlineGL for rendering only (no input or feedback)\n\tglEnable GL_NORMALIZE GL_DEPTH_TEST GL_CULL_FACE\n\tglShadeModel GL_SMOOTH\n\n\t# set up lighting (otherwise no change as it rotates)\n\tglEnable GL_LIGHTING GL_LIGHT0\n\tglLight GL_LIGHT0 GL_AMBIENT .8 .8 .8 0\n\tglLight GL_LIGHT0 GL_DIFFUSE 1 .8 .8 0\n\tglLight GL_LIGHT0 GL_SPECULAR .8 .8 .8 0\n\tglLight GL_LIGHT0 GL_POSITION 10 10 10 1\n\tswap_font\n}\n\nRenderLoop_Render() {\n\tModelViewer_Update\n\t\n\tglLoadIdentity\n\tModelViewer_ApplyMatrix\n\t\n\tglTranslate -40 0 0\n\tglScale 1/40\n\tglColor 0.5 0.5 0.5 1\n\tftglRenderFont font1 \"${fonts[font_i]}\" FTGL_RENDER_ALL\n\t\n\tglFlush\n\tcglSwapBuffers\n\tglClear GL_COLOR_BUFFER_BIT GL_DEPTH_BUFFER_BIT\n}\n\nRenderLoop_DispatchEvent() {\n\tif ! ModelViewer_DispatchEvent \"$@\"; then\n\t\tif [[ \"$1\" == \"K\" && \"$2\" == \"+\" && \"$3\" == q ]]; then\n\t\t\tRenderLoop_Done=1\n\t\telif [[ \"$1\" == \"K\" && \"$2\" == \"+\" && \"$3\" == ']' ]]; then\n\t\t\tnext_font\n\t\telif [[ \"$1\" == \"K\" && \"$2\" == \"+\" && \"$3\" == '[' ]]; then\n\t\t\tprev_font\n\t\telse\n\t\t\ttrue\n\t\tfi\n\tfi\n}\n\nCmdlineGL_Start rw || die \"Can't init CmdlineGL\"\nInit\nRenderLoop_Run\ncglQuit\n"
  },
  {
    "path": "share/examples/FlightSim.sh",
    "content": "#! /bin/bash\n[ -n \"$BASH_VERSION\" ] || exec bash $0\n\n# Define our handy die function\ndie() { echo \"$@\" >&2; exit 2; }\nset -u\n# Load bash libraries\nsource \"${BASH_SOURCE%/*}/../CmdlineGL.lib\" || die \"Can't find CmdlineGL.lib (${BASH_SOURCE%/*}/../CmdlineGL.lib)\";\n\nCmdlineGL_LoadLib RenderLoop Geom Ship LaserBeam Cube\nFixedPt=$Geom_FixedPt\n\nlet MAX_LASER_TRAVEL=100*$Geom_FixedPt\nLASER_SPEED=100\nSHOOT_PERIOD=200\nMAX_LASERS=100\nHighestInitLaser=-1\n\nInit() {\n\techo \"Loading models...\" >&2\n\tLaserBeam_InitGfx\n\tShip_InitGfx\n\tCube_InitGfx\n\tBuildCubeField\n\n\techo \"Initializing game state...\" >&2\n\tSetLights\n\tglEnable GL_NORMALIZE\n\tglEnable GL_DEPTH_TEST\n\tglEnable GL_CULL_FACE\n\tglShadeModel GL_SMOOTH\n\tglFog GL_FOG_MODE GL_LINEAR\n\tglFog GL_FOG_COLOR '#333333'\n\tglClearColor '#333333'\n\tglFog GL_FOG_START 10\n\tglFog GL_FOG_END 100\n\tglFog GL_FOG_DENSITY .1\n\tglEnable GL_FOG\n\tglEnable GL_LIGHTING\n\n\tInitCoordSys Ship\n\tInitCoordSys Cam\n\tShip_IV_Scale -$Geom_FixedPt\n\tShip_JV_Scale -$Geom_FixedPt\n\tShip_KV_Scale -$Geom_FixedPt\n\tInitVec CamTrail 0 0 0\n\tShipSpeed=1\n\t((CamDist=6*Geom_FixedPt))\n\tCamFollowHeight=1\n\tResetCam\n\tInpAimLf=0\n\tInpAimRt=0\n\tInpAimUp=0\n\tInpAimDn=0\n\tInpAccel=0\n\tInpDeaccel=0\n\tInpShoot=0\n\tLaserCount=0\n\tShootCount=0\n\tNextGun=0\n\tlet LastShoot=Timing_T\n}\n\nSetLights() {\n\tglLoadIdentity\n\tglEnable GL_LIGHTING\n\tglEnable GL_COLOR_MATERIAL\n\tglEnable GL_LIGHT0\n\tglLight GL_LIGHT0 GL_AMBIENT  .8 .8 .8 0\n \tglLight GL_LIGHT0 GL_DIFFUSE  1  .8 .8 0\n\tglLight GL_LIGHT0 GL_SPECULAR .8 .8 .8 0\n\tglLight GL_LIGHT0 GL_POSITION 10 10 10 1\n}\n\nBuildCubeField() {\n\tglNewList CubeField GL_COMPILE\n\tglShadeModel GL_FLAT\n\tglTranslate -22.5 -22.5 -22.5\n\tfor (( x=0; x<10; x++)); do\n\t\tfor (( y=0; y<10; y++)); do\n\t\t\tfor (( z=0; z<10; z++)); do\n\t\t\t\tCube\n\t\t\t\tglTranslate 0 0 5\n\t\t\tdone\n\t\t\tglTranslate 0 0 -50\n\t\t\tglTranslate 0 5 0\n\t\tdone\n\t\tglTranslate 0 -50 0\n\t\tglTranslate 5 0 0\n\tdone\n\tglShadeModel GL_SMOOTH\n\tglEndList\n}\n\nDrawCoordinates() {\n\tglBegin GL_LINES\n\tglColor \"#FF0000\"\n\tglVertex 1 0 0\n\tglVertex 0 0 0\n\tglColor \"#00FF00\"\n\tglVertex 0 1 0\n\tglVertex 0 0 0\n\tglColor \"#0000FF\"\n\tglVertex 0 0 1\n\tglVertex 0 0 0\n\tglEnd\n}\n\nInitLaser() {\n\tInitCoordSys ${1}\n\tlet ${1}_Travel=0\n}\n\nAddLaser() {\n\tlet idx=LaserCount++\n\tif ((idx>HighestInitLaser)); then InitLaser Laser${idx}; ((HighestInitLaser=idx)); fi\n\tCoordSys_Clone Laser${idx} $4\n\t((Laser${idx}_Pos_x=$1, Laser${idx}_Pos_y=$2, Laser${idx}_Pos_z=$3, Laser${idx}_Travel=0))\n}\n\nCloneLaser() {\n\tCoordSys_Clone $1 $2\n\t((${1}_Travel=${2}_Travel))\n}\n\nRemoveLaser() {\n\tlet LaserCount--\n\tCloneLaser Laser$1 Laser$LaserCount\n}\n\neval \"UpdateLasers() {\n\tlocal progress=\\$Timing_dT*$LASER_SPEED\n\tfor ((i=LaserCount-1; i>=0; i--)); do\n\t\t((Laser\\${i}_Pos_x+= Laser\\${i}_KV_x*progress/$FixedPt))\n\t\t((Laser\\${i}_Pos_y+= Laser\\${i}_KV_y*progress/$FixedPt))\n\t\t((Laser\\${i}_Pos_z+= Laser\\${i}_KV_z*progress/$FixedPt))\n\t\t((Laser\\${i}_Travel+=progress))\n\t\tif ((Laser\\${i}_Travel>$MAX_LASER_TRAVEL)); then\n\t\t\tRemoveLaser \\$i\n\t\tfi\n\tdone\n}\"\n\nDrawLasers() {\n\tglDisable GL_LIGHTING\n\tfor ((i=0; i<LaserCount; i++)); do\n\t\tglPushMatrix\n\t\tLaser${i}_EnterCS\n\t\tLaserBeam\n\t\tglPopMatrix\n\tdone\n\tglEnable GL_LIGHTING\n}\n\nShoot() {\n\tlocal x y z xOfs yOfs zOfs\n\t((xOfs=Ship_GunXOffset[NextGun], yOfs=Ship_GunYOffset, zOfs=Ship_GunZOffset,\n\t x=Ship_Pos_x+(Ship_IV_x*xOfs+Ship_JV_x*yOfs+Ship_KV_x*zOfs)/Geom_FixedPt,\n\t y=Ship_Pos_y+(Ship_IV_y*xOfs+Ship_JV_y*yOfs+Ship_KV_y*zOfs)/Geom_FixedPt,\n\t z=Ship_Pos_z+(Ship_IV_z*xOfs+Ship_JV_z*yOfs+Ship_KV_z*zOfs)/Geom_FixedPt))\n\tAddLaser $x $y $z Ship\n#\tcat ${SOUNDDIR:-.}/laser.dsp >/dev/dsp &\n\t((NextGun++, NextGun>3?NextGun=0:0))\n}\n\n# Pretty simple- update the ship's direction and speed, then move it along\n# its forward vector.\n#\n# Create a new bullet if it's time and the spacebar is pressed.\n#\nUpdateShip() {\n\tlocal dT=Timing_dT Dist\n\tif ((InpAimLf)); then Ship_RelativeYaw $((-dT*5)); Ship_RelativeRoll $((-dT*3)); fi\n\tif ((InpAimRt)); then Ship_RelativeYaw $((dT*5)); Ship_RelativeRoll $((dT*3)); fi\n\tif ((InpAimUp)); then Ship_RelativePitch $((dT*8));  fi\n\tif ((InpAimDn)); then Ship_RelativePitch $((-dT*8)); fi\n\tShip_Normalize\n\n\tif ((InpAccel && ShipSpeed<20)); then let ShipSpeed++; fi\n\tif ((InpDeaccel && ShipSpeed>0)); then let ShipSpeed--; fi\n\tShip_Throttle=$ShipSpeed;\n\t((Dist=Timing_dT*ShipSpeed))\n\t((Ship_Pos_x+=Ship_KV_x*Dist/$FixedPt, Ship_Pos_y+=Ship_KV_y*Dist/$FixedPt, Ship_Pos_z+=Ship_KV_z*Dist/$FixedPt))\n\n\tif ((InpShoot||ShootCount)); then\n\t\t((Timing_T-LastShoot>SHOOT_PERIOD*2? LastShoot=Timing_T-SHOOT_PERIOD*2:0))\n\t\tfor ((; LastShoot+SHOOT_PERIOD<Timing_T; LastShoot+=SHOOT_PERIOD)); do\n\t\t\tShoot\n\t\tdone\n\t\tShootCount=0\n\tfi\n}\n\n# The general idea behind this one is to find the vector between the camera\n# and the ship, and set it to exactly $CamDist, moving the camera along\n# the vector as necessary.  The usual effect is for the camera to\n# \"fall in line\" behind the ship.\n#\n# The camera's upward vector is always the same as the ship, and the camera\n# looks toward 19 units ahead of the ship (so the player can see where they're\n# going).\n#\nUpdateCam() {\n\tlocal fx fy fz # The \"follow\" point, toward which the camera travels\n\t((fx=Ship_Pos_x+Ship_JV_x*CamFollowHeight, fy=Ship_Pos_y+Ship_JV_y*CamFollowHeight, fz=Ship_Pos_z+Ship_JV_y*CamFollowHeight))\n\t((CamTrail_x=Cam_Pos_x-fx, CamTrail_y=Cam_Pos_y-fy, CamTrail_z=Cam_Pos_z-fz))\n\t# avoid div-by-0\n\tif ((CamTrail_x*CamTrail_x+CamTrail_y*CamTrail_y+CamTrail_z*CamTrail_z>$FixedPt)); then\n\t\tCamTrail_SetMagnitude $CamDist\n\t\t((Cam_Pos_x=fx+CamTrail_x, Cam_Pos_y=fy+CamTrail_y, Cam_Pos_z=fz+CamTrail_z))\n\telse\n\t\t((Cam_Pos_x=fx-Ship_KV_x*CamDist, Cam_Pos_y=fy-Ship_KV_y*CamDist, Cam_Pos_z=fz-Ship_KV_z*CamDist))\n\tfi\n\t((Cam_KV_x=CamTrail_x-Ship_KV_x*19, Cam_KV_y=CamTrail_y-Ship_KV_y*19, Cam_KV_z=CamTrail_z-Ship_KV_z*19))\n\tCam_KV_Normalize\n\t((Cam_JV_x=Ship_JV_x, Cam_JV_y=Ship_JV_y, Cam_JV_z=Ship_JV_z))\n\tCam_RegenIV\n\tCam_IV_Normalize\n\tCam_RegenJV # the camera's \"up\" is not necessarily the same as the ship's \"up\"\n}\n\n# Put the camera directly on top of its follow point, which causes the Update to reset its location\nResetCam() {\n\t((Cam_Pos_x=Ship_Pos_x+Ship_JV_x*CamFollowHeight, Cam_Pos_y=Ship_Pos_y+Ship_JV_y*CamFollowHeight, Cam_Pos_z=Ship_Pos_z+Ship_JV_y*CamFollowHeight))\n\tUpdateCam\n}\n\nRenderLoop_DispatchEvent() {\n\tcase \"$1\" in\n\tK)\n\t\tif [[ $2 = \"+\" ]]; then Press=1; else Press=0; fi\n\t\tcase \"$3\" in\n\t\tright) InpAimRt=$Press;;\n\t\tleft)  InpAimLf=$Press;;\n\t\tup)    InpAimUp=$Press;;\n\t\tdown)  InpAimDn=$Press;;\n\t\t=)     InpAccel=$Press;;\n\t\t-)     InpDeaccel=$Press;;\n\t\tspace) ((InpShoot=Press, Press?ShootCount++:0));;\n\t\tq)     RenderLoop_Done=1;;\n\t\tesac\n\t\t;;\n\tesac\n}\n\nRenderLoop_Render() {\n\tUpdateLasers\n\tUpdateShip\n\tUpdateCam\n\t\n\tglClear GL_COLOR_BUFFER_BIT GL_DEPTH_BUFFER_BIT\n\tglLoadIdentity\n\tCam_ExitCS\n\tglPushMatrix\n\t\tglLight GL_LIGHT0 GL_POSITION 0 0 1 0\n\t\tglScale 5\n\t\tglColor '#FFFFFF'\n\t\tglCallList CubeField\n\tglPopMatrix\n\tglPushMatrix\n\t\tShip_EnterCS\n\t\tglTranslate 0 -1 -5\n\t\tShip\n\tglPopMatrix\n\tDrawLasers\n\tglFlush\n\tcglSwapBuffers\n}\n\nmain() {\n\tInit\n\tRenderLoop_Run;\n\tcglQuit\n}\n\n# TODO: Write better options processing\nif (( $# > 1 )) && [[ \"$1\" == \"--geometry\" ]]; then\n\tCmdlineGL_Options=(\"${CmdlineGL_Options[@]}\" \"$1\" \"$2\");\n\tshift;\n\tshift;\nfi\nif (( $# < 1 )); then\n\tCmdlineGL_Start rw || die \"Can't init CmdlineGL\"\n\tmain\nelif [[ \"$1\" == \"--record\" ]]; then\n\tCmdlineGL() { tee replay | command CmdlineGL; }\n\tCmdlineGL_Start rw || die \"Can't init CmdlineGL\"\n\tmain\nelif [[ \"$1\" == \"--dump\" ]]; then\n\tCmdlineGL_Start stdout || die \"Can't init CmdlineGL state\"\n\tmain\nelse\n\techo 'Usage: FlightSim.sh [ --record | --dump ]'\n\techo\n\techo '   --dump    Dump all output to stdout at a virtual 40fps'\n\techo '   --record  Run CmdlineGL, but duplicate all output to \"./replay\"'\n\techo\n\techo '   Recordings can be played by piping them into CmdlineGL.'\n\techo '   For instance:'\n\techo '         $ CmdlineGL <replay >/dev/null'\n\techo\n\techo 'Controls:'\n\techo '    Up   / Down   Pitch of ship'\n\techo '    Left / Right  Roll+Yaw of ship'\n\techo '    +    / -      Speed of ship'\n\techo '    Space         Fire lasers'\n\techo '    q             Quit'\n\techo\nfi\n"
  },
  {
    "path": "share/examples/ImgCube.sh",
    "content": "#! /bin/bash\n[ -n \"$BASH_VERSION\" ] || exec bash $0\nset -u\n# Define our handy die function\ndie() { echo \"$@\" >&2; exit 2; }\n\nsource \"${BASH_SOURCE%/*}/../CmdlineGL.lib\" || die \"Can't find CmdlineGL.lib (${BASH_SOURCE%/*}/../CmdlineGL.lib)\";\nCmdlineGL_LoadLib RenderLoop ModelViewer Cube || die \"Can't load required libraries\"\n\nInit() {\n\tglEnable GL_NORMALIZE GL_DEPTH_TEST\n\tglEnable GL_LIGHTING\n\tglEnable GL_TEXTURE_2D\n\tglShadeModel GL_SMOOTH\n\tglClearColor '#000033'\n\tglBlendFunc GL_SRC_ALPHA GL_ONE\n\t#glEnable GL_COLOR_MATERIAL\n\n\tCmdlineGL_LoadTex checker\n\n\t# Lighting\n\tglLoadIdentity\n\tglEnable GL_LIGHT0\n\tglLight GL_LIGHT0 GL_AMBIENT 0.8 0.8 0.8 0\n \tglLight GL_LIGHT0 GL_DIFFUSE 1 0.8 0.8 0\n\tglLight GL_LIGHT0 GL_SPECULAR 0.8 0.8 0.8 0\n\tglLight GL_LIGHT0 GL_POSITION 10 10 10 1\n\t\n\tglClear GL_COLOR_BUFFER_BIT GL_DEPTH_BUFFER_BIT\n}\n\nRenderLoop_Render() {\n\tModelViewer_Update\n\t\n\tglLoadIdentity\n\tModelViewer_ApplyMatrix\n\tglColor 0.5 0.5 0.5 1\n\tglBindTexture GL_TEXTURE_2D checker\n\tCube\n\tglFlush\n\tcglSwapBuffers\n\tglClear GL_COLOR_BUFFER_BIT GL_DEPTH_BUFFER_BIT\n}\n\nblend=0\nRenderLoop_DispatchEvent() {\n\tif ! ModelViewer_DispatchEvent \"$@\"; then\n\t\tif [[ \"$1\" == K && \"$2\" == + ]]; then\n\t\t\tcase \"$3\" in\n\t\t\tq) RenderLoop_Done=1;;\n\t\t\tb) ((blend=!blend)) \\\n\t\t\t       && { glEnable GL_BLEND; glDisable GL_DEPTH_TEST; } \\\n\t\t\t       || { glDisable GL_BLEND; glEnable GL_DEPTH_TEST; }\n\t\t\t   ;;\n\t\t\tesac\n\t\tfi\n\tfi\n}\n\nmain () {\n\tInit\n\tRenderLoop_Run\n\tcglQuit\n}\n\nif (( $# < 1 )); then\n\tCmdlineGL_Start rw || die \"Can't init CmdlineGL\"\n\tmain\nelif [[ \"$1\" == \"--record\" ]]; then\n\tCmdlineGL() { tee replay | command CmdlineGL; }\n\tCmdlineGL_Start rw || die \"Can't init CmdlineGL\"\n\tmain\nelif [[ \"$1\" == \"--dump\" ]]; then\n\tCmdlineGL_Start stdout || die \"Can't init CmdlineGL state\"\n\tmain\nelse\n\techo 'Usage: ImgCube.sh [ --record | --dump ]'\n\techo\n\techo '   --dump    Dump all output to stdout at a virtual 40fps'\n\techo '   --record  Run CmdlineGL, but duplicate all output to \"./replay\"'\n\techo\n\techo '   Recordings can be played by piping them into CmdlineGL.'\n\techo '   For instance:'\n\techo '         $ CmdlineGL <replay >/dev/null'\nfi\n"
  },
  {
    "path": "share/examples/ModelViewer.sh",
    "content": "#! /bin/bash\n[ -n \"$BASH_VERSION\" ] || exec bash $0 \"$@\"\nset -u\n# Define our handy die function\ndie() { echo \"$@\" >&2; exit 2; }\n\nsource \"${BASH_SOURCE%/*}/../CmdlineGL.lib\" || die \"Can't find CmdlineGL.lib (${BASH_SOURCE%/*}/../CmdlineGL.lib)\";\nCmdlineGL_LoadLib RenderLoop ModelViewer\n\nInit() {\n\tglEnable GL_NORMALIZE GL_DEPTH_TEST GL_CULL_FACE\n\tglEnable GL_LIGHTING\n\t#glEnable GL_TEXTURE_2D\n\tglShadeModel GL_SMOOTH\n\tglClearColor '#000033'\n\n\t# Lighting\n\tglLoadIdentity\n\tglEnable GL_LIGHT0\n\tglLight GL_LIGHT0 GL_AMBIENT 0.8 0.8 0.8 0\n \tglLight GL_LIGHT0 GL_DIFFUSE 1 0.8 0.8 0\n\tglLight GL_LIGHT0 GL_SPECULAR 0.8 0.8 0.8 0\n\tglLight GL_LIGHT0 GL_POSITION 10 10 10 1\n\n\tglClear GL_COLOR_BUFFER_BIT GL_DEPTH_BUFFER_BIT\n}\n\nRenderLoop_Render() {\n\tModelViewer_Update\n\t\n\tglLoadIdentity\n\tModelViewer_ApplyMatrix\n\tglColor 0.5 0.5 0.5 1\n\t$Model\n\tglFlush\n\tcglSwapBuffers\n\tglClear GL_COLOR_BUFFER_BIT GL_DEPTH_BUFFER_BIT\n}\n\nRenderLoop_DispatchEvent() {\n\tif ! ModelViewer_DispatchEvent \"$@\"; then\n\t\tif [[ \"$1\" == \"K\" && \"$2\" == \"+\" && \"$3\" == \"q\" ]]; then\n\t\t\tRenderLoop_Done=1;\n\t\tfi\n\tfi\n}\n\nif (( $# != 1 )); then\n\techo 'Usage: ModelViewer.sh LIBNAME'\n\techo\n\techo ' where LIBNAME is the base-name of a library that defines a renderable model,'\n\techo ' such as \"Cube\" (bash-lib/Cube.lib)'\n\techo\nelif ! CmdlineGL_LoadLib \"$1\"; then\n\techo 'Failed to load model \"$1\"'\nfi\nModel=$1;\nModel=${Model##*/}\nModel=${Model%.*}\n\nif ! [[ \"$( type -t \"$Model\" )\" == function ]]; then\n\techo \"Library \\\"$1\\\" does not define a function named \\\"$Model\\\"\"\n\techo 'This is required'\nelse\n\tCmdlineGL_Start rw || die \"Can't init CmdlineGL\"\n\tInit\n\tRenderLoop_Run\n\tcglQuit\nfi\n"
  },
  {
    "path": "share/examples/Pyramids.sh",
    "content": "#! /bin/bash\n[ -n \"$BASH_VERSION\" ] || exec bash $0\n\n# Define our handy die function\ndie() { echo \"$@\" >&2; exit 2; }\n\nsource \"${BASH_SOURCE%/*}/../CmdlineGL.lib\" || die \"Can't find CmdlineGL.lib (${BASH_SOURCE%/*}/../CmdlineGL.lib)\";\nCmdlineGL_LoadLib Timing RenderLoop\n\nlet x=0;\n\nToInt() {\n\tResult=${1/./}\n}\nToFloat() {\n\tlet dec_pos=${#1}-$2;\n\tResult=${1:0:dec_pos}.${1:dec_pos};\n}\n\nTriangle() {\n\tglBegin GL_TRIANGLES\n\tglVertex 3 -3 0\n\tglVertex -3 -3 0\n\tglVertex 0 3 0\n\tglEnd\n}\n\nPyramid() {\n\tglBegin GL_TRIANGLES\n\tglColor 0.5 0.5 0.2\n\tglNormal 0 2 4.4\n\tglVertex 1 -1 1\n\tglVertex -1 -1 1\n\tglVertex 0 1.2 0\n\n\tglColor 0.5 0.2 0.5\n\tglNormal -4.4 2 0\n\tglVertex -1 -1 1\n\tglVertex -1 -1 -1\n\tglVertex 0 1.2 0\n\n\tglColor 0.2 0.5 0.5\n\tglNormal 0 2 -4.4\n\tglVertex -1 -1 -1\n\tglVertex 1 -1 -1\n\tglVertex 0 1.2 0\n\n\tglColor 0.2 0.7 0.5\n\tglNormal 4.4 2 0\n\tglVertex 1 -1 -1\n\tglVertex 1 -1 1\n\tglVertex 0 1.2 0\n\tglEnd\n\n\tglColor 0.2 0.2 0.5\n\tglBegin GL_QUADS\n\tglNormal 0 -1 0\n\tglVertex 1 -1 -1\n\tglVertex -1 -1 -1\n\tglVertex -1 -1 1\n\tglVertex 1 -1 1\n\tglEnd\n}\n\nBuildList() {\n\tglLoadIdentity\n\tglNewList tri GL_COMPILE\n\tglColor 0.5 0.5 0.5\n\tPyramid\n\tglEndList\n}\n\nSetLights() {\n\tglLoadIdentity\n\tglEnable GL_LIGHTING\n\tglEnable GL_COLOR_MATERIAL\n\tglEnable GL_LIGHT0\n\tglLight GL_LIGHT0 GL_AMBIENT 0.8 0.8 0.8 0\n \tglLight GL_LIGHT0 GL_DIFFUSE 1 0.8 0.8 0\n\tglLight GL_LIGHT0 GL_SPECULAR 0.8 0.8 0.8 0\n\tglLight GL_LIGHT0 GL_POSITION 10 10 10 1\n}\n\nInit() {\n\tBuildList\n\tSetLights\n\n\tglEnable GL_NORMALIZE\n\tglEnable GL_DEPTH_TEST\n\tglClear GL_COLOR_BUFFER_BIT GL_DEPTH_BUFFER_BIT\n\n\tframetime=0;\n\tdirection=0;\n\tdistance=10;\n\tpitch=0;\n}\n\nSwap() {\n\tglFlush\n\tcglSwapBuffers\n\tglClear GL_COLOR_BUFFER_BIT GL_DEPTH_BUFFER_BIT\n}\n\nRenderLoop_Render() {\n\tUpdate; # apply current user input to program state\n\t\n\tToFloat 000$((Timing_T*8%36000)) 2\n\tx=$Result\n\tglLoadIdentity\n\tglTranslate 0 0 -$distance\n\tglRotate $pitch 1 0 0\n\tglRotate $direction 0 1 0\n\t\n\tglTranslate 3 0 0\n\tglCallList tri\n\tglTranslate -3 0 3\n\tglCallList tri\n\tglTranslate -3 0 -3\n\tglCallList tri\n\tglTranslate 3 0 -3\n\tglCallList tri\n\tglTranslate 0 0 3\n\t\n\tglRotate $x 0 0 1\n\tglRotate $x 0 1 1\n\tglCallList tri\n\tSwap;\n}\n\nMouseClick() {\n\tlocal Press btn=$2\n\tif [[ \"$1\" = \"+\" ]]; then Press=1; else Press=0; fi\n\tif ((btn==1)); then\n\t\t((Dragging=Press))\n\tfi\n}\n\n# Handle mouse drag actions.\n# If the mouse has moved since last time change the pitch or direction\n# by the vertical or horizontal distance the mouse has moved.\n# Also repaint the robot and record the \"last position\" of the mouse.\n#\nMouseMotion() {\n\tlocal dx=$3 dy=$4;\n\tif ((Dragging)); then\n\t\tif ((dy)); then\n\t\t\t((pitch+= dy))\n\t\tfi\n\t\tif ((dx)); then\n\t\t\t((direction+= dx));\n\t\tfi\n\tfi\n}\n\nRenderLoop_DispatchEvent() {\n\tlocal Press\n\tcase \"$1\" in\n\tK)\n\t\tif [[ \"$2\" = \"+\" ]]; then Press=1; else Press=0; fi\n\t\tcase \"$3\" in\n\t\tright)  PanRight=$Press;;\n\t\tleft)   PanLeft=$Press;;\n\t\tup)     PanUp=$Press;;\n\t\tdown)   PanDn=$Press;;\n\t\t=)      ZoomIn=$Press;;\n\t\t-)      ZoomOut=$Press;;\n\t\tq)      RenderLoop_Done=1;;\n\t\tesac\n\t\t;;\n\tM)\n\t\tif [[ \"$2\" = \"@\" ]]; then\n\t\t\tMouseMotion $3 $4 $5 $6\n\t\telse\n\t\t\tMouseClick $2 $3\n\t\tfi\n\t\t;;\n\tesac\n}\n\nUpdate() {\n\tif ((PanLeft)); then let direction+=2; fi\n\tif ((PanRight));then let direction-=2; fi\n\tif ((PanUp));   then let pitch-=2; fi\n\tif ((PanDn));   then let pitch+=2; fi\n\tif ((ZoomIn));  then let distance-=1; fi\n\tif ((ZoomOut)); then let distance+=1; fi\n}\n\nmain() {\n\tInit\n\tSwap\n\tRenderLoop_Run;\n\tcglQuit\n}\n\nif [[ \"$1\" == \"--record\" ]]; then\n\tCmdlineGL() { tee replay | command CmdlineGL; }\n\tCmdlineGL_Start rw || die \"Can't init CmdlineGL\"\n\tmain\nelif [[ \"$1\" == \"--dump\" ]]; then\n\tCmdlineGL_Start stdout || die \"Can't init CmdlineGL state\"\n\tmain\nelif [[ -z \"$1\" ]]; then\n\tCmdlineGL_Start rw || die \"Can't init CmdlineGL\"\n\tmain\nelse\n\techo 'Usage: Pyramids.sh [ --record | --dump ]'\n\techo\n\techo '   --dump    Dump all output to stdout at a virtual 40fps'\n\techo '   --record  Run CmdlineGL, but duplicate all output to \"./replay\"'\n\techo\n\techo '   Recordings can be played by piping them into CmdlineGL.'\n\techo '   For instance:'\n\techo '         $ CmdlineGL <replay >/dev/null'\nfi\n"
  },
  {
    "path": "share/examples/Robot.sh",
    "content": "#! /bin/bash\n[ -n \"$BASH_VERSION\" ] || exec bash $0\nset -u\n# Define our handy die function\ndie() { echo \"$@\" >&2; exit 2; }\n\nsource \"${BASH_SOURCE%/*}/../CmdlineGL.lib\" || die \"Can't find CmdlineGL.lib (${BASH_SOURCE%/*}/../CmdlineGL.lib)\";\nCmdlineGL_LoadLib RenderLoop ModelViewer\n\n#------------------------------------------------------------------------------\n# This is an almost line-by-line conversion from C to bash\n# The conversion process was rather fun in a strange morbid way...\n#\n# Actually, the program is somewhat improved, since it uses display lists now\n#\n#------------------------------------------------------------------------------\n# Constants for the dimensions of the robot's body\n#\n#                   ___\n#                  /   \\\n#   Y              \\   /\n#   |             -_____-\n#   |        -----|     |-----\n#   |        |    |     |    |\n#   |______X |----|     |----|\n#  / 0       | |  |     |  | |\n# /           \\\\  |     |   \\\\\n# Z            \\\\ -__-__-    \\\\\n#               \\\\_ | | __    \\\\\n#               |  LJ LJ  |\n#               |  r|_r|  |\n#               |  |   |  |\n#               |  |   |  |\n#               |--|   |--|\n#               |  |   |  |\n#               |  |   |  |\n#               |__|   |__|\n#              |    | |    |\n#              ------ ------\n#\n\nHEAD_RADIUS=100;\nTORSO_LENGTH=480;\nTORSO_RADIUS=90;\nHIP_WIDTH=220;\nHIP_SPACING=20;\nHIP_RADIUS=35;\nSHOULDER_WIDTH=500;\nSHOULDER_RADIUS=70;\nUPPER_ARM_LENGTH=300;\nUPPER_ARM_RADIUS=40;\nLOWER_ARM_LENGTH=280;\nLOWER_ARM_RADIUS=30;\nUPPER_LEG_LENGTH=340;\nUPPER_LEG_RADIUS=55;\nLOWER_LEG_LENGTH=300;\nLOWER_LEG_RADIUS=45;\nFOOT_LENGTH=160;\nFOOT_HEIGHT=30;\nHEAD_HEIGHT=$((TORSO_LENGTH+$HEAD_RADIUS));\nPELVIC_HEIGHT=$((-HIP_RADIUS*18/10));\nSHOULDER_HEIGHT=$((TORSO_LENGTH*84/100));\nSHOULDER_OFFSET=$((SHOULDER_WIDTH/2 - $UPPER_ARM_RADIUS));\nELBOW_RADIUS=$((LOWER_ARM_RADIUS*12/10));\nELBOW_WIDTH=$((LOWER_ARM_RADIUS*24/10));\nLEG_OFFSET=$((HIP_WIDTH/2 ));\nUPPER_LEG_PIPE_LENGTH=$((UPPER_LEG_LENGTH+UPPER_LEG_RADIUS));\nHIP_SUPPORT_WIDTH=$((HIP_WIDTH - HIP_SPACING*2 - UPPER_LEG_RADIUS*2));\nHIP_SUPPORT_HALF_WIDTH=$((HIP_SUPPORT_WIDTH/2));\nKNEE_RADIUS=$((LOWER_LEG_RADIUS*12/10));\nKNEE_WIDTH=$((LOWER_LEG_RADIUS*24/10));\n\n# Indicies of important angles\n#\nNeckX=0; NeckY=1;\nLShoulder=2; RShoulder=3; LElbow=4; RElbow=5;\nTorso=6;\nLHip=7; RHip=8; LKnee=9; RKnee=10; LFoot=11; RFoot=12;\n\n# Joint records for the motionless robot and the four stage animation\n#\nStanding=(    0  0  1000  1000 -2000 -2000      0       0     0     0     0  1000  1000 );\nWalkScript0=( 0  0  2000  2000 -5500 -5500      0   -4000  1000  7000  1000 -2000  -500 );\nWalkScript1=( 0  0  4000     0 -4000 -7000   -700   -3000  2500  2000  3000  2000  3000 );\nWalkScript2=( 0  0  2000  2000 -5500 -5500      0    1000 -4000  1000  7000  -500 -2000 );\nWalkScript3=( 0  0     0  4000 -7000 -4000    700    2500 -3000  3000  2000  3000  2000 );\n\n\n# Variables that describe the current robot\n#\nRobot_Joints=0;\nRobot_MoveProgress=0;\nRobot_Animate=true;\n\n# Variables related to the camera\n#\nView_Direction=0;\nView_Pitch=0;\nView_Distance=1000;\nView_Mode=0;\n\nDragging=0;\n\n# Draw the head of the robot.\n# Draws a sphere with radius \"HEAD_RADIUS\" at the current origin.\n#\nbuild_head() {\n\tglNewList head GL_COMPILE\n\tglPushMatrix\n\tglScale $HEAD_RADIUS $HEAD_RADIUS $HEAD_RADIUS\n\tgluSphere quadric 100 10 10\n\tglPopMatrix\n\tglEndList\n}\nhead() {\n\tglCallList head\n}\n\n# Draw a closed cylinder.\n# This is equivalent to a\n#\nclosedCylinder() { # GLUquadricObj *qobj GLdouble baseRadius GLdouble topRadius GLdouble height GLint slices GLint stacks\n\tbaseRadius=$2; topRadius=$3; height=$4; slices=$5; stacks=$6;\n\tgluCylinder $1 0 $baseRadius 0 $slices 1\n\tgluCylinder $1 $baseRadius $topRadius $height $slices $stacks\n\tglTranslate 0 0 $height\n\tgluCylinder $1 $topRadius 0 0 $slices 1\n\tglTranslate 0 0 -$height\n}\n\n# Draw the torso of the robot.\n# This consists of a large vertical cylinder above the origin a tapered\n# cylinder on the bottom of it and horizontal shoulder cylinder.\n# The origin ends up located at the very bottom of the torso.\n#\nbuild_torso() {\n\tglNewList torso GL_COMPILE\n\tglPushMatrix\n\tglTranslate 0 $TORSO_LENGTH 0\n\tglRotate 9000 100 0 0\n\tlocal TorsoZ=$((TORSO_LENGTH*8/10));\n\tclosedCylinder quadric $TORSO_RADIUS $TORSO_RADIUS $TorsoZ 20 1\n\tglTranslate 0 0 $TorsoZ\n\tclosedCylinder quadric $TORSO_RADIUS $((HIP_SUPPORT_WIDTH/2)) $((TORSO_LENGTH*2/10)) 20 1\n\tglPopMatrix\n\n\tglPushMatrix\n\tglTranslate $((-SHOULDER_WIDTH/2)) $SHOULDER_HEIGHT 0.0\n\tglRotate 9000 0 100 0\n\tclosedCylinder quadric $SHOULDER_RADIUS $SHOULDER_RADIUS $SHOULDER_WIDTH 20 1\n\tglPopMatrix\n\tglEndList\n}\ntorso() {\n\tglCallList torso\n}\n\n# Draw the lower torso of the robot.\n# This piece is composed of a vertical disc (short horizontal cylinder) and a\n# long horizontal cylinder that runs through it.\n#\nbuild_lower_torso() {\n\tglNewList lower_torso GL_COMPILE\n\tglPushMatrix\n\tglTranslate 0 $PELVIC_HEIGHT 0\n\tglRotate 9000 0 100 0\n\tglTranslate 0 0 -$HIP_SUPPORT_HALF_WIDTH\n\tclosedCylinder quadric $TORSO_RADIUS $TORSO_RADIUS $HIP_SUPPORT_WIDTH 20 1\n\n\tglTranslate 0 0 -$(($HIP_SPACING + $UPPER_LEG_RADIUS))\n\tgluCylinder quadric $HIP_RADIUS $HIP_RADIUS $HIP_WIDTH 10 1\n\tglPopMatrix\n\tglEndList\n}\nlower_torso() {\n\tglCallList lower_torso\n}\n\n# Draw the upper arm of the robot.\n# This is a simple cylinder that runs vertically from its origin downward\n# toward the elbow.\n#\nbuild_upper_arm() {\n\tglNewList upper_arm GL_COMPILE\n\tglPushMatrix\n\tglRotate 9000 100 0 0\n\tgluCylinder quadric $UPPER_ARM_RADIUS $LOWER_ARM_RADIUS $UPPER_ARM_LENGTH 20 1\n\tglPopMatrix\n\tglEndList\n}\nupper_arm() {\n\tglCallList upper_arm\n}\n\n# Draw the elbow and lower arm.\n# This function draws a short horizontal cylinder at the origin then draws\n# lower arm extending downward from there.\n#\nbuild_lower_arm() {\n\tglNewList lower_arm GL_COMPILE\n\tglPushMatrix\n\tglRotate 9000 0 100 0\n\tglTranslate 0 0 $((-ELBOW_WIDTH/2))\n\tclosedCylinder quadric $ELBOW_RADIUS $ELBOW_RADIUS $ELBOW_WIDTH 20 1\n\tglPopMatrix\n\n\tglPushMatrix\n\tglRotate 9000 100 0 0\n\tclosedCylinder quadric $LOWER_ARM_RADIUS $LOWER_ARM_RADIUS $LOWER_ARM_LENGTH 20 1\n\tglPopMatrix\n\tglEndList\n}\nlower_arm() {\n\tglCallList lower_arm\n}\n\n# Draw the upper leg.\n# This function draws a simple cylinder that starts just above the origin and\n# extends downward.\n#\nbuild_upper_leg() {\n\tglNewList upper_leg GL_COMPILE\n\tglPushMatrix\n\tglTranslate 0 $UPPER_LEG_RADIUS 0\n\tglRotate 9000 100 0 0\n\tclosedCylinder quadric $UPPER_LEG_RADIUS $LOWER_LEG_RADIUS $UPPER_LEG_PIPE_LENGTH 20 1\n\tglPopMatrix\n\tglEndList\n}\nupper_leg() {\n\tglCallList upper_leg\n}\n\n# Draw the knee and lower leg.\n# This draws a short horizontal cylinder for the knee then draws a vertical\n# cylinder for the lower leg.\n#\nbuild_lower_leg() {\n\tglNewList lower_leg GL_COMPILE\n\tglPushMatrix\n\tglRotate 9000 0 100 0\n\tglTranslate 0 0 $((-KNEE_WIDTH/2))\n\tclosedCylinder quadric $KNEE_RADIUS $KNEE_RADIUS $KNEE_WIDTH 20 1\n\tglPopMatrix\n\n\tglPushMatrix\n\tglRotate 9000 1 0 0\n\tgluCylinder quadric $LOWER_LEG_RADIUS $LOWER_LEG_RADIUS $LOWER_LEG_LENGTH 20 1\n\tglPopMatrix\n\tglEndList\n}\nlower_leg() {\n\tglCallList lower_leg\n}\n\n# Draw the ankle and foot.\n# This draws a short horizontal cylinder for the ankle/heel and then draws\n# a flattened tapered cylinder along the Z axis for the foot.\n#\nbuild_foot() {\n\tglNewList foot GL_COMPILE\n\tglPushMatrix\n\tglRotate 9000 0 100 0\n\tglTranslate 0 0 $((-LOWER_LEG_RADIUS))\n\tclosedCylinder quadric $LOWER_LEG_RADIUS $LOWER_LEG_RADIUS $((LOWER_LEG_RADIUS*2)) 20 1\n\tglPopMatrix\n\tglPushMatrix\n\tglTranslate 0 $((-LOWER_LEG_RADIUS*3/10)) 0\n\tglScale 100 30 100\n\tclosedCylinder quadric $((LOWER_LEG_RADIUS*8/10)) $((LOWER_LEG_RADIUS*12/10)) $FOOT_LENGTH 20 1\n\tglPopMatrix\n\tglEndList\n}\nfoot() {\n\tglCallList foot\n}\n\n# Display the robot using the joint angles in the Robot structure.\n#\n# This function starts from the identity matrix and first modifies the matrix\n# to put the camera in the desired position.\n#\n# It then traverses the structure of the robot's body calling each of\n# the drawing functions in thew process.\n#\n# Last it swaps the drawing buffers to make the new image visible.\n#\nRepaint() {\n\t# Clear the drawing buffer\n\tglClear GL_COLOR_BUFFER_BIT\n\tglClear GL_DEPTH_BUFFER_BIT\n\tglLoadIdentity\n\n\t# Alter the model matrix to give the effect of having a movable camera.\n\tModelViewer_ApplyMatrix\n\n\tglPushMatrix\n\t# Move to the center of the head rotate by the neck angles and draw.\n\tglTranslate 0 $HEAD_HEIGHT 0\n\tglRotate ${Robot_Joints[$NeckX]} 100 0 0\n\tglRotate ${Robot_Joints[$NeckY]} 0 100 0\n\t\thead\n\tglPopMatrix\n\n\t# Draw the torso.  It never needs rotated.\n\ttorso\n\n\tglPushMatrix\n\t# Draw the left arm.  Start at the left shoulder draw the uper arm\n\t#  then translate down to the elbow rotate and draw the lower arm.\n\tglTranslate $SHOULDER_OFFSET $SHOULDER_HEIGHT 0\n\tglRotate ${Robot_Joints[$LShoulder]} 100 0 0\n\t\tupper_arm\n\t\tglTranslate 0 -$UPPER_ARM_LENGTH 0\n\t\tglRotate ${Robot_Joints[$LElbow]} 100 0 0\n\t\t\tlower_arm\n\tglPopMatrix\n\n\tglPushMatrix\n\t# Same for the right arm.\n\tglTranslate -$SHOULDER_OFFSET $SHOULDER_HEIGHT 0\n\tglRotate ${Robot_Joints[$RShoulder]} 100 0 0\n\t\tupper_arm\n\t\tglTranslate 0 -$UPPER_ARM_LENGTH 0\n\t\tglRotate ${Robot_Joints[$RElbow]} 100 0 0\n\t\t\tlower_arm\n\tglPopMatrix\n\n\tglPushMatrix\n\t# Rotate for the hips draw them then draw the left and right leg.\n\tglRotate ${Robot_Joints[$Torso]} 0 100 0\n\t\tlower_torso\n\n\t\tglPushMatrix\n\t\t# First move to the left draw the upper leg and then translate down\n\t\t#  to the knee draw the lower leg then translate down to the foot\n\t\t#  then rotate and draw it.\n\t\tglTranslate $LEG_OFFSET $PELVIC_HEIGHT 0\n\t\tglRotate ${Robot_Joints[$LHip]} 100 0 0\n\t\t\tupper_leg\n\t\t\tglTranslate 0 -$UPPER_LEG_LENGTH 0\n\t\t\tglRotate ${Robot_Joints[$LKnee]} 100 0 0\n\t\t\t\tlower_leg\n\t\t\t\tglTranslate 0 -$LOWER_LEG_LENGTH 0\n\t\t\t\tglRotate ${Robot_Joints[$LFoot]} 100 0 0\n\t\t\t\tfoot\n\t\tglPopMatrix\n\n\t\tglPushMatrix\n\t\t# Same for the right leg.\n\t\tglTranslate -$LEG_OFFSET $PELVIC_HEIGHT 0\n\t\tglRotate ${Robot_Joints[$RHip]} 100 0 0\n\t\t\tupper_leg\n\t\t\tglTranslate 0 -$UPPER_LEG_LENGTH 0\n\t\t\tglRotate ${Robot_Joints[$RKnee]} 100 0 0\n\t\t\t\tlower_leg\n\t\t\t\tglTranslate 0 -$LOWER_LEG_LENGTH 0\n\t\t\t\tglRotate ${Robot_Joints[$RFoot]} 100 0 0\n\t\t\t\tfoot\n\t\tglPopMatrix\n\tglPopMatrix\n\n\t# Flush any remaining drawing commands and flip the buffers.\n\tglFlush\n\tcglSwapBuffers\n}\n\n\n# Set the angles of the current robot's joints by averaging angles from a\n# \"before\" and \"after\" position.  \"Progress\" indicates how far the joint\n# has come from the \"before\" position toward the \"after\" one.\n# This function stores the results directly into the Robot global variable.\n#\nSetJoints() {\n\tlocal FromAng=$1 ToAng=$2 Progress=$3;\n\tfor ((i=0; i<13; i++)); do\n\t\t(( Robot_Joints[i]=$FromAng[i]+($ToAng[i]-$FromAng[i])*Progress/100 ));\n\tdone\n}\n\n\n# Animate the robot by progressing it through the four walking states.\n# This function renews the GLut timer so that it will be called again\n#  periodically.\n# The parameter is ignored.\n#\nAnimate() {\n\tif [[ -n \"$Robot_Animate\" ]]; then\n\t\tlet Robot_MoveProgress+=5;\n\t\tif (( Robot_MoveProgress >= 400 )); then\n \t\t\tlet Robot_MoveProgress-=400;\n\t\tfi\n\t\t(( idx1=Robot_MoveProgress/100 ))\n\t\t(( idx2=idx1+1 ))\n\t\tif (( idx2 > 3 )); then idx2=0; fi\n\t\tSetJoints \"WalkScript$idx1\" \"WalkScript$idx2\" $((Robot_MoveProgress - (idx1 * 100) ))\n\telse\n\t\tSetJoints \"Standing\" \"Standing\" 0\n\tfi\n}\n\n# Initialize the globals and set up OpenGL.\n#\nInit() {\n\t# Use fixed point numbers for all floating-point GL parameters\n\tcglPushDivisor 100\n\n\t# Turn on normalization of surface vectors and enable Z-buffering.\n\tglEnable GL_NORMALIZE\n\tglEnable GL_DEPTH_TEST\n\t# Setup lighting\n\t# Turn on lights and iterate through the global array of light records.\n\t# For each light in the array enable that number light in OpenGl and\n\t#  set the colors for it.\n\tglEnable GL_LIGHTING\n\tglLight GL_LIGHT0 GL_AMBIENT 80 80 80 100\n\tglLight GL_LIGHT0 GL_DIFFUSE 80 80 80 100\n\tglLight GL_LIGHT0 GL_SPECULAR 80 80 80 100\n\tglLight GL_LIGHT0 GL_POSITION 1000 1000 1000 100\n\tglEnable GL_LIGHT0\n\n\t# Setup material properties.\n\t# Allocate quadrics with filled drawing style\n\tgluNewQuadric quadric\n\tgluQuadricDrawStyle quadric GLU_FILL\n\n\tbuild_head;\n\tbuild_torso;\n\tbuild_lower_torso;\n\tbuild_upper_arm;\n\tbuild_lower_arm;\n\tbuild_upper_leg;\n\tbuild_lower_leg;\n\tbuild_foot;\n\n\t# Initialize runtime variables.\n\tRobot_MoveProgress=0;\n\tSetJoints \"WalkScript0\" \"WalkScript0\" 0\n\tRobot_Animate=true;\n}\n\nRenderLoop_DispatchEvent() {\n\tif ! ModelViewer_DispatchEvent \"$@\"; then\n\t\tif [[ \"$1\" == \"K\" && \"$2\" == \"+\" && \"$3\" == \"q\" ]]; then\n\t\t\tRenderLoop_Done=1;\n\t\tfi\n\tfi\n}\n\nRenderLoop_Render() {\n\tModelViewer_Update\n\tAnimate\n\tRepaint\n}\n\nmain() {\n\tInit\n\tRenderLoop_Run;\n\tcglQuit\n}\n\n# TODO: Write better options processing\nif (( $# > 1 )) && [[ \"$1\" == \"--geometry\" ]]; then\n        CmdlineGL_Options=(\"${CmdlineGL_Options[@]}\" \"$1\" \"$2\");\n        shift;\n        shift;\nfi\nif (( ! $# )); then\n\tCmdlineGL_Start rw || die \"Can't init CmdlineGL\"\n\tmain\nelif [[ \"$1\" == \"--record\" ]]; then\n\tCmdlineGL() { tee replay | command CmdlineGL; }\n\tCmdlineGL_Start rw || die \"Can't init CmdlineGL\"\n\tmain\nelif [[ \"$1\" == \"--dump\" ]]; then\n\tCmdlineGL_Start stdout || die \"Can't init CmdlineGL state\"\n\tmain\nelse\n\techo 'Usage: Robot.sh [ --record | --dump ]'\n\techo\n\techo '   --dump    Dump all output to stdout at a virtual 40fps'\n\techo '   --record  Run CmdlineGL, but duplicate all output to \"./replay\"'\n\techo\n\techo '   Recordings can be played by piping them into CmdlineGL.'\n\techo '   For instance:'\n\techo '         $ CmdlineGL <replay >/dev/null'\nfi\n\n"
  },
  {
    "path": "share/examples/SpinText.sh",
    "content": "#! /bin/bash\n#\n#  This is an extremely minimal example which rotates a string of text\n#  rendered in 3D.  The only complicated part is finding a valid font...\n#\ntext=\"$1\";\nfont=\"$2\";\nset -eu\n\nsource \"${BASH_SOURCE%/*}/../CmdlineGL.lib\" || die \"Can't find CmdlineGL.lib (${BASH_SOURCE%/*}/../CmdlineGL.lib)\";\n\nif [[ -z \"$text\" ]]; then\n\techo \"Usage: SpinText.sh STRING_OF_TEXT [FONT_FILE]\";\n\texit 1;\nfi\nif [[ -z \"$font\" ]]; then\n\t# See if we can find a sensible default\n\tfont=`find /usr/share -name '*.ttf' | grep -i mono | head -n 1`;\n\tif [[ ! -f \"$font\" ]]; then\n\t\techo \"Can't find any default font; specify font filename as second argument.\";\n\t\texit 2;\n\tfi\nelse\n\tif [[ ! -f \"$font\" ]]; then\n\t\techo \"No such font \\\"$font\\\"\";\n\t\texit 2;\n\tfi\nfi\n\nR=0\nT=0\nspin_rate=12 # degrees per second\n\n# Initialize CmdlineGL for rendering only (no input or feedback)\nCmdlineGL_Start ro\nglEnable GL_NORMALIZE GL_DEPTH_TEST GL_CULL_FACE\nglShadeModel GL_SMOOTH\n\n# Load font file and configure font rendering parameters\nftglCreateExtrudeFont font1 \"$font\"\nftglSetFontFaceSize   font1 72 72\nftglSetFontDepth      font1 20\n\n# Prepare the graphics in a display list.  Need to call once first since ftgl\n# creates its own display lists, then again to capture those in the second\n# display list.\nftglRenderFont font1 \"$text\" FTGL_ALIGN_CENTER FTGL_RENDER_ALL\nglNewList mytext GL_COMPILE\nglTranslate -$(( ${#text}/2 * 40 )) -36 10   # flaky guess at midpoint of string\nftglRenderFont font1 \"$text\" FTGL_RENDER_ALL\nglEndList\n\n# set up lighting (otherwise no change as it rotates)\nglEnable GL_LIGHTING GL_LIGHT0\nglLight GL_LIGHT0 GL_AMBIENT .8 .8 .8 0\nglLight GL_LIGHT0 GL_DIFFUSE 1 .8 .8 0\nglLight GL_LIGHT0 GL_SPECULAR .8 .8 .8 0\nglLight GL_LIGHT0 GL_POSITION 10 10 10 1\n\nwhile true; do\n\tglClear GL_COLOR_BUFFER_BIT GL_DEPTH_BUFFER_BIT\n\tglLoadIdentity\n\tglRotate $((R+=spin_rate))/60 0 1 0  # assuming 60fps\n\tglScale 10/$((40 * ${#text} / 2))    # flaky guess at scaling to window width\n\tglCallList mytext\n\tglFlush\n\tcglSwapBuffers\n\tcglSync $((T+=16)) # blindly assume we can maintain 60fps\ndone\n"
  },
  {
    "path": "share/lib-bash/CmdlineGL.lib",
    "content": "# CmdlineGL Base API\n#--------------------------------------\n# Functions:\n#   CmdlineGL_LoadLib LIBRARY [LIBRARY...]\n#   CmdlineGL_LoadTex TEXTURE [TEXTURE...]\n#   CmdlineGL_LoadFont FONT [FONT...]\n#   CmdlineGL_Start [MODE]\n#   CmdlineGL_Send COMMAND [ARGS...]\n#   CmdlineGL_Recv\n#   gl*\n#   glu*\n#   cgl*\n#\n# Variables:\n#   CmdlineGL_Options - array variable of options to pass to CmdlineGL\n#   CmdlineGL_LibPath - ':' separated list of directories where *.lib can be found\n#   CmdlineGL_TexPath - same for *.png\n#   CmdlineGL_FontPath - same for *.ttf\n#   CmdlineGL_Mode: str - either 'stdout', 'w' or 'rw', or empty if CmdlineGL is not started yet\n#   CmdlineGL_In: int - File handle of user input returned from CmdlineGL\n#   CmdlineGL_Out: int - File handle where commands are written\n#   CmdlineGL_InputLine: str - Most recent input event\n#\n\ndeclare -a CmdlineGL_Options\nCmdlineGL_Mode=\nCmdlineGL_In=\nCmdlineGL_Out=\nCmdlineGL_InputLine=\nCmdlineGL_LibLoaded=\":\"\nCmdlineGL_TexLoaded=\":\"\nCmdlineGL_FontLoaded=\":\"\n\nCmdlineGL_LoadLib() {\n\t# Unpack path into an array, so that we can expand the path into 'find' cleanly\n\tIFS=':' read -ra CmdlineGL_LibPathAry <<< \"$CmdlineGL_LibPath\";\n\tfor lib in \"$@\"; do\n\t\tif [[ \"$CmdlineGL_LibLoaded\" != *:\"$lib\":* ]]; then\n\t\t\tlocal fname;\n\t\t\t# If full path name is given, load it directly\n\t\t\tif [[ \"$lib\" = */* ]]; then\n\t\t\t\tfname=\"$lib\"\n\t\t\telse\n\t\t\t\tfname=`find \"${CmdlineGL_LibPathAry[@]}\" -name \"$lib\".lib | head -n 1` || { echo \"Can't find lib '$lib' in path '$CmdlineGL_LibPath'\"; return 2; }\n\t\t\tfi\n\t\t\tsource \"$fname\" || { echo \"Failed to load '$lib'\"; return 2; }\n\t\t\tCmdlineGL_LibLoaded=\"$CmdlineGL_LibLoaded$lib:\"\n\t\tfi\n\tdone\n}\n\nCmdlineGL_LoadTex() {\n\t# Unpack path into an array, so that we can expand the path into 'find' cleanly\n\tIFS=':' read -ra CmdlineGL_TexPathAry <<< \"$CmdlineGL_TexPath\";\n\tfor tex in \"$@\"; do\n\t\tif [[ \"$CmdlineGL_TexLoaded\" != *:\"$tex\":* ]]; then\n\t\t\tlocal fname=`find \"${CmdlineGL_TexPathAry[@]}\" -name \"$tex\".png | head -n 1` || { echo \"Can't find Tex '$tex' in path '$CmdlineGL_TexPath'\"; return 2; }\n\t\t\tglBindTexture GL_TEXTURE_2D \"$tex\"\n\t\t\tcglLoadImage2D \"$fname\"\n\t\t\tglTexParameter GL_TEXTURE_2D GL_TEXTURE_MIN_FILTER GL_LINEAR\n\t\t\tglTexParameter GL_TEXTURE_2D GL_TEXTURE_MAG_FILTER GL_LINEAR\n\t\tfi\n\tdone\n}\n\nCmdlineGL_LoadFont() {\n\t# Unpack path into an array, so that we can expand the path into 'find' cleanly\n\tIFS=':' read -ra CmdlineGL_FontPathAry <<< \"$CmdlineGL_FontPath\";\n\tfor font in \"$@\"; do\n\t\tif [[ \"$CmdlineGL_FontLoaded\" != *:\"$font\":* ]]; then\n\t\t\tlocal fname=`find \"${CmdlineGL_FontPathAry[@]}\" -name \"$font\".png | head -n 1` || { echo \"Can't find Font '$font' in path '$CmdlineGL_FontPath'\"; return 2; }\n\t\t\techo \"TODO\" >&2; return 1;\n\t\tfi\n\tdone\n}\n\n# Build aliases for each available command in the API.\n# This is the first time we check for an executable CmdlineGL, but can't check its\n# exit status within the substitution...\nCmdlineGL_Commands=( $( CmdlineGL --showcmds ) ) || { echo \"Can't run CmdlineGL\"; return 2; }\nfor cmd in ${CmdlineGL_Commands[@]}; do eval \"$cmd(){ CmdlineGL_Send $cmd \\\"\\$@\\\"; }\"; done\n\n# This default gets overwritten by CmdlineGL_Start  (thunk/trampoline style)\nCmdlineGL_Send() {\n\tCmdlineGL_Start\n\tCmdlineGL_Send \"$@\"\n}\nCmdlineGL_Recv() {\n\tCmdlineGL_Start\n\tCmdlineGL_Recv \"$@\"\n}\n# If we are running under bash, we can create a coprocess\n# and skip all the fifo nonsense.\nCmdlineGL_Start() {\n\tif [[ $# > 0 && \"$1\" == stdout ]]; then\n\t\tCmdlineGL_Mode=stdout\n\t\tCmdlineGL_Out=1\n\t\tCmdlineGL_Recv(){ return 1; }\n\telif [[ $# > 0 && \"$1\" == rw ]]; then\n\t\tif [[ \"${BASH_VERSINFO[0]}\" -ge 4 ]]; then\n\t\t\tcoproc CmdlineGL \"${CmdlineGL_Options[@]}\" -t || return 1\n\t\t\tCmdlineGL_In=\"${COPROC[0]}\"\n\t\t\tCmdlineGL_Out=\"${COPROC[1]}\"\n\t\telse\n\t\t\t# In dark ages of bash, need to find free FDs and connect them to fifos\n\t\t\tCmdlineGL_CreateFifo || return 1\n\t\t\tCmdlineGL_NextFreeFD CmdlineGL_Out || return 1\n\t\t\teval \"exec $CmdlineGL_Out<>\\\"\\$CMDLINEGL_FIFO_DIR/out\\\"\"\n\t\t\t# Start CmdlineGL before we open the input fifo, else it would block us\n\t\t\tCmdlineGL \"${CmdlineGL_Options[@]}\" -t <&$CmdlineGL_Out >\"$CMDLINEGL_FIFO_DIR/in\" &\n\t\t\tCmdlineGL_NextFreeFD CmdlineGL_In || return 1\n\t\t\teval \"exec $CmdlineGL_In<\\\"\\$CMDLINEGL_FIFO_DIR/in\\\"\"\n\t\tfi\n\t\tCmdlineGL_Mode=rw\n\t\tCmdlineGL_Recv(){ read -r -u $CmdlineGL_In CmdlineGL_InputLine; };\n\telse\n\t\tif [[ \"${BASH_VERSINFO[0]}\" -ge 4 ]]; then\n\t\t\tcoproc CmdlineGL \"${CmdlineGL_Options[@]}\" -t --noevents || return 1\n\t\t\tCmdlineGL_Out=\"${COPROC[1]}\"\n\t\telse\n\t\t\t# In dark ages of bash, need to find free FDs and connect them to fifos\n\t\t\tCmdlineGL_CreateFifo || return 1\n\t\t\tCmdlineGL_NextFreeFD CmdlineGL_Out || return 1\n\t\t\teval \"exec $CmdlineGL_Out<>\\\"\\$CMDLINEGL_FIFO_DIR/out\\\"\"\n\t\t\tCmdlineGL \"${CmdlineGL_Options[@]}\" -t <&$CmdlineGL_Out &\n\t\tfi\n\t\tCmdlineGL_Mode=w\n\t\tCmdlineGL_Recv(){ return 1; }\n\tfi\n\tCmdlineGL_Send(){\n\t\t# Quote each argument, replacing occurrences of \\ with \\\\, newline with \\n and \" with \\\"\n\t\t{ echo -n \"$1\"; shift; for x; do x=\"${x//\\\\/\\\\\\\\}\"; x=\"${x//$'\\n'/\\\\n}\"; echo -n ' \"'\"${x//\\\"/\\\\\\\"}\"'\"'; done; echo; } >&$CmdlineGL_Out;\n\t};\n\t# Performance optimization! whee!  But not for the functions that need quoted arguments...\n\tfor cmd in \"${CmdlineGL_Commands[@]}\"; do\n\t\tif [[ \"$cmd\" != ftgl* && \"$cmd\" != cglEcho && \"$cmd\" != cglLoadImage2D  ]]; then\n\t\t\teval \"$cmd(){ echo $cmd \\\"\\$@\\\" >&$CmdlineGL_Out; }\";\n\t\tfi\n\tdone\n}\n\nCmdlineGL_CreateFifo() {\n\t# Create a FIFO unless one is already active\n\tif [[ \"z$CMDLINEGL_FIFO_DIR\" = \"z\" ]]; then\n\t\tCMDLINEGL_FIFO_DIR=$(mktemp -d -t CmdlineGL.XXXXXX);\n\telif [[ ! -d \"$CMDLINEGL_FIFO_DIR\" ]]; then\n\t\techo \"CMDLINEGL_FIFO_DIR '$CMDLINEGL_FIFO_DIR' does not exist\"\n\t\treturn 1\n\tfi\n\t[[ -e \"$CMDLINEGL_FIFO_DIR/in\" ]] || mkfifo \"$CMDLINEGL_FIFO_DIR/in\" || {\n\t\techo \"Failed to create input fifo\";\n\t\treturn 1;\n\t}\n\t[[ -e \"$CMDLINEGL_FIFO_DIR/out\" ]] || mkfifo \"$CMDLINEGL_FIFO_DIR/out\" || {\n\t\techo \"Failed to create output fifo\";\n\t\treturn 1;\n\t}\n\treturn 0;\n}\n\nCmdlineGL_NextFreeFD() {\n\tlocal fd=2 fd_max=$(ulimit -n) dest_var=$1;\n\twhile ((++fd < fd_max)); do ! true <&$fd && break; done 2>&- \\\n\t\t&& (( $dest_var=fd )) \\\n\t\t|| { echo \"No free file descriptor\"; return 1; }\n}\n"
  },
  {
    "path": "share/lib-bash/Cube.lib",
    "content": "# Simple 2x2x2 cube model, with colored faces, which auto-compiles to a display list\n\nCube_InitGfx() {\n\tglNewList Cube GL_COMPILE\n\tglBegin GL_QUADS\n\n\t# Top\n\tglNormal 0 1 0\n\tglTexCoord 1 1; glVertex 1 1 1\n\tglTexCoord 1 0; glVertex 1 1 -1\n\tglTexCoord 0 0; glVertex -1 1 -1\n\tglTexCoord 0 1; glVertex -1 1 1\n\n\t# Right\n\tglNormal 1 0 0\n\tglTexCoord 1 0; glVertex 1 1 -1\n\tglTexCoord 1 1; glVertex 1 1 1\n\tglTexCoord 0 1; glVertex 1 -1 1\n\tglTexCoord 0 0; glVertex 1 -1 -1\n\n\t# Front\n\tglNormal 0 0 1\n\tglTexCoord 1 1; glVertex 1 1 1\n\tglTexCoord 0 1; glVertex -1 1 1\n\tglTexCoord 0 0; glVertex -1 -1 1\n\tglTexCoord 1 0; glVertex 1 -1 1\n\n\t# Bottom\n\tglNormal 0 -1 0\n\tglTexCoord 1 1; glVertex 1 -1 1\n\tglTexCoord 0 1; glVertex -1 -1 1\n\tglTexCoord 0 0; glVertex -1 -1 -1\n\tglTexCoord 1 0; glVertex 1 -1 -1\n\n\t# Left\n\tglNormal -1 0 0\n\tglTexCoord 1 1; glVertex -1 1 1\n\tglTexCoord 1 0; glVertex -1 1 -1\n\tglTexCoord 0 0; glVertex -1 -1 -1\n\tglTexCoord 0 1; glVertex -1 -1 1\n\n\t# Back\n\tglNormal 0 0 -1\n\tglTexCoord 0 1; glVertex 1 1 -1\n\tglTexCoord 0 0; glVertex 1 -1 -1\n\tglTexCoord 1 0; glVertex -1 -1 -1\n\tglTexCoord 1 1; glVertex -1 1 -1\n\n\tglEnd\n\tglEndList\n\n\tCube() { glCallList Cube; }\n}\n\nCube() {\n\tCube_InitGfx\n\tglCallList Cube\n}\n"
  },
  {
    "path": "share/lib-bash/Geom.lib",
    "content": "# Library of some stuff mostly to do with cartesian points, vectors\n# and coordinate-systems.\n#\nCmdlineGL_LoadLib Trig\n\n: ${Geom_FixedPt:=1000}\n(( Geom_FixedPt= Geom_FixedPt )) # ensure integer, so it's safe to eval\ndeclare -r Geom_FixedPt=$Geom_FixedPt\n\n## Calculate the magnitude of a vector\n# For numbers which are close to forming a unit vector, the initial guess of\n# Mag^2/FixedPt is very close, and tends to converge in just 2-4 iterations.\n# Note that this only approximates sqrt, since I don't bother to round properly\n#\n# @param $1: x coordinate\n# @param $2: y coordinate\n# @param $3: z coordinate\n# @return $Result: the approximate magnitude of the vector\n#\neval \"Magnitude3D() {\n\tlocal magsq=\\$1*\\$1+\\$2*\\$2+\\$3*\\$3 mag=magsq/$Geom_FixedPt prevmag=0\n\twhile((prevmag-mag>1||mag-prevmag>1));do((prevmag=mag,mag=(mag+magsq/mag)/2));done\n\tlet Result=mag\n}\"\n\nInitPoint() {\n\tlet ${1}_x=${2:-0}\n\tlet ${1}_y=${3:-0}\n\tlet ${1}_z=${4:-0}\n\teval \"${1}_Add() { (( ${1}_x+=\\$1, ${1}_y+=\\$2, ${1}_z+=\\$3 )); }\"\n\teval \"${1}_Scale() { (( ${1}_x=${1}_x*\\$1/$Geom_FixedPt, ${1}_y=${1}_y*\\$1/$Geom_FixedPt, ${1}_z=${1}_z*\\$1/$Geom_FixedPt )); }\"\n}\n# Copy the value of Point $2 into Point $1\nClonePoint() {\n\t((${1}_x=${2}_x, ${1}_y=${2}_y, ${1}_z=${2}_z))\n}\nFreePoint() {\n\tunset ${1}_x ${1}_y ${1}_z ${1}_Add\n}\nInitVec() {\n\tInitPoint $1 $2 $3 $4\n\teval \"${1}_Magnitude() { Magnitude3D \\$${1}_x \\$${1}_y \\$${1}_z; }\"\n\teval \"${1}_SetMagnitude() {\n\t\tlocal NewMag=\\$1\n\t\t${1}_Magnitude\n\t\t((${1}_x=${1}_x*NewMag/Result, ${1}_y=${1}_y*NewMag/Result, ${1}_z=${1}_z*NewMag/Result))\n\t}\"\n\teval \"${1}_Normalize() {\n\t\t${1}_Magnitude\n\t\t((${1}_x=${1}_x*$Geom_FixedPt/Result, ${1}_y=${1}_y*$Geom_FixedPt/Result, ${1}_z=${1}_z*$Geom_FixedPt/Result))\n\t}\"\n}\nFreeVec() {\n\tunset ${1}_Magnitude ${1}_MakeUnit\n\tFreePoint $1\n}\n\nInitCoordSys() {\n\tInitVec ${1}_IV $Geom_FixedPt 0 0\n\tInitVec ${1}_JV 0 $Geom_FixedPt 0\n\tInitVec ${1}_KV 0 0 $Geom_FixedPt\n\tInitVec ${1}_Pos 0 0 0\n\n\t# Push an OpenGL Matrix that changes the modelview coordinate system to that\n \t# of this object.\n\t#\n\teval \"${1}_EnterCS() {\n\t\tglMultMatrix \\$${1}_IV_x/$Geom_FixedPt \\$${1}_IV_y/$Geom_FixedPt \\$${1}_IV_z/$Geom_FixedPt 0 \\\\\n\t\t             \\$${1}_JV_x/$Geom_FixedPt \\$${1}_JV_y/$Geom_FixedPt \\$${1}_JV_z/$Geom_FixedPt 0 \\\\\n\t\t             \\$${1}_KV_x/$Geom_FixedPt \\$${1}_KV_y/$Geom_FixedPt \\$${1}_KV_z/$Geom_FixedPt 0 \\\\\n\t\t             \\$${1}_Pos_x/$Geom_FixedPt \\$${1}_Pos_y/$Geom_FixedPt \\$${1}_Pos_z/$Geom_FixedPt 1\n\t}\"\n\n\t# Push an OpenGL matrix that enters this object's parent coordinate system.\n\t# This goes on the assumption that this object is the current coordinate system,\n\t# such as would happen if this CS were a mobile camera.\n\t# For situations where the modelview is in this coord. sys. due to a _EnterCS(),\n \t# just use glPopMatrix\n\t# Note: this could be done in a single glMultMatrix, but then bash would be\n\t# doing the math instead of OpenGL.  I'm betting its best to generate this extra\n\t# line of output, though I didn't benchmark it.\n\t#\n\teval \"${1}_ExitCS() {\n\t\tglMultMatrix \\$${1}_IV_x/$Geom_FixedPt \\$${1}_JV_x/$Geom_FixedPt \\$${1}_KV_x/$Geom_FixedPt 0 \\\\\n\t\t             \\$${1}_IV_y/$Geom_FixedPt \\$${1}_JV_y/$Geom_FixedPt \\$${1}_KV_y/$Geom_FixedPt 0 \\\\\n\t\t             \\$${1}_IV_z/$Geom_FixedPt \\$${1}_JV_z/$Geom_FixedPt \\$${1}_KV_z/$Geom_FixedPt 0 \\\\\n\t\t             0 0 0 1\n\t\tglTranslate -\\$${1}_Pos_x/$Geom_FixedPt -\\$${1}_Pos_y/$Geom_FixedPt -\\$${1}_Pos_z/$Geom_FixedPt\n\t}\"\n\n\t# Makes the I/J/K vectors into something close to unit vectors\n\t#\n\teval \"${1}_Normalize() {\n\t\t${1}_IV_Normalize\n\t\t${1}_JV_Normalize\n\t\t${1}_KV_Normalize\n\t}\"\n\n\teval \"${1}_RelativeYaw() {\n\t\tlocal angle=\\$1 x2 y2 z2 cy sy\n\t\t# K2= K * cos(y) - I * sin(y)\n\t\tsincos \\$angle\n\t\t(( sy=Result, cy=Result2,\n\t\t   ${1}_KV_x= (${1}_KV_x*cy - ${1}_IV_x*sy)/$Trig_SinScale,\n\t\t   ${1}_KV_y= (${1}_KV_y*cy - ${1}_IV_y*sy)/$Trig_SinScale,\n\t\t   ${1}_KV_z= (${1}_KV_z*cy - ${1}_IV_z*sy)/$Trig_SinScale ))\n\t\t${1}_RegenIV\n\t}\"\n\teval \"${1}_RelativePitch() {\n\t\tlocal angle=\\$1 x2 y2 z2 cy sy\n\t\t# K2= K * cos(y) - J * sin(y)\n\t\tsincos \\$angle\n\t\t(( sy=Result, cy=Result2,\n\t\t   ${1}_KV_x= (${1}_KV_x*cy - ${1}_JV_x*sy)/$Trig_SinScale,\n\t\t   ${1}_KV_y= (${1}_KV_y*cy - ${1}_JV_y*sy)/$Trig_SinScale,\n\t\t   ${1}_KV_z= (${1}_KV_z*cy - ${1}_JV_z*sy)/$Trig_SinScale ))\n\t\t${1}_RegenJV\n\t}\"\n\teval \"${1}_RelativeRoll() {\n\t\tlocal angle=\\$1 x2 y2 z2 cy sy\n\t\t# J2= J * cos(y) - I * sin(y)\n\t\tsincos \\$angle\n\t\t(( sy=Result, cy=Result2,\n\t\t   ${1}_JV_x= (${1}_JV_x*cy - ${1}_IV_x*sy)/$Trig_SinScale,\n\t\t   ${1}_JV_y= (${1}_JV_y*cy - ${1}_IV_y*sy)/$Trig_SinScale,\n\t\t   ${1}_JV_z= (${1}_JV_z*cy - ${1}_IV_z*sy)/$Trig_SinScale ))\n\t\t${1}_RegenIV\n\t}\"\n\t# I= J cross K\n\teval \"${1}_RegenIV() {\n\t\t(( x2=(${1}_JV_y*${1}_KV_z - ${1}_JV_z*${1}_KV_y)/$Geom_FixedPt, y2=(${1}_JV_z*${1}_KV_x - ${1}_JV_x*${1}_KV_z)/$Geom_FixedPt, z2=(${1}_JV_x*${1}_KV_y - ${1}_JV_y*${1}_KV_x)/$Geom_FixedPt ))\n\t\t(( ${1}_IV_x=x2, ${1}_IV_y=y2, ${1}_IV_z=z2 ))\n\t}\"\n\t# J= K cross I\n\teval \"${1}_RegenJV() {\n\t\t(( x2=(${1}_KV_y*${1}_IV_z - ${1}_KV_z*${1}_IV_y)/$Geom_FixedPt, y2=(${1}_KV_z*${1}_IV_x - ${1}_KV_x*${1}_IV_z)/$Geom_FixedPt, z2=(${1}_KV_x*${1}_IV_y - ${1}_KV_y*${1}_IV_x)/$Geom_FixedPt ))\n\t\t(( ${1}_JV_x=x2, ${1}_JV_y=y2, ${1}_JV_z=z2 ))\n\t}\"\n\t# K= I cross J\n\teval \"${1}_RegenKV() {\n\t\t(( x2=(${1}_IV_y*${1}_JV_z - ${1}_IV_z*${1}_JV_y)/$Geom_FixedPt, y2=(${1}_IV_z*${1}_JV_x - ${1}_IV_x*${1}_JV_z)/$Geom_FixedPt, z2=(${1}_IV_x*${1}_JV_y - ${1}_IV_y*${1}_JV_x)/$Geom_FixedPt ))\n\t\t(( ${1}_KV_x=x2, ${1}_KV_y=y2, ${1}_KV_z=z2 ))\n\t}\"\n}\n\n# Copy the value of CoordSys $2 into CoordSys $1\nCoordSys_Clone() {\n\tClonePoint ${1}_IV ${2}_IV\n\tClonePoint ${1}_JV ${2}_JV\n\tClonePoint ${1}_KV ${2}_KV\n\tClonePoint ${1}_Pos ${2}_Pos\n}\n\n# Print the coordinate system\nCoordSys_Print() {\n\tlocal x, y, z\n\t((x=${1}_IV_x y=${1}_IV_y z=${1}_IV_z))\n\techo \"I: ($x,\t$y,\t$z) Magnitude=$((x*x+y*y+z*z))\"\u001b[K\n\t((x=${1}_JV_x y=${1}_JV_y z=${1}_JV_z))\n\techo \"J: ($x,\t$y,\t$z) Magnitude=$((x*x+y*y+z*z))\"\u001b[K\n\t((x=${1}_KV_x y=${1}_KV_y z=${1}_KV_z))\n\techo \"K: ($x,\t$y,\t$z) Magnitude=$((x*x+y*y+z*z))\"\u001b[K\n\techo \"Origin: (${1}_Pos_x,\t${1}_Pos_y,\t${1}_Pos_z)\"\u001b[K\n}\n\nFreeCoordSys() {\n\tFreeVec ${1}_IV\n\tFreeVec ${1}_JV\n\tFreeVec ${1}_KV\n\tunset ${1}_EnterCS ${1}_ExitCS ${1}_Normalize\n\tunset ${1}_RelativeYaw ${1}_RelativePitch ${1}_RelativeRoll\n\tunset ${1}_RegenIV ${1}_RegenJV ${1}_RegenKV\n}\n"
  },
  {
    "path": "share/lib-bash/LaserBeam.lib",
    "content": "LaserBeam_InitGfx() {\n\tglNewList LaserBeam GL_COMPILE\n\n\t# Front\n\tglBegin GL_TRIANGLE_FAN\n\tglColor 1 0.7 0.7\n\tglVertex 0 0 10\n\tglColor 1 0.2 0.2\n\tglVertex 0 0.2 9\n\tglVertex -0.2 0 9\n\tglVertex 0 -0.2 9\n\tglVertex 0.2 0 9\n\tglVertex 0 0.2 9\n\tglEnd\n\n\t# Tail\n\tglBegin GL_TRIANGLE_FAN\n\tglColor 0.6 0 0\n\tglVertex 0 0 0\n\tglColor 1 0.2 0.2\n\tglVertex 0 0.2 9\n\tglVertex 0.2 0 9\n\tglVertex 0 -0.2 9\n\tglVertex -0.2 0 9\n\tglVertex 0 0.2 9\n\tglEnd\n\n\tglEndList\n\n\tLaserBeam() { glCallList LaserBeam; }\n}\n\nLaserBeam() {\n\tLaserBeam_InitGfx\n\tglCallList LaserBeam\n}\n"
  },
  {
    "path": "share/lib-bash/LinInterpolate.lib",
    "content": "# Title: LinInterpolate.sh\n# Author: Michael Conrad\n# Date:\t2005-05-29\n#\n\n## Perform a linear interpolation on a table of values, to simulate a function.\n# This routine uses linear interpolation between the nearest two\n# elements of an array containing points along the function.\n#\n# $1: Table: a name of an array\n# $2: Pos: a position of the value to retrieve, in the range 0..Max\n# $3: Max: the maximum value of Pos\ninterpolate() {\n\t# FromIdx: the index of the array to interpolate from\n\t# ToIdx: the index of the array to interpolate to\n\t# Pct: the percentage of the distance from From to To which the result should be\n\tlocal Table=$1 Pos=$2 Max=$3 TableLen From Pct Idx FromVal ToVal\n\teval \"TableLen=\\${#$Table[@]}\"\n\t(( From= Pos * (TableLen-1), Idx= From/Max, Pct= From - Idx*Max ))\n\tif ((Idx==$TableMax)); then\n\t\t(( Result=Table[Idx] ));\n\telse\n\t\t(( FromVal=$Table[Idx], ToVal=$Table[Idx+1], Result= FromVal + (ToVal - FromVal)*Pct/Max ));\n\tfi\n}\n\n## Create an interpolation function with the array and bounds \"compiled\" into it.\n# This function creates a new function which performs the same operation as\n# \"interpolate\", except that it \"compiles\" the name, maximum table element,\n# and maximum parameter value into the function as constants, for better\n# performance.\n#\n# $1: FunctionName: the name to define for the function\n# $2: Table: the name of the table to interpolate from\n# $3: InputMax: the maximum input value; this defines the domain of the function\nmake_interpolate_func() {\n\tlocal fname=$1 Table=$2 TableMax TableMax inpMax=$3\n\teval \"(( TableMax=\\${#$Table[@]} - 1 ))\"\n\teval \"$fname() {\n\t\tlocal From Pct Idx FromVal ToVal\n\t\t(( From= \\$1*$TableMax, Idx=From/$inpMax, Pct=From-Idx*$inpMax ))\n\t\tif ((Idx==$TableMax)); then\n\t\t\t(( Result=$Table[Idx] ))\n\t\telse\n\t\t\t(( FromVal=$Table[Idx], ToVal=$Table[Idx+1], Result=FromVal+(ToVal-FromVal)*Pct/$inpMax ));\n\t\tfi\n\t}\"\n}\n"
  },
  {
    "path": "share/lib-bash/ModelViewer.lib",
    "content": "# ModelView API\n#--------------------------------------\n#\n# This module sets up the translations and handles user input to give the\n# effect of a camera looking at a model, which you then render at the origin.\n#\n# Functions\n#   ModelViewer_DispatchEvent EVENT [PARAM...]\n#   ModelViewer_Update\n#   ModelViewer_ApplyMatrix\n# Variables\n#   ModelViewer_PanDegPerSec - Number of degrees to rotate per second of continual up/down/left/right keypress\n#   ModelViewer_ZoomPctPerSec - Percentage of distance to model which we will travel in one second\n#   ModelViewer_Distance   - Initial camera distance from the model\n#   ModelViewer_Pitch      - Initial camera vertical angle above the model\n#   ModelViewer_Direction  - Initial camera sideways angle around the model\n#\n\nCmdlineGL_LoadLib Timing\n\nModelViewer_Zoom=1000\nModelViewer_Pitch=0\nModelViewer_Direction=0\n\nModelViewer_MDrag=0\nModelViewer_Left=0\nModelViewer_Right=0\nModelViewer_Up=0\nModelViewer_Down=0\nModelViewer_Grow=0\nModelViewer_Shrink=0\nModelViewer_PanDegPerSec=90\nModelViewer_ZoomPctPerSec=40\n\n# DispatchEvent returns true if it consumed the event, false otherwise.\n# Positonal arguments are as received from CmdlineGL\nModelViewer_DispatchEvent() {\n\t(( $# > 0 )) || return 1\n\tlocal Press\n\tcase \"$1\" in\n\tK)\n\t\tif [[ \"$2\" == + ]]; then Press=1; else Press=0; fi\n\t\tcase \"$3\" in\n\t\tright) ((ModelViewer_Right= Press));;\n\t\tleft)  ((ModelViewer_Left=  Press));;\n\t\tup)    ((ModelViewer_Up=    Press));;\n\t\tdown)  ((ModelViewer_Down=  Press));;\n\t\t=)     ((ModelViewer_Grow=  Press));;\n\t\t-)     ((ModelViewer_Shrink=Press));;\n\t\t*)     return 1;; # not consumed\n\t\tesac\n\t\treturn 0 # consumed\n\t\t;;\n\tM)\n\t\tcase \"$2\" in\n\t\t@)\n\t\t\tlocal dx=\"$5\" dy=\"$6\";\n\t\t\t# Handle mouse drag actions.\n\t\t\t# If the mouse has moved since last time change the pitch or direction\n\t\t\t# by the vertical or horizontal distance the mouse has moved.\n\t\t\tif ((ModelViewer_MDrag)); then\n\t\t\t\t((ModelViewer_Pitch+= dy*1000))\n\t\t\t\t((ModelViewer_Direction+= dx*1000));\n\t\t\t\treturn 0 # consumed\n\t\t\tfi\n\t\t\t;;\n\t\t+)\n\t\t\tif [[ \"$3\" == 1 ]]; then\n\t\t\t\tModelViewer_MDrag=1\n\t\t\t\treturn 0 # consumed\n\t\t\tfi;;\n\t\t-)\n\t\t\tif [[ \"$3\" == 1 ]]; then\n\t\t\t\tModelViewer_MDrag=0\n\t\t\t\treturn 0 # consumed\n\t\t\tfi;;\n\t\tesac\n\t\treturn 1 # not consumed\n\t\t;;\n\tesac\n}\n\n# The user input events toggle variables, but don't modify the viewer state, yet.\n# Call Update once per frame to apply those inputs to the viewer state.\nModelViewer_Update() {\n\t# All numbers are scaled by 1000 to match time reported in milliseconds\n\t((ModelViewer_Left))  && ((ModelViewer_Direction+=Timing_dT*ModelViewer_PanDegPerSec))\n\t((ModelViewer_Right)) && ((ModelViewer_Direction-=Timing_dT*ModelViewer_PanDegPerSec))\n\t((ModelViewer_Up))    && ((ModelViewer_Pitch-=Timing_dT*ModelViewer_PanDegPerSec))\n\t((ModelViewer_Down))  && ((ModelViewer_Pitch+=Timing_dT*ModelViewer_PanDegPerSec))\n\tlocal adjust;\n\t((adjust=ModelViewer_Grow? ( ModelViewer_Shrink? 0 : -1 ) : ModelViewer_Shrink? 1 : 0))\n\t((adjust= adjust + adjust * ModelViewer_ZoomPctPerSec*ModelViewer_Zoom*Timing_dT/100000))\n\t((ModelViewer_Zoom += adjust))\n\t((ModelViewer_Zoom>=10)) || ((ModelViewer_Zoom=10))\n}\n\n# Call this right after LoadIdentity to move from camera space to model space\nModelViewer_ApplyMatrix() {\n\tglScale 1000/$ModelViewer_Zoom\n\tglRotate $ModelViewer_Pitch/1000 1/1 0 0\n\tglRotate $ModelViewer_Direction/1000 0 1/1 0\n}\n"
  },
  {
    "path": "share/lib-bash/RenderLoop.lib",
    "content": "CmdlineGL_LoadLib Timing\n\n# RenderLoop API\n#--------------------------------------\n# Functions:\n#   RenderLoop_Run\n# Callbacks (to be implemented by user)\n#   RenderLoop_Render\n#   RenderLoop_DispatchEvent EVENT_TYPE [EVENT_ARGS...]\n#\n# Variables:\n#   RenderLoop_Done: bool - Set to true in order to end main loop\n#\nRenderLoop_Done=0\n\n# Generic do-nothing place holder to be replaced by caller\nRenderLoop_Render() {\n\tglClear GL_COLOR_BUFFER_BIT\n\tcglSwapBuffers\n}\n\n# Generic do-nothing place holder which receives each input event\nRenderLoop_DispatchEvent() {\n\tfalse\n}\n\n# Using Timing lib, repeatedly run RenderLoop_Render and RenderLoop_DispatchEvent\n# as needed and terminate when RenderLoop_Done is set.\nRenderLoop_Run() {\n\tRenderLoop_Done=\"\";\n\tif [[ -z \"$CmdlineGL_In\" ]]; then\n\t\t# For write-only mode, assume a constant max frame rate.\n\t\t# If we get too far ahead, the pipe will fill and pause us.\n\t\twhile (( !RenderLoop_Done )); do\n\t\t\tRenderLoop_Render || true\n\t\t\tTiming_SyncNextFrame\n\t\t\tTiming_AssumeNextFrame\n\t\tdone\n\telse\n\t\t# For read-write mode, ask for the time before starting the frame,\n\t\t# then when we collect the input we know we're done when we see\n\t\t# the timestamp come back, and don't need to do awkward non-blocking\n\t\t# reads.\n\t\tcglGetTime\n\t\twhile (( !RenderLoop_Done )); do\n\t\t\tRenderLoop_Render || true\n\t\t\tTiming_SyncNextFrame\n\t\t\tRenderLoop_ProcessInput\n\t\t\tcglGetTime\n\t\tdone\n\tfi\n}\n\n# Split out for readability\nRenderLoop_ProcessInput() {\n\tlocal ReadMore=1 ReadTimeout=0\n\twhile ((ReadMore)); do\n\t\tif CmdlineGL_Recv; then\n\t\t\tif [[ \"$CmdlineGL_InputLine\" == t=* ]]; then\n\t\t\t\t# The time is the last thing we read for this frame's input\n\t\t\t\tTiming_Update ${CmdlineGL_InputLine:2}\n\t\t\t\tReadMore=0\n\t\t\telse\n\t\t\t\tRenderLoop_DispatchEvent $CmdlineGL_InputLine\n\t\t\tfi\n\t\telse\n\t\t\tlet ReadTimeout++\n\t\t\tif ((ReadTimeout>3)); then\n\t\t\t\tRenderLoop_Done=1\n\t\t\t\tReadMore=0\n\t\t\t\techo \"Reading from pipe timed out...  shutting down.\" >&2\n\t\t\tfi\n\t\tfi\n\tdone\n}\n"
  },
  {
    "path": "share/lib-bash/Ship.lib",
    "content": "# This is the model for the player's ship.\n# It was originally designed facing the -Z axis, but then I decided to make\n# all my models face down +z, and rather than mangling all the coordinates,\n# I just rotate 180 before drawing it.\n#\n\nCmdlineGL_LoadLib Trig Geom\n\nShip_Throttle=1\nShip_Initialized=0\nShip_GunXOffset=( -$((12*Geom_FixedPt/10)) $((12*Geom_FixedPt/10)) -$((16*Geom_FixedPt/10)) $((16*Geom_FixedPt/10)) )\nShip_GunYOffset=$((3*Geom_FixedPt/10))\nShip_GunZOffset=$((9*Geom_FixedPt/10))\n\nShip_WingShield() {\n\t#inside\n\tglBegin GL_TRIANGLE_FAN;\n\tglNormal 1 0 0; \tglVertex 0 0 0\n\tglNormal 1 0 0.2;\tglVertex 0.2 0 -3\n\tglNormal 1 -0.7 0;\tglVertex 0.2 1 0.5\n\tglNormal 1 0 -0.2;\tglVertex 0.2 0 2\n\tglNormal 1 0.7 0;\tglVertex 0.2 -1 0.5\n\tglNormal 1 0 0.2;\tglVertex 0.2 0 -3\n\tglEnd\n\t#outside\n\tglBegin GL_TRIANGLE_FAN;\n\tglNormal -1 0 0;\tglVertex -0.5 0 0\n\tglNormal -1 1 0;\tglVertex 0.2 1 0.5\n\tglNormal -1 0 -0.3;\tglVertex 0.2 0 -3\n\tglNormal -1 -1 0;\tglVertex 0.2 -1 0.5\n\tglNormal -1 0 0.3;\tglVertex 0.2 0 2\n\tglNormal -1 1 0;\tglVertex 0.2 1 0.5\n\tglEnd\n}\n\nShip_Wing() {\n\tglBegin GL_QUAD_STRIP\n\tglNormal 0 1 0.1;   glVertex -2 0 0.5;     glVertex 0 0 1.5\n\tglNormal 0 1 -0.1;  glVertex -2 0.3 -0.3;  glVertex 0 0.3 -0.5\n\tglNormal 0 0 -1;    glVertex -2 0 -0.4;    glVertex 0 0 -0.6\n\tglNormal 0 -2 -0.1; glVertex -2 -0.3 -0.3; glVertex 0 -0.3 -0.5\n\tglNormal 0 -1 0.1;  glVertex -2 0 0.5;     glVertex 0 0 1.5\n\tglEnd\n}\n\nShip_HalfBody() {\n\tglBegin GL_TRIANGLE_STRIP\n\tglNormal 0.1 1 -0.1\n\tglVertex 0 0 -6\n\tglVertex 0 0.2 -4\n\tglVertex 0.8 0 -4.5\n\tglNormal 0 1 0\n\tglVertex 0 0.3 -3\n\tglVertex 1 0 -3.3\n\tglNormal 0 1 -0.3\n\tglVertex 0 0.2 0\n\tglVertex 0.8 0 0\n\tglEnd\n\tglBegin GL_TRIANGLE_STRIP\n\tglNormal 0.1 -1 -0.1\n\tglVertex 0 0 -6\n\tglVertex 0.8 0 -4.5\n\tglVertex 0 -0.2 -4\n\tglNormal 0 -1 0\n\tglVertex 1 0 -3.3\n\tglVertex 0 -0.3 -3\n\tglNormal 0 -1 -0.3\n\tglVertex 0.8 0 0\n\tglVertex 0 -0.2 0\n\tglEnd\n}\n\nShip_Thruster() {\n\t# Back half of thruster\n\tgluCylinder thruster 0.4 0.2 1.7 7 1\n\tglTranslate 0 0 1.7\n\tgluCylinder thruster 0.2 0.17 0 7 1\n\tglTranslate 0 0 -1.7\n\tglRotate 180 0 1 0\n\t# Front half of thruster\n\tgluCylinder thruster 0.4 0.2 1.1 7 1\n\tglTranslate 0 0 1.1\n\tgluCylinder thruster 0.18 0.2 0 7 1\n\tgluCylinder innerthruster 0.18 0.0 -0.5 7 1\n}\nShip_BuildThrustLists() {\n\tglNewList Thrust0 GL_COMPILE\n\tglDisable GL_LIGHTING\n\tglBegin GL_TRIANGLE_FAN\n\tglColor '#770000'\n\tglVertex 0 0 1.5\n\tglColor '#330000'\n\tfor ((i=0; i<8; i++)); do\n\t\tsincos $((-36000*i/7))\n\t\tglVertex $((Result*18))/1000000 $((Result2*18))/1000000 1.7\n\tdone\n\tglEnd\n\tglEnable GL_LIGHTING\n\tglEndList\n\n\tglNewList Thrust1 GL_COMPILE\n\tglDisable GL_LIGHTING\n\tglDisable GL_CULL_FACE\n\tglBegin GL_TRIANGLE_FAN\n\tglColor '#CC3300'\n\tglVertex 0 0 1.5\n\tglColor '#551100'\n\tfor ((i=0; i<8; i++)); do\n\t\tsincos $((-36000*i/7))\n\t\tglVertex $((Result*18))/1000000 $((Result2*18))/1000000 1.7\n\tdone\n\tglEnd\n\tglBlendFunc GL_SRC_ALPHA GL_ONE\n\tglEnable GL_BLEND\n\tglBegin GL_TRIANGLE_STRIP\n\tfor ((i=0; i<8; i++)); do\n\t\tsincos $((36000*i/7))\n\t\tglColor '#AA0000DD'\n\t\tglVertex $((Result*18))/1000000 $((Result2*18))/1000000 1.7\n\t\tglColor '#33000000'\n\t\tglVertex $((Result*8))/1000000 $((Result2*8))/1000000 2.3\n\tdone\n\tglEnd\n\tglEnable GL_CULL_FACE\n\tglDisable GL_BLEND\n\tglEnable GL_LIGHTING\n\tglEndList\n}\nShip_Thrust() {\n\tglRotate $RANDOM 0 0 1\n\tif ((Ship_Throttle)); then glCallList Thrust1; else glCallList Thrust0; fi\n}\nShip_Gun() {\n\tglPushMatrix\n\tglBegin GL_TRIANGLE_FAN\n\tglNormal 0 1 0; \tglVertex 0 0.1 0\n\tglNormal 0 0.5 1;\tglVertex 0 -0.15 0.3\n\tglNormal 1 0.5 -1;\tglVertex 0.1 0 -0.1\n\tglNormal -1 0.5 -1;\tglVertex -0.1 0 -0.1\n\tglNormal 0 0.5 1;\tglVertex 0 -0.15 0.3\n\tglEnd\n\tglTranslate 0 0 -1\n\tgluCylinder gun 0.025 0.05 1 5 1\n\tglPopMatrix\n}\n\nShip_InitGfx() {\n\tgluNewQuadric thruster\n\tgluNewQuadric innerthruster\n\tgluNewQuadric gun\n\tgluQuadricOrientation innerthruster GLU_INSIDE\n\n\tglNewList Ship GL_COMPILE\n\tglDisable GL_TEXTURE_2D\n\tglColor 0.4 0.4 0.4\n\tglPushMatrix\n\t\tShip_HalfBody\n\t\tShip_Wing\n\t\tglTranslate -2 0 0\n\t\tShip_WingShield\n\t\tglTranslate 4 0 0\n\t\tglRotate 180 0 0 1\n\t\tShip_WingShield\n\t\tglTranslate 2 0 0\n\t\tShip_Wing\n\t\tShip_HalfBody\n\tglPopMatrix\n\n\tglColor 0.2 0.2 0.2\n\tglPushMatrix\n\t\tglTranslate -1.9 -0.4 -0.2\n\t\tglRotate 10 0 1 0\n\t\tglRotate 5 1 0 0\n\t\tShip_Thruster\n\tglPopMatrix\n\tglPushMatrix\n\t\tglTranslate 1.9 -0.4 -0.2\n\t\tglRotate -10 0 1 0\n\t\tglRotate 5 1 0 0\n\t\tShip_Thruster\n\tglPopMatrix\n\n\tglPushMatrix\n\t\tglTranslate -1.2 0.3 -0.1\n\t\tShip_Gun\n\t\tglTranslate -0.4 0 0\n\t\tShip_Gun\n\t\tglTranslate 2.8 0 0\n\t\tShip_Gun\n\t\tglTranslate 0.4 0 0\n\t\tShip_Gun\n\tglPopMatrix\n\tglEndList\n\n\tShip_BuildThrustLists\n\n\tShip_Initialized=1;\n}\n\nShip() {\n\t((Ship_Initialized))||Ship_InitGfx\n\tcglPushDivisor 1\n\tglPushMatrix\n\tglRotate 180 0 1 0 # reverse model on Z axis\n\tglCallList Ship\n\tglPushMatrix\n\tglTranslate -1.9 -0.4 -0.2\n\tglRotate 10 0 1 0\n\tglRotate 5 1 0 0\n\tShip_Thrust\n\tglPopMatrix\n\tglTranslate 1.9 -0.4 -0.2\n\tglRotate -10 0 1 0\n\tglRotate 5 1 0 0\n\tShip_Thrust\n\tglPopMatrix\n\tcglPopDivisor\n}\n"
  },
  {
    "path": "share/lib-bash/Timing.lib",
    "content": "# Prevent multiple inclusion\n[[ -z ${TIMING_LIB+x} ]] || return 0\nTIMING_LIB=1;\n\n# Timing API\n#--------------------------------------\n#\n# This library uses a concept of \"Virtual Frames per Second\"; any time the\n# game loop isn't able to maintain the minimum frame rate it will slow down\n# the game time to match the speed of the computer.  In other words, Timing_T\n# may count slower than real time in order to maintain the minimum FPS needed\n# by game logic.\n#\n# Functions:\n#   Timing_SetMinMaxFPS MIN MAX\n#   Timing_Update TIME\n#   Timing_SyncNextFrame\n#   Timing_AssumeNextFrame\n#   Timing_PrintFPS\n#\n# Variables:\n#\n#   Timing_T: milliseconds - virtual time\n#   Timing_RT: milliseconds - real time\n#   Timing_Frame: current frame number\n#   Timing_dT: milliseconds - virtual time elapsed since last frame\n#   Timing_FPS: int - frames per real second\n#   Timing_FPVS: int - frames per virtual second\n#   Timing_AvgCount: int - number of samples to average\n#   Timing_MinFPS: int - lowest allowed FPVS\n#   Timing_MaxFPS: int - highest allowed FPS\n#\nTiming_T=0;\nTiming_RT=0;\nTiming_Slip=0;\nTiming_dT=0;\nTiming_dTAvg=100;\nTiming_dRTAvg=100;\nTiming_AvgCount=10;\nTiming_FPS=0;\nTiming_FPVS=0;\nTiming_FPSPrint_dT=0;\nTiming_FPSLastPrint=0;\nTiming_Frame=0;\n\n# Choose the minimum frame rate (below which the \"game time\" slows down)\n# and the max frame rate (above which we sleep)\nTiming_SetMinMaxFPS() {\n\tlocal NewMin=$1\n\tlocal NewMax=$2\n\t(( Timing_MinFPS=NewMin ))\n\t(( Timing_MaxFPS=NewMax ))\n\t(( Timing_MaxFPS < Timing_MinFPS )) && (( Timing_MaxFPS=Timing_MinFPS ))\n\t(( Timing_MaxFPS < 1 )) && Timing_MaxFPS=1\n\t(( Timing_Min_dT=1000/Timing_MaxFPS ))\n\tif (( Timing_MinFPS > 0 )); then\n\t\t(( Timing_Max_dT=(1000+Timing_MinFPS/2)/Timing_MinFPS )) # round up\n\telse\n\t\tTiming_Max_dT=1000000;\n\tfi\n}\n\n# Update the game time with a new \"Real\" timestamp, and assume a frame is completed.\n# This will adjust the game time according to Min FPS, and recalculate the current FPS\nTiming_Update() {\n\tlocal NewTime=$1\n\t((\n\t\tTiming_dT=NewTime-Timing_RT,\n\t\tTiming_Frame++,\n\t\tTiming_dT<1? Timing_dT=1 : 1,\n\t\tTiming_dRTAvg= (Timing_dRTAvg * Timing_AvgCount + Timing_dT*100) / (Timing_AvgCount+1),\n\t\tTiming_dT>Timing_Max_dT? Timing_dT=Timing_Max_dT : 1,\n\t\tTiming_RT=NewTime, Timing_T+=Timing_dT,\n\t\tTiming_dTAvg= (Timing_dTAvg * Timing_AvgCount + Timing_dT*100) / (Timing_AvgCount+1),\n\n\t\tTiming_FPVS=100000/Timing_dTAvg, Timing_FPS=100000/Timing_dRTAvg,\n\t\t1\n\t))\n\tif (( (Timing_FPSPrint_dT? (Timing_T - Timing_FPSLastPrint) : -1) > Timing_FPSPrint_dT )); then\n\t\tTiming_PrintFPS\n\t\t((Timing_FPSLastPrint+=Timing_FPSPrintFreq, Frame=0))\n\tfi\n\treturn 0\n}\n\n# Send the command to CmdlineGL asking it to pause until the given timestamp.\nTiming_SyncNextFrame() {\n\tcglSync $(( Timing_RT+Timing_Min_dT ))\n}\n\n# Simulate a maximum frame rate.  Used when we don't get feedback from CmdlineGL\n# about the current time, like when generating a recording.\nTiming_AssumeNextFrame() {\n\tTiming_Update $(( Timing_RT+Timing_Min_dT ))\n}\n\n# Called automatically by Update if Timing_FPSPrint_dT > 0\nTiming_PrintFPS() {\n\techo \"FPS: $Timing_FPS  $Timing_Frame\" >&2\n}\n\nTiming_SetMinMaxFPS 10 80\n"
  },
  {
    "path": "share/lib-bash/Trig.lib",
    "content": "# Title: Trig.sh\n# Author: Michael Conrad\n# Date: 2005-05-29\n#\n# Some useful trig functions.\n# All are approximated using linear interpolation over a table of values.\n#\nCmdlineGL_LoadLib LinInterpolate\nTrig_SinScale=10000\n\nSIN_TABLE=( 0 0523 1045 1564 2079 2588 3090 3584 4067 4540 5000 5446 5878 6293 6691 7071 7431 7771 8090 8387 8660 8910 9135 9336 9511 9659 9781 9877 9945 9986 10000 )\nSIN_TABLE_LEN=${#SIN_TABLE[@]}\nlet SIN_TABLE_MAX=SIN_TABLE_LEN-1\n\nASIN_TABLE=( 0 115 229 344 459 574 689 805 921 1037 1154 1271 1389 1507 1626 1746 1866 1988 2110 2233 2358 2483 2610 2739 2869 3000 3133 3268 3406 3545 3687 3832 3979 4130 4284 4443 4605 4773 4946 5126 5313 5508 5714 5932 6164 6416 6693 7005 7374 7852 9000 )\nASIN_TABLE_LEN=${#ASIN_TABLE[@]}\nASIN_TAIL_TABLE=( 6416 6469 6523 6578 6635 6693 6752 6813 6875 6939 7005 7073 7144 7218 7294 7374 7456 7547 7641 7742 7852 7974 8111 8275 8487 9000 )\nASIN_TAIL_TABLE_LEN=${#ASIN_TAIL_TABLE[@]}\nlet ASIN_TABLE_MAX=ASIN_TABLE_LEN-1\nlet ASIN_TAIL_TABLE_MAX=ASIN_TAIL_TABLE_LEN-1\n\n## Autogeneration of \"trig_interpolate\"\n# This generates an interpolation function that uses SIN_TABLE and\n# expects params in the range 0-9000\n#\nmake_interpolate_func trig_interpolate SIN_TABLE 9000\n\n## Autogeneration of \"trig_inv_interpolate\"\n# This generates an interpolation function for the inverse trig functions\n# that uses ASIN_TABLE and expects params in the range 0-10000\n#\n# trig_inv_tail_interpolate handles arcsin inputs of 9000-10000\n# It provides much better tracking of the arcsin function over this range\n#\nmake_interpolate_func trig_inv_interpolate ASIN_TABLE 10000\nmake_interpolate_func trig_inv_tail_interpolate ASIN_TAIL_TABLE 1000\n\n## Get the sine of an angle\n# @Param $1: the angle, as an integer from 0 to 36000 (or any modular equivalent)\n# @return $Result: the sin of the angle, from -10000 to 10000\n#\nsin() {\n\tlocal Angle=$1 Flip=1\n\t(( Angle=(Angle%36000+36000)%36000 ));\n\tif (( Angle >= 18000 )); then (( Angle-=18000, Flip=-1 )); fi\n\tif (( Angle >= 9000 )); then (( Angle=18000-Angle )); fi\n\ttrig_interpolate $Angle\n\t(( Result*=Flip ));\n}\n\n## Get the cosine of an angle\n# @Param $1: the angle, as an integer from 0 to 36000 (or any modular equivalent)\n# @return $Result: the cos of the angle, from -10000 to 10000\n#\ncos() {\n\tlocal Angle=$1 Flip=1\n\t(( Angle=(Angle%36000+36000)%36000 ));\n\tif (( Angle >= 18000 )); then (( Angle=36000-Angle )); fi\n\tif (( Angle >= 9000 )); then (( Angle-=9000, Flip=-1 )); else (( Angle=9000-Angle )); fi\n\ttrig_interpolate $Angle\n\t(( Result*=Flip ));\n}\n\n## Perform both Sine and Cosine\n# This function performs both the sin and cosine on an angle, and runs significantly\n# faster than calling them separately.\n#\n# @Param $1: the angle, as an integer from 0 to 36000 (or any modular equivalent)\n# @return $Result: the sin of the angle, from -10000 to 10000\n# @return $Result2: the cos of the angle, from -10000 to 10000\n#\n# It was a sad day indeed when I realized that runtimes went down when I eliminated whitespace,\n# and that doing the substitutions during the declaration of the function instead of at runtime\n# made a significant difference...\n#\neval \"sincos() {\nlocal Angle sFlip=1 cFlip=1 From Pct Idx FromVal ToVal\n((Angle=(\\$1%36000+36000)%36000));\nif((Angle>=9000&&Angle<27000)); then cFlip=-1;fi\nif((Angle>=18000));then((Angle-=18000,sFlip=-1));fi\nif((Angle>=9000));then((Angle=18000-Angle));fi\n((From=Angle*$SIN_TABLE_MAX,Idx=From/9000,Pct=From-Idx*9000))\nif((Idx==$SIN_TABLE_MAX));then\n((Result=SIN_TABLE[$SIN_TABLE_MAX]*sFlip,Result2=SIN_TABLE[0]*cFlip))\nelse\n((FromVal=SIN_TABLE[Idx],ToVal=SIN_TABLE[Idx+1],Result=(FromVal+(ToVal-FromVal)*Pct/9000)*sFlip));\n((FromVal=SIN_TABLE[$SIN_TABLE_MAX-Idx],ToVal=SIN_TABLE[$((SIN_TABLE_MAX-1))-Idx],Result2=(FromVal+(ToVal-FromVal)*Pct/9000)*cFlip));\nfi\n}\"\n\ntan() {\n\tsincos $1\n\t(( Result=Result*10000/Result2 ))\n}\n\n## Get the angle of a Sine\n# @Param $1: the sine of the angle, as an integer from -10000..10000\n# @return Result: the angle of the sine, as an integer from -9000..9000\n#\nasin() {\n\tlocal Sin=$1 Sign=1\n\tif (( Sin < 0 )); then (( Sin=-Sin, Sign=-1 )); fi\n\tif (( Sin <= 9000 )); then trig_inv_interpolate $Sin\n\telse (( Sin=Sin-9000 )); trig_inv_tail_interpolate $Sin; fi\n\t(( Result*=Sign ));\n}\n\n## Get the angle of a Cosine\n# @Param $1: the cosine of the angle, as an integer from -10000 to 10000\n# @return Result: the angle of the cosine, as an integer from 0 to 18000\n#\nacos() {\n\tlocal Cos=$1 Sign=1\n\tif (( Cos < 0 )); then (( Cos=-Cos, Sign=-1 )); fi\n\tif (( Cos <= 9000 )); then trig_inv_interpolate $Cos\n\telse (( Cos=Cos-9000 )); trig_inv_tail_interpolate $Cos; fi\n\t(( Result=9000-(Result*Sign) ));\n}\n"
  },
  {
    "path": "share/lib-sh/CmdlineGL.lib",
    "content": "CmdlineGL_setup_fifo() {\n\t# Create a FIFO unless one is already active\n\tif [ \"z$CMDLINEGL_FIFO_DIR\" = \"z\" ]; then\n\t\tCMDLINEGL_FIFO_DIR=$(mktemp -d -t CmdlineGL.XXXXXX);\n\telif [ ! -d \"$CMDLINEGL_FIFO_DIR\" ]; then\n\t\techo \"CMDLINE_FIFO_DIR '$CMDLINEGL_FIFO_DIR' does not exist\"\n\t\treturn 1\n\tfi\n\t[ -e \"$CMDLINEGL_FIFO_DIR/out\" ] || mkfifo \"$CMDLINEGL_FIFO_DIR/out\" || {\n\t\techo \"Failed to create output fifo\";\n\t\treturn 1;\n\t}\n\t[ -e \"$CMDLINEGL_FIFO_DIR/in\" ] || mkfifo \"$CMDLINEGL_FIFO_DIR/in\" || {\n\t\techo \"Failed to create input fifo\";\n\t\treturn 1;\n\t}\n\treturn 0;\n}\n\nCmdlineGL_Start() {\n\tCmdlineGL_setup_fifo\n\tif [ \"x$1\" = \"rw\" ]; then\n\t\tCmdlineGL -f $CmdlineGL_Out > $CmdlineGL_In &\n\t\tCmdlineGL_Mode=rw\n\t\tCmdlineGL_Out=$CMDLINEGL_FIFO_DIR/out;\n\t\tCmdlineGL_In=$CMDLINEGL_FIFO_DIR/in;\n\telse\n\t\tCmdlineGL -f $CmdlineGL_Out --nouimsg &\n\t\tCmdlineGL_Mode=w\n\t\tCmdlineGL_Out=$CMDLINEGL_FIFO_DIR/out;\n\tfi\n}\n# build functions for each available command in the API\nfor cmd in `CmdlineGL --showcmds`; do\n\teval \"$cmd() { test \\\"z\\$CmdlineGL_Mode\\\" != \\\"z\\\" || CmdlineGL_start; echo \\\"$cmd \\$@\\\" >>\\$CmdlineGL_Out; }\"\ndone\nCmdlineGL_ReadInput() {\n\tCmdlineGL_InputLine=$(read -r <$CmdlineGL_In);\n}\n"
  },
  {
    "path": "src/ConstList.Win32.txt",
    "content": "GL_VERSION_1_1\nGL_ACCUM\nGL_LOAD\nGL_RETURN\nGL_MULT\nGL_ADD\nGL_NEVER\nGL_LESS\nGL_EQUAL\nGL_LEQUAL\nGL_GREATER\nGL_NOTEQUAL\nGL_GEQUAL\nGL_ALWAYS\nGL_CURRENT_BIT\nGL_POINT_BIT\nGL_LINE_BIT\nGL_POLYGON_BIT\nGL_POLYGON_STIPPLE_BIT\nGL_PIXEL_MODE_BIT\nGL_LIGHTING_BIT\nGL_FOG_BIT\nGL_DEPTH_BUFFER_BIT\nGL_ACCUM_BUFFER_BIT\nGL_STENCIL_BUFFER_BIT\nGL_VIEWPORT_BIT\nGL_TRANSFORM_BIT\nGL_ENABLE_BIT\nGL_COLOR_BUFFER_BIT\nGL_HINT_BIT\nGL_EVAL_BIT\nGL_LIST_BIT\nGL_TEXTURE_BIT\nGL_SCISSOR_BIT\nGL_ALL_ATTRIB_BITS\nGL_POINTS\nGL_LINES\nGL_LINE_LOOP\nGL_LINE_STRIP\nGL_TRIANGLES\nGL_TRIANGLE_STRIP\nGL_TRIANGLE_FAN\nGL_QUADS\nGL_QUAD_STRIP\nGL_POLYGON\nGL_ZERO\nGL_ONE\nGL_SRC_COLOR\nGL_ONE_MINUS_SRC_COLOR\nGL_SRC_ALPHA\nGL_ONE_MINUS_SRC_ALPHA\nGL_DST_ALPHA\nGL_ONE_MINUS_DST_ALPHA\nGL_DST_COLOR\nGL_ONE_MINUS_DST_COLOR\nGL_SRC_ALPHA_SATURATE\nGL_TRUE\nGL_FALSE\nGL_CLIP_PLANE0\nGL_CLIP_PLANE1\nGL_CLIP_PLANE2\nGL_CLIP_PLANE3\nGL_CLIP_PLANE4\nGL_CLIP_PLANE5\nGL_BYTE\nGL_UNSIGNED_BYTE\nGL_SHORT\nGL_UNSIGNED_SHORT\nGL_INT\nGL_UNSIGNED_INT\nGL_FLOAT\nGL_2_BYTES\nGL_3_BYTES\nGL_4_BYTES\nGL_DOUBLE\nGL_NONE\nGL_FRONT_LEFT\nGL_FRONT_RIGHT\nGL_BACK_LEFT\nGL_BACK_RIGHT\nGL_FRONT\nGL_BACK\nGL_LEFT\nGL_RIGHT\nGL_FRONT_AND_BACK\nGL_AUX0\nGL_AUX1\nGL_AUX2\nGL_AUX3\nGL_NO_ERROR\nGL_INVALID_ENUM\nGL_INVALID_VALUE\nGL_INVALID_OPERATION\nGL_STACK_OVERFLOW\nGL_STACK_UNDERFLOW\nGL_OUT_OF_MEMORY\nGL_2D\nGL_3D\nGL_3D_COLOR\nGL_3D_COLOR_TEXTURE\nGL_4D_COLOR_TEXTURE\nGL_PASS_THROUGH_TOKEN\nGL_POINT_TOKEN\nGL_LINE_TOKEN\nGL_POLYGON_TOKEN\nGL_BITMAP_TOKEN\nGL_DRAW_PIXEL_TOKEN\nGL_COPY_PIXEL_TOKEN\nGL_LINE_RESET_TOKEN\nGL_EXP\nGL_EXP2\nGL_CW\nGL_CCW\nGL_COEFF\nGL_ORDER\nGL_DOMAIN\nGL_CURRENT_COLOR\nGL_CURRENT_INDEX\nGL_CURRENT_NORMAL\nGL_CURRENT_TEXTURE_COORDS\nGL_CURRENT_RASTER_COLOR\nGL_CURRENT_RASTER_INDEX\nGL_CURRENT_RASTER_TEXTURE_COORDS\nGL_CURRENT_RASTER_POSITION\nGL_CURRENT_RASTER_POSITION_VALID\nGL_CURRENT_RASTER_DISTANCE\nGL_POINT_SMOOTH\nGL_POINT_SIZE\nGL_POINT_SIZE_RANGE\nGL_POINT_SIZE_GRANULARITY\nGL_LINE_SMOOTH\nGL_LINE_WIDTH\nGL_LINE_WIDTH_RANGE\nGL_LINE_WIDTH_GRANULARITY\nGL_LINE_STIPPLE\nGL_LINE_STIPPLE_PATTERN\nGL_LINE_STIPPLE_REPEAT\nGL_LIST_MODE\nGL_MAX_LIST_NESTING\nGL_LIST_BASE\nGL_LIST_INDEX\nGL_POLYGON_MODE\nGL_POLYGON_SMOOTH\nGL_POLYGON_STIPPLE\nGL_EDGE_FLAG\nGL_CULL_FACE\nGL_CULL_FACE_MODE\nGL_FRONT_FACE\nGL_LIGHTING\nGL_LIGHT_MODEL_LOCAL_VIEWER\nGL_LIGHT_MODEL_TWO_SIDE\nGL_LIGHT_MODEL_AMBIENT\nGL_SHADE_MODEL\nGL_COLOR_MATERIAL_FACE\nGL_COLOR_MATERIAL_PARAMETER\nGL_COLOR_MATERIAL\nGL_FOG\nGL_FOG_INDEX\nGL_FOG_DENSITY\nGL_FOG_START\nGL_FOG_END\nGL_FOG_MODE\nGL_FOG_COLOR\nGL_DEPTH_RANGE\nGL_DEPTH_TEST\nGL_DEPTH_WRITEMASK\nGL_DEPTH_CLEAR_VALUE\nGL_DEPTH_FUNC\nGL_ACCUM_CLEAR_VALUE\nGL_STENCIL_TEST\nGL_STENCIL_CLEAR_VALUE\nGL_STENCIL_FUNC\nGL_STENCIL_VALUE_MASK\nGL_STENCIL_FAIL\nGL_STENCIL_PASS_DEPTH_FAIL\nGL_STENCIL_PASS_DEPTH_PASS\nGL_STENCIL_REF\nGL_STENCIL_WRITEMASK\nGL_MATRIX_MODE\nGL_NORMALIZE\nGL_VIEWPORT\nGL_MODELVIEW_STACK_DEPTH\nGL_PROJECTION_STACK_DEPTH\nGL_TEXTURE_STACK_DEPTH\nGL_MODELVIEW_MATRIX\nGL_PROJECTION_MATRIX\nGL_TEXTURE_MATRIX\nGL_ATTRIB_STACK_DEPTH\nGL_CLIENT_ATTRIB_STACK_DEPTH\nGL_ALPHA_TEST\nGL_ALPHA_TEST_FUNC\nGL_ALPHA_TEST_REF\nGL_DITHER\nGL_BLEND_DST\nGL_BLEND_SRC\nGL_BLEND\nGL_LOGIC_OP_MODE\nGL_INDEX_LOGIC_OP\nGL_COLOR_LOGIC_OP\nGL_AUX_BUFFERS\nGL_DRAW_BUFFER\nGL_READ_BUFFER\nGL_SCISSOR_BOX\nGL_SCISSOR_TEST\nGL_INDEX_CLEAR_VALUE\nGL_INDEX_WRITEMASK\nGL_COLOR_CLEAR_VALUE\nGL_COLOR_WRITEMASK\nGL_INDEX_MODE\nGL_RGBA_MODE\nGL_DOUBLEBUFFER\nGL_STEREO\nGL_RENDER_MODE\nGL_PERSPECTIVE_CORRECTION_HINT\nGL_POINT_SMOOTH_HINT\nGL_LINE_SMOOTH_HINT\nGL_POLYGON_SMOOTH_HINT\nGL_FOG_HINT\nGL_TEXTURE_GEN_S\nGL_TEXTURE_GEN_T\nGL_TEXTURE_GEN_R\nGL_TEXTURE_GEN_Q\nGL_PIXEL_MAP_I_TO_I\nGL_PIXEL_MAP_S_TO_S\nGL_PIXEL_MAP_I_TO_R\nGL_PIXEL_MAP_I_TO_G\nGL_PIXEL_MAP_I_TO_B\nGL_PIXEL_MAP_I_TO_A\nGL_PIXEL_MAP_R_TO_R\nGL_PIXEL_MAP_G_TO_G\nGL_PIXEL_MAP_B_TO_B\nGL_PIXEL_MAP_A_TO_A\nGL_PIXEL_MAP_I_TO_I_SIZE\nGL_PIXEL_MAP_S_TO_S_SIZE\nGL_PIXEL_MAP_I_TO_R_SIZE\nGL_PIXEL_MAP_I_TO_G_SIZE\nGL_PIXEL_MAP_I_TO_B_SIZE\nGL_PIXEL_MAP_I_TO_A_SIZE\nGL_PIXEL_MAP_R_TO_R_SIZE\nGL_PIXEL_MAP_G_TO_G_SIZE\nGL_PIXEL_MAP_B_TO_B_SIZE\nGL_PIXEL_MAP_A_TO_A_SIZE\nGL_UNPACK_SWAP_BYTES\nGL_UNPACK_LSB_FIRST\nGL_UNPACK_ROW_LENGTH\nGL_UNPACK_SKIP_ROWS\nGL_UNPACK_SKIP_PIXELS\nGL_UNPACK_ALIGNMENT\nGL_PACK_SWAP_BYTES\nGL_PACK_LSB_FIRST\nGL_PACK_ROW_LENGTH\nGL_PACK_SKIP_ROWS\nGL_PACK_SKIP_PIXELS\nGL_PACK_ALIGNMENT\nGL_MAP_COLOR\nGL_MAP_STENCIL\nGL_INDEX_SHIFT\nGL_INDEX_OFFSET\nGL_RED_SCALE\nGL_RED_BIAS\nGL_ZOOM_X\nGL_ZOOM_Y\nGL_GREEN_SCALE\nGL_GREEN_BIAS\nGL_BLUE_SCALE\nGL_BLUE_BIAS\nGL_ALPHA_SCALE\nGL_ALPHA_BIAS\nGL_DEPTH_SCALE\nGL_DEPTH_BIAS\nGL_MAX_EVAL_ORDER\nGL_MAX_LIGHTS\nGL_MAX_CLIP_PLANES\nGL_MAX_TEXTURE_SIZE\nGL_MAX_PIXEL_MAP_TABLE\nGL_MAX_ATTRIB_STACK_DEPTH\nGL_MAX_MODELVIEW_STACK_DEPTH\nGL_MAX_NAME_STACK_DEPTH\nGL_MAX_PROJECTION_STACK_DEPTH\nGL_MAX_TEXTURE_STACK_DEPTH\nGL_MAX_VIEWPORT_DIMS\nGL_MAX_CLIENT_ATTRIB_STACK_DEPTH\nGL_SUBPIXEL_BITS\nGL_INDEX_BITS\nGL_RED_BITS\nGL_GREEN_BITS\nGL_BLUE_BITS\nGL_ALPHA_BITS\nGL_DEPTH_BITS\nGL_STENCIL_BITS\nGL_ACCUM_RED_BITS\nGL_ACCUM_GREEN_BITS\nGL_ACCUM_BLUE_BITS\nGL_ACCUM_ALPHA_BITS\nGL_NAME_STACK_DEPTH\nGL_AUTO_NORMAL\nGL_MAP1_COLOR_4\nGL_MAP1_INDEX\nGL_MAP1_NORMAL\nGL_MAP1_TEXTURE_COORD_1\nGL_MAP1_TEXTURE_COORD_2\nGL_MAP1_TEXTURE_COORD_3\nGL_MAP1_TEXTURE_COORD_4\nGL_MAP1_VERTEX_3\nGL_MAP1_VERTEX_4\nGL_MAP2_COLOR_4\nGL_MAP2_INDEX\nGL_MAP2_NORMAL\nGL_MAP2_TEXTURE_COORD_1\nGL_MAP2_TEXTURE_COORD_2\nGL_MAP2_TEXTURE_COORD_3\nGL_MAP2_TEXTURE_COORD_4\nGL_MAP2_VERTEX_3\nGL_MAP2_VERTEX_4\nGL_MAP1_GRID_DOMAIN\nGL_MAP1_GRID_SEGMENTS\nGL_MAP2_GRID_DOMAIN\nGL_MAP2_GRID_SEGMENTS\nGL_TEXTURE_1D\nGL_TEXTURE_2D\nGL_FEEDBACK_BUFFER_POINTER\nGL_FEEDBACK_BUFFER_SIZE\nGL_FEEDBACK_BUFFER_TYPE\nGL_SELECTION_BUFFER_POINTER\nGL_SELECTION_BUFFER_SIZE\nGL_TEXTURE_WIDTH\nGL_TEXTURE_HEIGHT\nGL_TEXTURE_INTERNAL_FORMAT\nGL_TEXTURE_BORDER_COLOR\nGL_TEXTURE_BORDER\nGL_DONT_CARE\nGL_FASTEST\nGL_NICEST\nGL_LIGHT0\nGL_LIGHT1\nGL_LIGHT2\nGL_LIGHT3\nGL_LIGHT4\nGL_LIGHT5\nGL_LIGHT6\nGL_LIGHT7\nGL_AMBIENT\nGL_DIFFUSE\nGL_SPECULAR\nGL_POSITION\nGL_SPOT_DIRECTION\nGL_SPOT_EXPONENT\nGL_SPOT_CUTOFF\nGL_CONSTANT_ATTENUATION\nGL_LINEAR_ATTENUATION\nGL_QUADRATIC_ATTENUATION\nGL_COMPILE\nGL_COMPILE_AND_EXECUTE\nGL_CLEAR\nGL_AND\nGL_AND_REVERSE\nGL_COPY\nGL_AND_INVERTED\nGL_NOOP\nGL_XOR\nGL_OR\nGL_NOR\nGL_EQUIV\nGL_INVERT\nGL_OR_REVERSE\nGL_COPY_INVERTED\nGL_OR_INVERTED\nGL_NAND\nGL_SET\nGL_EMISSION\nGL_SHININESS\nGL_AMBIENT_AND_DIFFUSE\nGL_COLOR_INDEXES\nGL_MODELVIEW\nGL_PROJECTION\nGL_TEXTURE\nGL_COLOR\nGL_DEPTH\nGL_STENCIL\nGL_COLOR_INDEX\nGL_STENCIL_INDEX\nGL_DEPTH_COMPONENT\nGL_RED\nGL_GREEN\nGL_BLUE\nGL_ALPHA\nGL_RGB\nGL_RGBA\nGL_LUMINANCE\nGL_LUMINANCE_ALPHA\nGL_BITMAP\nGL_POINT\nGL_LINE\nGL_FILL\nGL_RENDER\nGL_FEEDBACK\nGL_SELECT\nGL_FLAT\nGL_SMOOTH\nGL_KEEP\nGL_REPLACE\nGL_INCR\nGL_DECR\nGL_VENDOR\nGL_RENDERER\nGL_VERSION\nGL_EXTENSIONS\nGL_S\nGL_T\nGL_R\nGL_Q\nGL_MODULATE\nGL_DECAL\nGL_TEXTURE_ENV_MODE\nGL_TEXTURE_ENV_COLOR\nGL_TEXTURE_ENV\nGL_EYE_LINEAR\nGL_OBJECT_LINEAR\nGL_SPHERE_MAP\nGL_TEXTURE_GEN_MODE\nGL_OBJECT_PLANE\nGL_EYE_PLANE\nGL_NEAREST\nGL_LINEAR\nGL_NEAREST_MIPMAP_NEAREST\nGL_LINEAR_MIPMAP_NEAREST\nGL_NEAREST_MIPMAP_LINEAR\nGL_LINEAR_MIPMAP_LINEAR\nGL_TEXTURE_MAG_FILTER\nGL_TEXTURE_MIN_FILTER\nGL_TEXTURE_WRAP_S\nGL_TEXTURE_WRAP_T\nGL_CLAMP\nGL_REPEAT\nGL_CLIENT_PIXEL_STORE_BIT\nGL_CLIENT_VERTEX_ARRAY_BIT\nGL_CLIENT_ALL_ATTRIB_BITS\nGL_POLYGON_OFFSET_FACTOR\nGL_POLYGON_OFFSET_UNITS\nGL_POLYGON_OFFSET_POINT\nGL_POLYGON_OFFSET_LINE\nGL_POLYGON_OFFSET_FILL\nGL_ALPHA4\nGL_ALPHA8\nGL_ALPHA12\nGL_ALPHA16\nGL_LUMINANCE4\nGL_LUMINANCE8\nGL_LUMINANCE12\nGL_LUMINANCE16\nGL_LUMINANCE4_ALPHA4\nGL_LUMINANCE6_ALPHA2\nGL_LUMINANCE8_ALPHA8\nGL_LUMINANCE12_ALPHA4\nGL_LUMINANCE12_ALPHA12\nGL_LUMINANCE16_ALPHA16\nGL_INTENSITY\nGL_INTENSITY4\nGL_INTENSITY8\nGL_INTENSITY12\nGL_INTENSITY16\nGL_R3_G3_B2\nGL_RGB4\nGL_RGB5\nGL_RGB8\nGL_RGB10\nGL_RGB12\nGL_RGB16\nGL_RGBA2\nGL_RGBA4\nGL_RGB5_A1\nGL_RGBA8\nGL_RGB10_A2\nGL_RGBA12\nGL_RGBA16\nGL_TEXTURE_RED_SIZE\nGL_TEXTURE_GREEN_SIZE\nGL_TEXTURE_BLUE_SIZE\nGL_TEXTURE_ALPHA_SIZE\nGL_TEXTURE_LUMINANCE_SIZE\nGL_TEXTURE_INTENSITY_SIZE\nGL_PROXY_TEXTURE_1D\nGL_PROXY_TEXTURE_2D\nGL_TEXTURE_PRIORITY\nGL_TEXTURE_RESIDENT\nGL_TEXTURE_BINDING_1D\nGL_TEXTURE_BINDING_2D\nGL_VERTEX_ARRAY\nGL_NORMAL_ARRAY\nGL_COLOR_ARRAY\nGL_INDEX_ARRAY\nGL_TEXTURE_COORD_ARRAY\nGL_EDGE_FLAG_ARRAY\nGL_VERTEX_ARRAY_SIZE\nGL_VERTEX_ARRAY_TYPE\nGL_VERTEX_ARRAY_STRIDE\nGL_NORMAL_ARRAY_TYPE\nGL_NORMAL_ARRAY_STRIDE\nGL_COLOR_ARRAY_SIZE\nGL_COLOR_ARRAY_TYPE\nGL_COLOR_ARRAY_STRIDE\nGL_INDEX_ARRAY_TYPE\nGL_INDEX_ARRAY_STRIDE\nGL_TEXTURE_COORD_ARRAY_SIZE\nGL_TEXTURE_COORD_ARRAY_TYPE\nGL_TEXTURE_COORD_ARRAY_STRIDE\nGL_EDGE_FLAG_ARRAY_STRIDE\nGL_VERTEX_ARRAY_POINTER\nGL_NORMAL_ARRAY_POINTER\nGL_COLOR_ARRAY_POINTER\nGL_INDEX_ARRAY_POINTER\nGL_TEXTURE_COORD_ARRAY_POINTER\nGL_EDGE_FLAG_ARRAY_POINTER\nGL_V2F\nGL_V3F\nGL_C4UB_V2F\nGL_C4UB_V3F\nGL_C3F_V3F\nGL_N3F_V3F\nGL_C4F_N3F_V3F\nGL_T2F_V3F\nGL_T4F_V4F\nGL_T2F_C4UB_V3F\nGL_T2F_C3F_V3F\nGL_T2F_N3F_V3F\nGL_T2F_C4F_N3F_V3F\nGL_T4F_C4F_N3F_V4F\nGL_EXT_vertex_array\nGL_EXT_bgra\nGL_EXT_paletted_texture\nGL_WIN_swap_hint\nGL_WIN_draw_range_elements\nGL_VERTEX_ARRAY_EXT\nGL_NORMAL_ARRAY_EXT\nGL_COLOR_ARRAY_EXT\nGL_INDEX_ARRAY_EXT\nGL_TEXTURE_COORD_ARRAY_EXT\nGL_EDGE_FLAG_ARRAY_EXT\nGL_VERTEX_ARRAY_SIZE_EXT\nGL_VERTEX_ARRAY_TYPE_EXT\nGL_VERTEX_ARRAY_STRIDE_EXT\nGL_VERTEX_ARRAY_COUNT_EXT\nGL_NORMAL_ARRAY_TYPE_EXT\nGL_NORMAL_ARRAY_STRIDE_EXT\nGL_NORMAL_ARRAY_COUNT_EXT\nGL_COLOR_ARRAY_SIZE_EXT\nGL_COLOR_ARRAY_TYPE_EXT\nGL_COLOR_ARRAY_STRIDE_EXT\nGL_COLOR_ARRAY_COUNT_EXT\nGL_INDEX_ARRAY_TYPE_EXT\nGL_INDEX_ARRAY_STRIDE_EXT\nGL_INDEX_ARRAY_COUNT_EXT\nGL_TEXTURE_COORD_ARRAY_SIZE_EXT\nGL_TEXTURE_COORD_ARRAY_TYPE_EXT\nGL_TEXTURE_COORD_ARRAY_STRIDE_EXT\nGL_TEXTURE_COORD_ARRAY_COUNT_EXT\nGL_EDGE_FLAG_ARRAY_STRIDE_EXT\nGL_EDGE_FLAG_ARRAY_COUNT_EXT\nGL_VERTEX_ARRAY_POINTER_EXT\nGL_NORMAL_ARRAY_POINTER_EXT\nGL_COLOR_ARRAY_POINTER_EXT\nGL_INDEX_ARRAY_POINTER_EXT\nGL_TEXTURE_COORD_ARRAY_POINTER_EXT\nGL_EDGE_FLAG_ARRAY_POINTER_EXT\nGL_DOUBLE_EXT\nGL_BGR_EXT\nGL_BGRA_EXT\nGL_COLOR_TABLE_FORMAT_EXT\nGL_COLOR_TABLE_WIDTH_EXT\nGL_COLOR_TABLE_RED_SIZE_EXT\nGL_COLOR_TABLE_GREEN_SIZE_EXT\nGL_COLOR_TABLE_BLUE_SIZE_EXT\nGL_COLOR_TABLE_ALPHA_SIZE_EXT\nGL_COLOR_TABLE_LUMINANCE_SIZE_EXT\nGL_COLOR_TABLE_INTENSITY_SIZE_EXT\nGL_COLOR_INDEX1_EXT\nGL_COLOR_INDEX2_EXT\nGL_COLOR_INDEX4_EXT\nGL_COLOR_INDEX8_EXT\nGL_COLOR_INDEX12_EXT\nGL_COLOR_INDEX16_EXT\nGL_MAX_ELEMENTS_VERTICES_WIN\nGL_MAX_ELEMENTS_INDICES_WIN\nGL_PHONG_WIN\nGL_PHONG_HINT_WIN\nGL_FOG_SPECULAR_TEXTURE_WIN\nGL_LOGIC_OP\nGL_TEXTURE_COMPONENTS\nGLU_VERSION_1_1\nGLU_VERSION_1_2\nGLU_INVALID_ENUM\nGLU_INVALID_VALUE\nGLU_OUT_OF_MEMORY\nGLU_INCOMPATIBLE_GL_VERSION\nGLU_VERSION\nGLU_EXTENSIONS\nGLU_TRUE\nGLU_FALSE\nGLU_SMOOTH\nGLU_FLAT\nGLU_NONE\nGLU_POINT\nGLU_LINE\nGLU_FILL\nGLU_SILHOUETTE\nGLU_OUTSIDE\nGLU_INSIDE\nGLU_TESS_MAX_COORD\nGLU_TESS_WINDING_RULE\nGLU_TESS_BOUNDARY_ONLY\nGLU_TESS_TOLERANCE\nGLU_TESS_WINDING_ODD\nGLU_TESS_WINDING_NONZERO\nGLU_TESS_WINDING_POSITIVE\nGLU_TESS_WINDING_NEGATIVE\nGLU_TESS_WINDING_ABS_GEQ_TWO\nGLU_TESS_BEGIN\nGLU_TESS_VERTEX\nGLU_TESS_END\nGLU_TESS_ERROR\nGLU_TESS_EDGE_FLAG\nGLU_TESS_COMBINE\nGLU_TESS_BEGIN_DATA\nGLU_TESS_VERTEX_DATA\nGLU_TESS_END_DATA\nGLU_TESS_ERROR_DATA\nGLU_TESS_EDGE_FLAG_DATA\nGLU_TESS_COMBINE_DATA\nGLU_TESS_ERROR1\nGLU_TESS_ERROR2\nGLU_TESS_ERROR3\nGLU_TESS_ERROR4\nGLU_TESS_ERROR5\nGLU_TESS_ERROR6\nGLU_TESS_ERROR7\nGLU_TESS_ERROR8\nGLU_TESS_MISSING_BEGIN_POLYGON\nGLU_TESS_MISSING_BEGIN_CONTOUR\nGLU_TESS_MISSING_END_POLYGON\nGLU_TESS_MISSING_END_CONTOUR\nGLU_TESS_COORD_TOO_LARGE\nGLU_TESS_NEED_COMBINE_CALLBACK\nGLU_AUTO_LOAD_MATRIX\nGLU_CULLING\nGLU_SAMPLING_TOLERANCE\nGLU_DISPLAY_MODE\nGLU_PARAMETRIC_TOLERANCE\nGLU_SAMPLING_METHOD\nGLU_U_STEP\nGLU_V_STEP\nGLU_PATH_LENGTH\nGLU_PARAMETRIC_ERROR\nGLU_DOMAIN_DISTANCE\nGLU_MAP1_TRIM_2\nGLU_MAP1_TRIM_3\nGLU_OUTLINE_POLYGON\nGLU_OUTLINE_PATCH\nGLU_NURBS_ERROR1\nGLU_NURBS_ERROR2\nGLU_NURBS_ERROR3\nGLU_NURBS_ERROR4\nGLU_NURBS_ERROR5\nGLU_NURBS_ERROR6\nGLU_NURBS_ERROR7\nGLU_NURBS_ERROR8\nGLU_NURBS_ERROR9\nGLU_NURBS_ERROR10\nGLU_NURBS_ERROR11\nGLU_NURBS_ERROR12\nGLU_NURBS_ERROR13\nGLU_NURBS_ERROR14\nGLU_NURBS_ERROR15\nGLU_NURBS_ERROR16\nGLU_NURBS_ERROR17\nGLU_NURBS_ERROR18\nGLU_NURBS_ERROR19\nGLU_NURBS_ERROR20\nGLU_NURBS_ERROR21\nGLU_NURBS_ERROR22\nGLU_NURBS_ERROR23\nGLU_NURBS_ERROR24\nGLU_NURBS_ERROR25\nGLU_NURBS_ERROR26\nGLU_NURBS_ERROR27\nGLU_NURBS_ERROR28\nGLU_NURBS_ERROR29\nGLU_NURBS_ERROR30\nGLU_NURBS_ERROR31\nGLU_NURBS_ERROR32\nGLU_NURBS_ERROR33\nGLU_NURBS_ERROR34\nGLU_NURBS_ERROR35\nGLU_NURBS_ERROR36\nGLU_NURBS_ERROR37\nGLU_CW\nGLU_CCW\nGLU_INTERIOR\nGLU_EXTERIOR\nGLU_UNKNOWN\nGLU_BEGIN\nGLU_VERTEX\nGLU_END\nGLU_ERROR\nGLU_EDGE_FLAG\n"
  },
  {
    "path": "src/ConstList.works_for_me",
    "content": "GL_VERSION_1_1\nGL_VERSION_1_2\nGL_VERSION_1_3\nGL_ARB_imaging\nGL_FALSE\nGL_TRUE\nGL_2_BYTES\nGL_3_BYTES\nGL_4_BYTES\nGL_POINTS\nGL_LINES\nGL_LINE_LOOP\nGL_LINE_STRIP\nGL_TRIANGLES\nGL_TRIANGLE_STRIP\nGL_TRIANGLE_FAN\nGL_QUADS\nGL_QUAD_STRIP\nGL_POLYGON\nGL_VERTEX_ARRAY\nGL_NORMAL_ARRAY\nGL_COLOR_ARRAY\nGL_INDEX_ARRAY\nGL_TEXTURE_COORD_ARRAY\nGL_EDGE_FLAG_ARRAY\nGL_VERTEX_ARRAY_SIZE\nGL_VERTEX_ARRAY_TYPE\nGL_VERTEX_ARRAY_STRIDE\nGL_NORMAL_ARRAY_TYPE\nGL_NORMAL_ARRAY_STRIDE\nGL_COLOR_ARRAY_SIZE\nGL_COLOR_ARRAY_TYPE\nGL_COLOR_ARRAY_STRIDE\nGL_INDEX_ARRAY_TYPE\nGL_INDEX_ARRAY_STRIDE\nGL_TEXTURE_COORD_ARRAY_SIZE\nGL_TEXTURE_COORD_ARRAY_TYPE\nGL_TEXTURE_COORD_ARRAY_STRIDE\nGL_EDGE_FLAG_ARRAY_STRIDE\nGL_VERTEX_ARRAY_POINTER\nGL_NORMAL_ARRAY_POINTER\nGL_COLOR_ARRAY_POINTER\nGL_INDEX_ARRAY_POINTER\nGL_TEXTURE_COORD_ARRAY_POINTER\nGL_EDGE_FLAG_ARRAY_POINTER\nGL_V2F\nGL_V3F\nGL_C4UB_V2F\nGL_C4UB_V3F\nGL_C3F_V3F\nGL_N3F_V3F\nGL_C4F_N3F_V3F\nGL_T2F_V3F\nGL_T4F_V4F\nGL_T2F_C4UB_V3F\nGL_T2F_C3F_V3F\nGL_T2F_N3F_V3F\nGL_T2F_C4F_N3F_V3F\nGL_T4F_C4F_N3F_V4F\nGL_MATRIX_MODE\nGL_MODELVIEW\nGL_PROJECTION\nGL_TEXTURE\nGL_POINT_SMOOTH\nGL_POINT_SIZE\nGL_POINT_SIZE_GRANULARITY\nGL_POINT_SIZE_RANGE\nGL_LINE_SMOOTH\nGL_LINE_STIPPLE\nGL_LINE_STIPPLE_PATTERN\nGL_LINE_STIPPLE_REPEAT\nGL_LINE_WIDTH\nGL_LINE_WIDTH_GRANULARITY\nGL_LINE_WIDTH_RANGE\nGL_POINT\nGL_LINE\nGL_FILL\nGL_CW\nGL_CCW\nGL_FRONT\nGL_BACK\nGL_POLYGON_MODE\nGL_POLYGON_SMOOTH\nGL_POLYGON_STIPPLE\nGL_EDGE_FLAG\nGL_CULL_FACE\nGL_CULL_FACE_MODE\nGL_FRONT_FACE\nGL_POLYGON_OFFSET_FACTOR\nGL_POLYGON_OFFSET_UNITS\nGL_POLYGON_OFFSET_POINT\nGL_POLYGON_OFFSET_LINE\nGL_POLYGON_OFFSET_FILL\nGL_COMPILE\nGL_COMPILE_AND_EXECUTE\nGL_LIST_BASE\nGL_LIST_INDEX\nGL_LIST_MODE\nGL_NEVER\nGL_LESS\nGL_EQUAL\nGL_LEQUAL\nGL_GREATER\nGL_NOTEQUAL\nGL_GEQUAL\nGL_ALWAYS\nGL_DEPTH_TEST\nGL_DEPTH_BITS\nGL_DEPTH_CLEAR_VALUE\nGL_DEPTH_FUNC\nGL_DEPTH_RANGE\nGL_DEPTH_WRITEMASK\nGL_DEPTH_COMPONENT\nGL_LIGHTING\nGL_LIGHT0\nGL_LIGHT1\nGL_LIGHT2\nGL_LIGHT3\nGL_LIGHT4\nGL_LIGHT5\nGL_LIGHT6\nGL_LIGHT7\nGL_SPOT_EXPONENT\nGL_SPOT_CUTOFF\nGL_CONSTANT_ATTENUATION\nGL_LINEAR_ATTENUATION\nGL_QUADRATIC_ATTENUATION\nGL_AMBIENT\nGL_DIFFUSE\nGL_SPECULAR\nGL_SHININESS\nGL_EMISSION\nGL_POSITION\nGL_SPOT_DIRECTION\nGL_AMBIENT_AND_DIFFUSE\nGL_COLOR_INDEXES\nGL_LIGHT_MODEL_TWO_SIDE\nGL_LIGHT_MODEL_LOCAL_VIEWER\nGL_LIGHT_MODEL_AMBIENT\nGL_FRONT_AND_BACK\nGL_SHADE_MODEL\nGL_FLAT\nGL_SMOOTH\nGL_COLOR_MATERIAL\nGL_COLOR_MATERIAL_FACE\nGL_COLOR_MATERIAL_PARAMETER\nGL_NORMALIZE\nGL_CLIP_PLANE0\nGL_CLIP_PLANE1\nGL_CLIP_PLANE2\nGL_CLIP_PLANE3\nGL_CLIP_PLANE4\nGL_CLIP_PLANE5\nGL_ACCUM_RED_BITS\nGL_ACCUM_GREEN_BITS\nGL_ACCUM_BLUE_BITS\nGL_ACCUM_ALPHA_BITS\nGL_ACCUM_CLEAR_VALUE\nGL_ACCUM\nGL_ADD\nGL_LOAD\nGL_MULT\nGL_RETURN\nGL_ALPHA_TEST\nGL_ALPHA_TEST_REF\nGL_ALPHA_TEST_FUNC\nGL_BLEND\nGL_BLEND_SRC\nGL_BLEND_DST\nGL_ZERO\nGL_ONE\nGL_SRC_COLOR\nGL_ONE_MINUS_SRC_COLOR\nGL_SRC_ALPHA\nGL_ONE_MINUS_SRC_ALPHA\nGL_DST_ALPHA\nGL_ONE_MINUS_DST_ALPHA\nGL_DST_COLOR\nGL_ONE_MINUS_DST_COLOR\nGL_SRC_ALPHA_SATURATE\nGL_FEEDBACK\nGL_RENDER\nGL_SELECT\nGL_2D\nGL_3D\nGL_3D_COLOR\nGL_3D_COLOR_TEXTURE\nGL_4D_COLOR_TEXTURE\nGL_POINT_TOKEN\nGL_LINE_TOKEN\nGL_LINE_RESET_TOKEN\nGL_POLYGON_TOKEN\nGL_BITMAP_TOKEN\nGL_DRAW_PIXEL_TOKEN\nGL_COPY_PIXEL_TOKEN\nGL_PASS_THROUGH_TOKEN\nGL_FEEDBACK_BUFFER_POINTER\nGL_FEEDBACK_BUFFER_SIZE\nGL_FEEDBACK_BUFFER_TYPE\nGL_SELECTION_BUFFER_POINTER\nGL_SELECTION_BUFFER_SIZE\nGL_FOG\nGL_FOG_MODE\nGL_FOG_DENSITY\nGL_FOG_COLOR\nGL_FOG_INDEX\nGL_FOG_START\nGL_FOG_END\nGL_LINEAR\nGL_EXP\nGL_EXP2\nGL_LOGIC_OP\nGL_INDEX_LOGIC_OP\nGL_COLOR_LOGIC_OP\nGL_LOGIC_OP_MODE\nGL_CLEAR\nGL_SET\nGL_COPY\nGL_COPY_INVERTED\nGL_NOOP\nGL_INVERT\nGL_AND\nGL_NAND\nGL_OR\nGL_NOR\nGL_XOR\nGL_EQUIV\nGL_AND_REVERSE\nGL_AND_INVERTED\nGL_OR_REVERSE\nGL_OR_INVERTED\nGL_STENCIL_TEST\nGL_STENCIL_WRITEMASK\nGL_STENCIL_BITS\nGL_STENCIL_FUNC\nGL_STENCIL_VALUE_MASK\nGL_STENCIL_REF\nGL_STENCIL_FAIL\nGL_STENCIL_PASS_DEPTH_PASS\nGL_STENCIL_PASS_DEPTH_FAIL\nGL_STENCIL_CLEAR_VALUE\nGL_STENCIL_INDEX\nGL_KEEP\nGL_REPLACE\nGL_INCR\nGL_DECR\nGL_NONE\nGL_LEFT\nGL_RIGHT\nGL_FRONT_LEFT\nGL_FRONT_RIGHT\nGL_BACK_LEFT\nGL_BACK_RIGHT\nGL_AUX0\nGL_AUX1\nGL_AUX2\nGL_AUX3\nGL_COLOR_INDEX\nGL_RED\nGL_GREEN\nGL_BLUE\nGL_ALPHA\nGL_LUMINANCE\nGL_LUMINANCE_ALPHA\nGL_ALPHA_BITS\nGL_RED_BITS\nGL_GREEN_BITS\nGL_BLUE_BITS\nGL_INDEX_BITS\nGL_SUBPIXEL_BITS\nGL_AUX_BUFFERS\nGL_READ_BUFFER\nGL_DRAW_BUFFER\nGL_DOUBLEBUFFER\nGL_STEREO\nGL_BITMAP\nGL_COLOR\nGL_DEPTH\nGL_STENCIL\nGL_DITHER\nGL_RGB\nGL_RGBA\nGL_MAX_LIST_NESTING\nGL_MAX_ATTRIB_STACK_DEPTH\nGL_MAX_MODELVIEW_STACK_DEPTH\nGL_MAX_NAME_STACK_DEPTH\nGL_MAX_PROJECTION_STACK_DEPTH\nGL_MAX_TEXTURE_STACK_DEPTH\nGL_MAX_EVAL_ORDER\nGL_MAX_LIGHTS\nGL_MAX_CLIP_PLANES\nGL_MAX_TEXTURE_SIZE\nGL_MAX_PIXEL_MAP_TABLE\nGL_MAX_VIEWPORT_DIMS\nGL_MAX_CLIENT_ATTRIB_STACK_DEPTH\nGL_ATTRIB_STACK_DEPTH\nGL_CLIENT_ATTRIB_STACK_DEPTH\nGL_COLOR_CLEAR_VALUE\nGL_COLOR_WRITEMASK\nGL_CURRENT_INDEX\nGL_CURRENT_COLOR\nGL_CURRENT_NORMAL\nGL_CURRENT_RASTER_COLOR\nGL_CURRENT_RASTER_DISTANCE\nGL_CURRENT_RASTER_INDEX\nGL_CURRENT_RASTER_POSITION\nGL_CURRENT_RASTER_TEXTURE_COORDS\nGL_CURRENT_RASTER_POSITION_VALID\nGL_CURRENT_TEXTURE_COORDS\nGL_INDEX_CLEAR_VALUE\nGL_INDEX_MODE\nGL_INDEX_WRITEMASK\nGL_MODELVIEW_MATRIX\nGL_MODELVIEW_STACK_DEPTH\nGL_NAME_STACK_DEPTH\nGL_PROJECTION_MATRIX\nGL_PROJECTION_STACK_DEPTH\nGL_RENDER_MODE\nGL_RGBA_MODE\nGL_TEXTURE_MATRIX\nGL_TEXTURE_STACK_DEPTH\nGL_VIEWPORT\nGL_AUTO_NORMAL\nGL_MAP1_COLOR_4\nGL_MAP1_INDEX\nGL_MAP1_NORMAL\nGL_MAP1_TEXTURE_COORD_1\nGL_MAP1_TEXTURE_COORD_2\nGL_MAP1_TEXTURE_COORD_3\nGL_MAP1_TEXTURE_COORD_4\nGL_MAP1_VERTEX_3\nGL_MAP1_VERTEX_4\nGL_MAP2_COLOR_4\nGL_MAP2_INDEX\nGL_MAP2_NORMAL\nGL_MAP2_TEXTURE_COORD_1\nGL_MAP2_TEXTURE_COORD_2\nGL_MAP2_TEXTURE_COORD_3\nGL_MAP2_TEXTURE_COORD_4\nGL_MAP2_VERTEX_3\nGL_MAP2_VERTEX_4\nGL_MAP1_GRID_DOMAIN\nGL_MAP1_GRID_SEGMENTS\nGL_MAP2_GRID_DOMAIN\nGL_MAP2_GRID_SEGMENTS\nGL_COEFF\nGL_DOMAIN\nGL_ORDER\nGL_FOG_HINT\nGL_LINE_SMOOTH_HINT\nGL_PERSPECTIVE_CORRECTION_HINT\nGL_POINT_SMOOTH_HINT\nGL_POLYGON_SMOOTH_HINT\nGL_DONT_CARE\nGL_FASTEST\nGL_NICEST\nGL_SCISSOR_TEST\nGL_SCISSOR_BOX\nGL_MAP_COLOR\nGL_MAP_STENCIL\nGL_INDEX_SHIFT\nGL_INDEX_OFFSET\nGL_RED_SCALE\nGL_RED_BIAS\nGL_GREEN_SCALE\nGL_GREEN_BIAS\nGL_BLUE_SCALE\nGL_BLUE_BIAS\nGL_ALPHA_SCALE\nGL_ALPHA_BIAS\nGL_DEPTH_SCALE\nGL_DEPTH_BIAS\nGL_PIXEL_MAP_S_TO_S_SIZE\nGL_PIXEL_MAP_I_TO_I_SIZE\nGL_PIXEL_MAP_I_TO_R_SIZE\nGL_PIXEL_MAP_I_TO_G_SIZE\nGL_PIXEL_MAP_I_TO_B_SIZE\nGL_PIXEL_MAP_I_TO_A_SIZE\nGL_PIXEL_MAP_R_TO_R_SIZE\nGL_PIXEL_MAP_G_TO_G_SIZE\nGL_PIXEL_MAP_B_TO_B_SIZE\nGL_PIXEL_MAP_A_TO_A_SIZE\nGL_PIXEL_MAP_S_TO_S\nGL_PIXEL_MAP_I_TO_I\nGL_PIXEL_MAP_I_TO_R\nGL_PIXEL_MAP_I_TO_G\nGL_PIXEL_MAP_I_TO_B\nGL_PIXEL_MAP_I_TO_A\nGL_PIXEL_MAP_R_TO_R\nGL_PIXEL_MAP_G_TO_G\nGL_PIXEL_MAP_B_TO_B\nGL_PIXEL_MAP_A_TO_A\nGL_PACK_ALIGNMENT\nGL_PACK_LSB_FIRST\nGL_PACK_ROW_LENGTH\nGL_PACK_SKIP_PIXELS\nGL_PACK_SKIP_ROWS\nGL_PACK_SWAP_BYTES\nGL_UNPACK_ALIGNMENT\nGL_UNPACK_LSB_FIRST\nGL_UNPACK_ROW_LENGTH\nGL_UNPACK_SKIP_PIXELS\nGL_UNPACK_SKIP_ROWS\nGL_UNPACK_SWAP_BYTES\nGL_ZOOM_X\nGL_ZOOM_Y\nGL_TEXTURE_ENV\nGL_TEXTURE_ENV_MODE\nGL_TEXTURE_1D\nGL_TEXTURE_2D\nGL_TEXTURE_WRAP_S\nGL_TEXTURE_WRAP_T\nGL_TEXTURE_MAG_FILTER\nGL_TEXTURE_MIN_FILTER\nGL_TEXTURE_ENV_COLOR\nGL_TEXTURE_GEN_S\nGL_TEXTURE_GEN_T\nGL_TEXTURE_GEN_MODE\nGL_TEXTURE_BORDER_COLOR\nGL_TEXTURE_WIDTH\nGL_TEXTURE_HEIGHT\nGL_TEXTURE_BORDER\nGL_TEXTURE_COMPONENTS\nGL_TEXTURE_RED_SIZE\nGL_TEXTURE_GREEN_SIZE\nGL_TEXTURE_BLUE_SIZE\nGL_TEXTURE_ALPHA_SIZE\nGL_TEXTURE_LUMINANCE_SIZE\nGL_TEXTURE_INTENSITY_SIZE\nGL_NEAREST_MIPMAP_NEAREST\nGL_NEAREST_MIPMAP_LINEAR\nGL_LINEAR_MIPMAP_NEAREST\nGL_LINEAR_MIPMAP_LINEAR\nGL_OBJECT_LINEAR\nGL_OBJECT_PLANE\nGL_EYE_LINEAR\nGL_EYE_PLANE\nGL_SPHERE_MAP\nGL_DECAL\nGL_MODULATE\nGL_NEAREST\nGL_REPEAT\nGL_CLAMP\nGL_S\nGL_T\nGL_R\nGL_Q\nGL_TEXTURE_GEN_R\nGL_TEXTURE_GEN_Q\nGL_VENDOR\nGL_RENDERER\nGL_VERSION\nGL_EXTENSIONS\nGL_NO_ERROR\nGL_INVALID_VALUE\nGL_INVALID_ENUM\nGL_INVALID_OPERATION\nGL_STACK_OVERFLOW\nGL_STACK_UNDERFLOW\nGL_OUT_OF_MEMORY\nGL_CURRENT_BIT\nGL_POINT_BIT\nGL_LINE_BIT\nGL_POLYGON_BIT\nGL_POLYGON_STIPPLE_BIT\nGL_PIXEL_MODE_BIT\nGL_LIGHTING_BIT\nGL_FOG_BIT\nGL_DEPTH_BUFFER_BIT\nGL_ACCUM_BUFFER_BIT\nGL_STENCIL_BUFFER_BIT\nGL_VIEWPORT_BIT\nGL_TRANSFORM_BIT\nGL_ENABLE_BIT\nGL_COLOR_BUFFER_BIT\nGL_HINT_BIT\nGL_EVAL_BIT\nGL_LIST_BIT\nGL_TEXTURE_BIT\nGL_SCISSOR_BIT\nGL_ALL_ATTRIB_BITS\nGL_PROXY_TEXTURE_1D\nGL_PROXY_TEXTURE_2D\nGL_TEXTURE_PRIORITY\nGL_TEXTURE_RESIDENT\nGL_TEXTURE_BINDING_1D\nGL_TEXTURE_BINDING_2D\nGL_TEXTURE_INTERNAL_FORMAT\nGL_ALPHA4\nGL_ALPHA8\nGL_ALPHA12\nGL_ALPHA16\nGL_LUMINANCE4\nGL_LUMINANCE8\nGL_LUMINANCE12\nGL_LUMINANCE16\nGL_LUMINANCE4_ALPHA4\nGL_LUMINANCE6_ALPHA2\nGL_LUMINANCE8_ALPHA8\nGL_LUMINANCE12_ALPHA4\nGL_LUMINANCE12_ALPHA12\nGL_LUMINANCE16_ALPHA16\nGL_INTENSITY\nGL_INTENSITY4\nGL_INTENSITY8\nGL_INTENSITY12\nGL_INTENSITY16\nGL_R3_G3_B2\nGL_RGB4\nGL_RGB5\nGL_RGB8\nGL_RGB10\nGL_RGB12\nGL_RGB16\nGL_RGBA2\nGL_RGBA4\nGL_RGB5_A1\nGL_RGBA8\nGL_RGB10_A2\nGL_RGBA12\nGL_RGBA16\nGL_CLIENT_PIXEL_STORE_BIT\nGL_CLIENT_VERTEX_ARRAY_BIT\nGL_ALL_CLIENT_ATTRIB_BITS\nGL_CLIENT_ALL_ATTRIB_BITS\nGL_RESCALE_NORMAL\nGL_CLAMP_TO_EDGE\nGL_MAX_ELEMENTS_VERTICES\nGL_MAX_ELEMENTS_INDICES\nGL_BGR\nGL_BGRA\nGL_UNSIGNED_BYTE_3_3_2\nGL_UNSIGNED_BYTE_2_3_3_REV\nGL_UNSIGNED_SHORT_5_6_5\nGL_UNSIGNED_SHORT_5_6_5_REV\nGL_UNSIGNED_SHORT_4_4_4_4\nGL_UNSIGNED_SHORT_4_4_4_4_REV\nGL_UNSIGNED_SHORT_5_5_5_1\nGL_UNSIGNED_SHORT_1_5_5_5_REV\nGL_UNSIGNED_INT_8_8_8_8\nGL_UNSIGNED_INT_8_8_8_8_REV\nGL_UNSIGNED_INT_10_10_10_2\nGL_UNSIGNED_INT_2_10_10_10_REV\nGL_LIGHT_MODEL_COLOR_CONTROL\nGL_SINGLE_COLOR\nGL_SEPARATE_SPECULAR_COLOR\nGL_TEXTURE_MIN_LOD\nGL_TEXTURE_MAX_LOD\nGL_TEXTURE_BASE_LEVEL\nGL_TEXTURE_MAX_LEVEL\nGL_SMOOTH_POINT_SIZE_RANGE\nGL_SMOOTH_POINT_SIZE_GRANULARITY\nGL_SMOOTH_LINE_WIDTH_RANGE\nGL_SMOOTH_LINE_WIDTH_GRANULARITY\nGL_ALIASED_POINT_SIZE_RANGE\nGL_ALIASED_LINE_WIDTH_RANGE\nGL_PACK_SKIP_IMAGES\nGL_PACK_IMAGE_HEIGHT\nGL_UNPACK_SKIP_IMAGES\nGL_UNPACK_IMAGE_HEIGHT\nGL_TEXTURE_3D\nGL_PROXY_TEXTURE_3D\nGL_TEXTURE_DEPTH\nGL_TEXTURE_WRAP_R\nGL_MAX_3D_TEXTURE_SIZE\nGL_TEXTURE_BINDING_3D\nGL_CONSTANT_COLOR\nGL_ONE_MINUS_CONSTANT_COLOR\nGL_CONSTANT_ALPHA\nGL_ONE_MINUS_CONSTANT_ALPHA\nGL_COLOR_TABLE\nGL_POST_CONVOLUTION_COLOR_TABLE\nGL_POST_COLOR_MATRIX_COLOR_TABLE\nGL_PROXY_COLOR_TABLE\nGL_PROXY_POST_CONVOLUTION_COLOR_TABLE\nGL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE\nGL_COLOR_TABLE_SCALE\nGL_COLOR_TABLE_BIAS\nGL_COLOR_TABLE_FORMAT\nGL_COLOR_TABLE_WIDTH\nGL_COLOR_TABLE_RED_SIZE\nGL_COLOR_TABLE_GREEN_SIZE\nGL_COLOR_TABLE_BLUE_SIZE\nGL_COLOR_TABLE_ALPHA_SIZE\nGL_COLOR_TABLE_LUMINANCE_SIZE\nGL_COLOR_TABLE_INTENSITY_SIZE\nGL_CONVOLUTION_1D\nGL_CONVOLUTION_2D\nGL_SEPARABLE_2D\nGL_CONVOLUTION_BORDER_MODE\nGL_CONVOLUTION_FILTER_SCALE\nGL_CONVOLUTION_FILTER_BIAS\nGL_REDUCE\nGL_CONVOLUTION_FORMAT\nGL_CONVOLUTION_WIDTH\nGL_CONVOLUTION_HEIGHT\nGL_MAX_CONVOLUTION_WIDTH\nGL_MAX_CONVOLUTION_HEIGHT\nGL_POST_CONVOLUTION_RED_SCALE\nGL_POST_CONVOLUTION_GREEN_SCALE\nGL_POST_CONVOLUTION_BLUE_SCALE\nGL_POST_CONVOLUTION_ALPHA_SCALE\nGL_POST_CONVOLUTION_RED_BIAS\nGL_POST_CONVOLUTION_GREEN_BIAS\nGL_POST_CONVOLUTION_BLUE_BIAS\nGL_POST_CONVOLUTION_ALPHA_BIAS\nGL_CONSTANT_BORDER\nGL_REPLICATE_BORDER\nGL_CONVOLUTION_BORDER_COLOR\nGL_COLOR_MATRIX\nGL_COLOR_MATRIX_STACK_DEPTH\nGL_MAX_COLOR_MATRIX_STACK_DEPTH\nGL_POST_COLOR_MATRIX_RED_SCALE\nGL_POST_COLOR_MATRIX_GREEN_SCALE\nGL_POST_COLOR_MATRIX_BLUE_SCALE\nGL_POST_COLOR_MATRIX_ALPHA_SCALE\nGL_POST_COLOR_MATRIX_RED_BIAS\nGL_POST_COLOR_MATRIX_GREEN_BIAS\nGL_POST_COLOR_MATRIX_BLUE_BIAS\nGL_POST_COLOR_MATRIX_ALPHA_BIAS\nGL_HISTOGRAM\nGL_PROXY_HISTOGRAM\nGL_HISTOGRAM_WIDTH\nGL_HISTOGRAM_FORMAT\nGL_HISTOGRAM_RED_SIZE\nGL_HISTOGRAM_GREEN_SIZE\nGL_HISTOGRAM_BLUE_SIZE\nGL_HISTOGRAM_ALPHA_SIZE\nGL_HISTOGRAM_LUMINANCE_SIZE\nGL_HISTOGRAM_SINK\nGL_MINMAX\nGL_MINMAX_FORMAT\nGL_MINMAX_SINK\nGL_TABLE_TOO_LARGE\nGL_BLEND_EQUATION\nGL_MIN\nGL_MAX\nGL_FUNC_ADD\nGL_FUNC_SUBTRACT\nGL_FUNC_REVERSE_SUBTRACT\nGL_BLEND_COLOR\nGL_TEXTURE0\nGL_TEXTURE1\nGL_TEXTURE2\nGL_TEXTURE3\nGL_TEXTURE4\nGL_TEXTURE5\nGL_TEXTURE6\nGL_TEXTURE7\nGL_TEXTURE8\nGL_TEXTURE9\nGL_TEXTURE10\nGL_TEXTURE11\nGL_TEXTURE12\nGL_TEXTURE13\nGL_TEXTURE14\nGL_TEXTURE15\nGL_TEXTURE16\nGL_TEXTURE17\nGL_TEXTURE18\nGL_TEXTURE19\nGL_TEXTURE20\nGL_TEXTURE21\nGL_TEXTURE22\nGL_TEXTURE23\nGL_TEXTURE24\nGL_TEXTURE25\nGL_TEXTURE26\nGL_TEXTURE27\nGL_TEXTURE28\nGL_TEXTURE29\nGL_TEXTURE30\nGL_TEXTURE31\nGL_ACTIVE_TEXTURE\nGL_CLIENT_ACTIVE_TEXTURE\nGL_MAX_TEXTURE_UNITS\nGL_NORMAL_MAP\nGL_REFLECTION_MAP\nGL_TEXTURE_CUBE_MAP\nGL_TEXTURE_BINDING_CUBE_MAP\nGL_TEXTURE_CUBE_MAP_POSITIVE_X\nGL_TEXTURE_CUBE_MAP_NEGATIVE_X\nGL_TEXTURE_CUBE_MAP_POSITIVE_Y\nGL_TEXTURE_CUBE_MAP_NEGATIVE_Y\nGL_TEXTURE_CUBE_MAP_POSITIVE_Z\nGL_TEXTURE_CUBE_MAP_NEGATIVE_Z\nGL_PROXY_TEXTURE_CUBE_MAP\nGL_MAX_CUBE_MAP_TEXTURE_SIZE\nGL_COMPRESSED_ALPHA\nGL_COMPRESSED_LUMINANCE\nGL_COMPRESSED_LUMINANCE_ALPHA\nGL_COMPRESSED_INTENSITY\nGL_COMPRESSED_RGB\nGL_COMPRESSED_RGBA\nGL_TEXTURE_COMPRESSION_HINT\nGL_TEXTURE_COMPRESSED_IMAGE_SIZE\nGL_TEXTURE_COMPRESSED\nGL_NUM_COMPRESSED_TEXTURE_FORMATS\nGL_COMPRESSED_TEXTURE_FORMATS\nGL_MULTISAMPLE\nGL_SAMPLE_ALPHA_TO_COVERAGE\nGL_SAMPLE_ALPHA_TO_ONE\nGL_SAMPLE_COVERAGE\nGL_SAMPLE_BUFFERS\nGL_SAMPLES\nGL_SAMPLE_COVERAGE_VALUE\nGL_SAMPLE_COVERAGE_INVERT\nGL_MULTISAMPLE_BIT\nGL_TRANSPOSE_MODELVIEW_MATRIX\nGL_TRANSPOSE_PROJECTION_MATRIX\nGL_TRANSPOSE_TEXTURE_MATRIX\nGL_TRANSPOSE_COLOR_MATRIX\nGL_COMBINE\nGL_COMBINE_RGB\nGL_COMBINE_ALPHA\nGL_SOURCE0_RGB\nGL_SOURCE1_RGB\nGL_SOURCE2_RGB\nGL_SOURCE0_ALPHA\nGL_SOURCE1_ALPHA\nGL_SOURCE2_ALPHA\nGL_OPERAND0_RGB\nGL_OPERAND1_RGB\nGL_OPERAND2_RGB\nGL_OPERAND0_ALPHA\nGL_OPERAND1_ALPHA\nGL_OPERAND2_ALPHA\nGL_RGB_SCALE\nGL_ADD_SIGNED\nGL_INTERPOLATE\nGL_SUBTRACT\nGL_CONSTANT\nGL_PRIMARY_COLOR\nGL_PREVIOUS\nGL_DOT3_RGB\nGL_DOT3_RGBA\nGL_CLAMP_TO_BORDER\nGL_ARB_multitexture\nGL_TEXTURE0_ARB\nGL_TEXTURE1_ARB\nGL_TEXTURE2_ARB\nGL_TEXTURE3_ARB\nGL_TEXTURE4_ARB\nGL_TEXTURE5_ARB\nGL_TEXTURE6_ARB\nGL_TEXTURE7_ARB\nGL_TEXTURE8_ARB\nGL_TEXTURE9_ARB\nGL_TEXTURE10_ARB\nGL_TEXTURE11_ARB\nGL_TEXTURE12_ARB\nGL_TEXTURE13_ARB\nGL_TEXTURE14_ARB\nGL_TEXTURE15_ARB\nGL_TEXTURE16_ARB\nGL_TEXTURE17_ARB\nGL_TEXTURE18_ARB\nGL_TEXTURE19_ARB\nGL_TEXTURE20_ARB\nGL_TEXTURE21_ARB\nGL_TEXTURE22_ARB\nGL_TEXTURE23_ARB\nGL_TEXTURE24_ARB\nGL_TEXTURE25_ARB\nGL_TEXTURE26_ARB\nGL_TEXTURE27_ARB\nGL_TEXTURE28_ARB\nGL_TEXTURE29_ARB\nGL_TEXTURE30_ARB\nGL_TEXTURE31_ARB\nGL_ACTIVE_TEXTURE_ARB\nGL_CLIENT_ACTIVE_TEXTURE_ARB\nGL_MAX_TEXTURE_UNITS_ARB\nGL_EXT_abgr\nGL_ABGR_EXT\nGL_EXT_blend_color\nGL_CONSTANT_COLOR_EXT\nGL_ONE_MINUS_CONSTANT_COLOR_EXT\nGL_CONSTANT_ALPHA_EXT\nGL_ONE_MINUS_CONSTANT_ALPHA_EXT\nGL_BLEND_COLOR_EXT\nGL_EXT_polygon_offset\nGL_POLYGON_OFFSET_EXT\nGL_POLYGON_OFFSET_FACTOR_EXT\nGL_POLYGON_OFFSET_BIAS_EXT\nGL_EXT_texture3D\nGL_PACK_SKIP_IMAGES_EXT\nGL_PACK_IMAGE_HEIGHT_EXT\nGL_UNPACK_SKIP_IMAGES_EXT\nGL_UNPACK_IMAGE_HEIGHT_EXT\nGL_TEXTURE_3D_EXT\nGL_PROXY_TEXTURE_3D_EXT\nGL_TEXTURE_DEPTH_EXT\nGL_TEXTURE_WRAP_R_EXT\nGL_MAX_3D_TEXTURE_SIZE_EXT\nGL_TEXTURE_3D_BINDING_EXT\nGL_EXT_texture_object\nGL_TEXTURE_PRIORITY_EXT\nGL_TEXTURE_RESIDENT_EXT\nGL_TEXTURE_1D_BINDING_EXT\nGL_TEXTURE_2D_BINDING_EXT\nGL_EXT_rescale_normal\nGL_RESCALE_NORMAL_EXT\nGL_EXT_vertex_array\nGL_VERTEX_ARRAY_EXT\nGL_NORMAL_ARRAY_EXT\nGL_COLOR_ARRAY_EXT\nGL_INDEX_ARRAY_EXT\nGL_TEXTURE_COORD_ARRAY_EXT\nGL_EDGE_FLAG_ARRAY_EXT\nGL_VERTEX_ARRAY_SIZE_EXT\nGL_VERTEX_ARRAY_TYPE_EXT\nGL_VERTEX_ARRAY_STRIDE_EXT\nGL_VERTEX_ARRAY_COUNT_EXT\nGL_NORMAL_ARRAY_TYPE_EXT\nGL_NORMAL_ARRAY_STRIDE_EXT\nGL_NORMAL_ARRAY_COUNT_EXT\nGL_COLOR_ARRAY_SIZE_EXT\nGL_COLOR_ARRAY_TYPE_EXT\nGL_COLOR_ARRAY_STRIDE_EXT\nGL_COLOR_ARRAY_COUNT_EXT\nGL_INDEX_ARRAY_TYPE_EXT\nGL_INDEX_ARRAY_STRIDE_EXT\nGL_INDEX_ARRAY_COUNT_EXT\nGL_TEXTURE_COORD_ARRAY_SIZE_EXT\nGL_TEXTURE_COORD_ARRAY_TYPE_EXT\nGL_TEXTURE_COORD_ARRAY_STRIDE_EXT\nGL_TEXTURE_COORD_ARRAY_COUNT_EXT\nGL_EDGE_FLAG_ARRAY_STRIDE_EXT\nGL_EDGE_FLAG_ARRAY_COUNT_EXT\nGL_VERTEX_ARRAY_POINTER_EXT\nGL_NORMAL_ARRAY_POINTER_EXT\nGL_COLOR_ARRAY_POINTER_EXT\nGL_INDEX_ARRAY_POINTER_EXT\nGL_TEXTURE_COORD_ARRAY_POINTER_EXT\nGL_EDGE_FLAG_ARRAY_POINTER_EXT\nGL_SGIS_texture_edge_clamp\nGL_CLAMP_TO_EDGE_SGIS\nGL_EXT_blend_minmax\nGL_FUNC_ADD_EXT\nGL_MIN_EXT\nGL_MAX_EXT\nGL_BLEND_EQUATION_EXT\nGL_EXT_blend_subtract\nGL_FUNC_SUBTRACT_EXT\nGL_FUNC_REVERSE_SUBTRACT_EXT\nGL_EXT_blend_logic_op\nGL_EXT_point_parameters\nGL_POINT_SIZE_MIN_EXT\nGL_POINT_SIZE_MAX_EXT\nGL_POINT_FADE_THRESHOLD_SIZE_EXT\nGL_DISTANCE_ATTENUATION_EXT\nGL_EXT_paletted_texture\nGL_TABLE_TOO_LARGE_EXT\nGL_TEXTURE_INDEX_SIZE_EXT\nGL_COLOR_INDEX1_EXT\nGL_COLOR_INDEX2_EXT\nGL_COLOR_INDEX4_EXT\nGL_COLOR_INDEX8_EXT\nGL_COLOR_INDEX12_EXT\nGL_COLOR_INDEX16_EXT\nGL_EXT_clip_volume_hint\nGL_CLIP_VOLUME_CLIPPING_HINT_EXT\nGL_EXT_compiled_vertex_array\nGL_ARRAY_ELEMENT_LOCK_FIRST_EXT\nGL_ARRAY_ELEMENT_LOCK_COUNT_EXT\nGL_HP_occlusion_test\nGL_OCCLUSION_TEST_HP\nGL_OCCLUSION_TEST_RESULT_HP\nGL_EXT_shared_texture_palette\nGL_SHARED_TEXTURE_PALETTE_EXT\nGL_EXT_stencil_wrap\nGL_INCR_WRAP_EXT\nGL_DECR_WRAP_EXT\nGL_NV_texgen_reflection\nGL_NORMAL_MAP_NV\nGL_REFLECTION_MAP_NV\nGL_EXT_texture_env_add\nGL_MESA_window_pos\nGL_MESA_resize_buffers\nGL_EXT_texture_env_dot3\nGL_DOT3_RGB_EXT\nGL_DOT3_RGBA_EXT\nGL_MESA_trace\nGL_TRACE_ALL_BITS_MESA\nGL_TRACE_OPERATIONS_BIT_MESA\nGL_TRACE_PRIMITIVES_BIT_MESA\nGL_TRACE_ARRAYS_BIT_MESA\nGL_TRACE_TEXTURES_BIT_MESA\nGL_TRACE_PIXELS_BIT_MESA\nGL_TRACE_ERRORS_BIT_MESA\nGL_TRACE_MASK_MESA\nGL_TRACE_NAME_MESA\nGL_MESA_packed_depth_stencil\nGL_DEPTH_STENCIL_MESA\nGL_UNSIGNED_INT_24_8_MESA\nGL_UNSIGNED_INT_8_24_REV_MESA\nGL_UNSIGNED_SHORT_15_1_MESA\nGL_UNSIGNED_SHORT_1_15_REV_MESA\nGL_MESA_ycbcr_texture\nGL_YCBCR_MESA\nGL_UNSIGNED_SHORT_8_8_MESA\nGL_UNSIGNED_SHORT_8_8_REV_MESA\nGL_MESA_pack_invert\nGL_PACK_INVERT_MESA\nGL_APPLE_client_storage\nGL_UNPACK_CLIENT_STORAGE_APPLE\nGL_APPLE_ycbcr_422\nGL_YCBCR_422_APPLE\nGL_UNSIGNED_SHORT_8_8_APPLE\nGL_UNSIGNED_SHORT_8_8_REV_APPLE\nGL_ATI_texture_env_combine3\nGL_MODULATE_ADD_ATI\nGL_MODULATE_SIGNED_ADD_ATI\nGL_MODULATE_SUBTRACT_ATI\nGLU_EXT_object_space_tess\nGLU_EXT_nurbs_tessellator\nGLU_FALSE\nGLU_TRUE\nGLU_VERSION_1_1\nGLU_VERSION_1_2\nGLU_VERSION_1_3\nGLU_VERSION\nGLU_EXTENSIONS\nGLU_INVALID_ENUM\nGLU_INVALID_VALUE\nGLU_OUT_OF_MEMORY\nGLU_INVALID_OPERATION\nGLU_OUTLINE_POLYGON\nGLU_OUTLINE_PATCH\nGLU_NURBS_ERROR\nGLU_ERROR\nGLU_NURBS_BEGIN\nGLU_NURBS_BEGIN_EXT\nGLU_NURBS_VERTEX\nGLU_NURBS_VERTEX_EXT\nGLU_NURBS_NORMAL\nGLU_NURBS_NORMAL_EXT\nGLU_NURBS_COLOR\nGLU_NURBS_COLOR_EXT\nGLU_NURBS_TEXTURE_COORD\nGLU_NURBS_TEX_COORD_EXT\nGLU_NURBS_END\nGLU_NURBS_END_EXT\nGLU_NURBS_BEGIN_DATA\nGLU_NURBS_BEGIN_DATA_EXT\nGLU_NURBS_VERTEX_DATA\nGLU_NURBS_VERTEX_DATA_EXT\nGLU_NURBS_NORMAL_DATA\nGLU_NURBS_NORMAL_DATA_EXT\nGLU_NURBS_COLOR_DATA\nGLU_NURBS_COLOR_DATA_EXT\nGLU_NURBS_TEXTURE_COORD_DATA\nGLU_NURBS_TEX_COORD_DATA_EXT\nGLU_NURBS_END_DATA\nGLU_NURBS_END_DATA_EXT\nGLU_NURBS_ERROR1\nGLU_NURBS_ERROR2\nGLU_NURBS_ERROR3\nGLU_NURBS_ERROR4\nGLU_NURBS_ERROR5\nGLU_NURBS_ERROR6\nGLU_NURBS_ERROR7\nGLU_NURBS_ERROR8\nGLU_NURBS_ERROR9\nGLU_NURBS_ERROR10\nGLU_NURBS_ERROR11\nGLU_NURBS_ERROR12\nGLU_NURBS_ERROR13\nGLU_NURBS_ERROR14\nGLU_NURBS_ERROR15\nGLU_NURBS_ERROR16\nGLU_NURBS_ERROR17\nGLU_NURBS_ERROR18\nGLU_NURBS_ERROR19\nGLU_NURBS_ERROR20\nGLU_NURBS_ERROR21\nGLU_NURBS_ERROR22\nGLU_NURBS_ERROR23\nGLU_NURBS_ERROR24\nGLU_NURBS_ERROR25\nGLU_NURBS_ERROR26\nGLU_NURBS_ERROR27\nGLU_NURBS_ERROR28\nGLU_NURBS_ERROR29\nGLU_NURBS_ERROR30\nGLU_NURBS_ERROR31\nGLU_NURBS_ERROR32\nGLU_NURBS_ERROR33\nGLU_NURBS_ERROR34\nGLU_NURBS_ERROR35\nGLU_NURBS_ERROR36\nGLU_NURBS_ERROR37\nGLU_AUTO_LOAD_MATRIX\nGLU_CULLING\nGLU_SAMPLING_TOLERANCE\nGLU_DISPLAY_MODE\nGLU_PARAMETRIC_TOLERANCE\nGLU_SAMPLING_METHOD\nGLU_U_STEP\nGLU_V_STEP\nGLU_NURBS_MODE\nGLU_NURBS_MODE_EXT\nGLU_NURBS_TESSELLATOR\nGLU_NURBS_TESSELLATOR_EXT\nGLU_NURBS_RENDERER\nGLU_NURBS_RENDERER_EXT\nGLU_OBJECT_PARAMETRIC_ERROR\nGLU_OBJECT_PARAMETRIC_ERROR_EXT\nGLU_OBJECT_PATH_LENGTH\nGLU_OBJECT_PATH_LENGTH_EXT\nGLU_PATH_LENGTH\nGLU_PARAMETRIC_ERROR\nGLU_DOMAIN_DISTANCE\nGLU_MAP1_TRIM_2\nGLU_MAP1_TRIM_3\nGLU_POINT\nGLU_LINE\nGLU_FILL\nGLU_SILHOUETTE\nGLU_SMOOTH\nGLU_FLAT\nGLU_NONE\nGLU_OUTSIDE\nGLU_INSIDE\nGLU_TESS_BEGIN\nGLU_BEGIN\nGLU_TESS_VERTEX\nGLU_VERTEX\nGLU_TESS_END\nGLU_END\nGLU_TESS_ERROR\nGLU_TESS_EDGE_FLAG\nGLU_EDGE_FLAG\nGLU_TESS_COMBINE\nGLU_TESS_BEGIN_DATA\nGLU_TESS_VERTEX_DATA\nGLU_TESS_END_DATA\nGLU_TESS_ERROR_DATA\nGLU_TESS_EDGE_FLAG_DATA\nGLU_TESS_COMBINE_DATA\nGLU_CW\nGLU_CCW\nGLU_INTERIOR\nGLU_EXTERIOR\nGLU_UNKNOWN\nGLU_TESS_WINDING_RULE\nGLU_TESS_BOUNDARY_ONLY\nGLU_TESS_TOLERANCE\nGLU_TESS_ERROR1\nGLU_TESS_ERROR2\nGLU_TESS_ERROR3\nGLU_TESS_ERROR4\nGLU_TESS_ERROR5\nGLU_TESS_ERROR6\nGLU_TESS_ERROR7\nGLU_TESS_ERROR8\nGLU_TESS_MISSING_BEGIN_POLYGON\nGLU_TESS_MISSING_BEGIN_CONTOUR\nGLU_TESS_MISSING_END_POLYGON\nGLU_TESS_MISSING_END_CONTOUR\nGLU_TESS_COORD_TOO_LARGE\nGLU_TESS_NEED_COMBINE_CALLBACK\nGLU_TESS_WINDING_ODD\nGLU_TESS_WINDING_NONZERO\nGLU_TESS_WINDING_POSITIVE\nGLU_TESS_WINDING_NEGATIVE\nGLU_TESS_WINDING_ABS_GEQ_TWO\nGLU_TESS_MAX_COORD\nFTGL_RENDER_FRONT\nFTGL_RENDER_BACK\nFTGL_RENDER_SIDE\nFTGL_RENDER_ALL\nFTGL_ALIGN_LEFT\nFTGL_ALIGN_CENTER\nFTGL_ALIGN_RIGHT\nFTGL_ALIGN_JUSTIFY\n"
  },
  {
    "path": "src/Contained_RBTree.c",
    "content": "/******************************************************************************\\\n*   Contained_RBTree.cpp            by: TheSilverDirk / Michael Conrad         *\n*   Created: 03/12/2000             Last Modified: 08/29/2002                  *\n*   See Contained_RBTree.h for details                                         *\n\\******************************************************************************/\n\n/*\nCredits:\n\n  Intrest in red/black trees was inspired by Dr. John Franco, and his animated\n\tred/black tree java applet.\n  http://www.ececs.uc.edu/~franco/C321/html/RedBlack/redblack.html\n\n  The node insertion code was written in a joint effort with Anthony Deeter.\n\n  The red/black deletion algorithm was derived from the deletion patterns in\n   \"Fundamentals of Sequential and Parallel Algorithms\",\n\tby Dr. Kenneth A. Berman and Dr. Jerome L. Paul\n\n  I also got the sentinel node idea from this book.\n\n*/\n#include <config.h>\n#include \"Contained_RBTree.h\"\n\n//namespace ContainedClass {\n\nRBTreeNode Sentinel= { &Sentinel, &Sentinel, &Sentinel, RBTreeNode_Black, 0 };\n\nbool RBTreeNode_IsSentinel( RBTreeNode *Node ) {\n\treturn Node->Left == Node;\n}\n\nvoid RBTreeNode_Init( RBTreeNode* Node ) {\n\tNode->Color= RBTreeNode_Unassigned;\n}\n\nvoid RBTree_InitRootSentinel( RBTreeNode *RootSentinel ) {\n\tRootSentinel->Color= RBTreeNode_Black;\n\tRootSentinel->Left= &Sentinel;\n\tRootSentinel->Right= &Sentinel;\n\tRootSentinel->Parent= 0; // this uniquely marks this as the root sentinel\n\tRootSentinel->Object= 0;\n}\n\nvoid RBTree_Clear( RBTreeNode *RootSentinel ) {\n\tRBTreeNode *Temp= RBTree_GetLeftmost(RootSentinel->Left);\n\twhile (Temp != &Sentinel) {\n\t\tTemp->Color= RBTreeNode_Unassigned;\n\t\tTemp= RBTree_GetNext(Temp);\n\t}\n\tRootSentinel->Left= &Sentinel;\n}\n\nbool RBTree_Add( RBTreeNode *RootSentinel, RBTreeNode* NewNode, RBTree_inorder_func* inorder ) {\n\tRBTreeNode* Current;\n\tif (NewNode->Color != RBTreeNode_Unassigned)\n\t\treturn false;\n\n\tNewNode->Color= RBTreeNode_Red;\n\tNewNode->Left=  &Sentinel;\n\tNewNode->Right= &Sentinel;\n\n\tCurrent= RootSentinel->Left;\n\tif (Current == &Sentinel) {\n\t\tRootSentinel->Left= NewNode;\n\t\tNewNode->Parent= RootSentinel;\n\t}\n\telse {\n\t\tdo {\n\t\t\t// if the new node comes before the current node, go left\n\t\t\tif (inorder( NewNode->Object, Current->Object )) {\n\t\t\t\tif (Current->Left == &Sentinel) {\n\t\t\t\t\tCurrent->Left= NewNode;\n\t\t\t\t\tNewNode->Parent= Current;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\telse Current= Current->Left;\n\t\t\t}\n\t\t\t// else go right\n\t\t\telse {\n\t\t\t\tif (Current->Right == &Sentinel) {\n\t\t\t\t\tCurrent->Right= NewNode;\n\t\t\t\t\tNewNode->Parent= Current;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\telse Current= Current->Right;\n\t\t\t}\n\t\t} while (1);\n\t\tRBTree_Balance( Current );\n\t}\n\tRootSentinel->Left->Color= RBTreeNode_Black;\n\treturn true;\n}\n\nRBTreeNode* RBTree_Find( const RBTreeNode *RootSentinel, const void* SearchKey, RBTree_compare_func* compare) {\n\tRBTreeNode* Current= RootSentinel->Left;\n\twhile (Current != &Sentinel) {\n\t\tint i= compare( SearchKey, Current->Object );\n\t\tif      (i<0) Current= Current->Left;\n\t\telse if (i>0) Current= Current->Right;\n\t\telse return Current;\n\t}\n\treturn &Sentinel;\n}\n\nRBTreeNode* RBTree_GetLeftmost( RBTreeNode* Node ) {\n\twhile (Node->Left != &Sentinel)\n\t\tNode= Node->Left;\n\treturn Node;\n}\n\nRBTreeNode* RBTree_GetRightmost( RBTreeNode* Node ) {\n\twhile (Node->Right != &Sentinel)\n\t\tNode= Node->Right;\n\treturn Node;\n}\n\nRBTreeNode* RBTree_GetPrev( RBTreeNode* Node ) {\n\t// If we are not at a leaf, move to the right-most node\n\t//  in the tree to the left of this node.\n\tif (Node->Left != &Sentinel) {\n\t\tRBTreeNode* Current= Node->Left;\n\t\twhile (Current->Right != &Sentinel)\n\t\t\tCurrent= Current->Right;\n\t\treturn Current;\n\t}\n\t// Else walk up the tree until we see a parent node to the left\n\telse {\n\t\tRBTreeNode* Parent= Node->Parent;\n\t\twhile (Parent->Left == Node) {\n\t\t\tNode= Parent;\n\t\t\tParent= Parent->Parent;\n\t\t\t// Check for RootSentinel\n\t\t\tif (!Parent) return &Sentinel;\n\t\t}\n\t\treturn Parent;\n\t}\n}\n\nRBTreeNode* RBTree_GetNext( RBTreeNode* Node ) {\n\t// If we are not at a leaf, move to the left-most node\n\t//  in the tree to the right of this node.\n\tif (Node->Right != &Sentinel) {\n\t\tRBTreeNode* Current= Node->Right;\n\t\twhile (Current->Left != &Sentinel)\n\t\t\tCurrent= Current->Left;\n\t\treturn Current;\n\t}\n\t// Else walk up the tree until we see a parent node to the right\n\telse {\n\t\tRBTreeNode* Parent= Node->Parent;\n\t\twhile (Parent->Right == Node) {\n\t\t\tNode= Parent;\n\t\t\tParent= Node->Parent;\n\t\t}\n\t\t// Check for the RootSentinel\n\t\tif (!Parent->Parent) return &Sentinel;\n\n\t\treturn Parent;\n\t}\n}\n\nvoid RBTree_RightSide_RightRotate( RBTreeNode* Node ) {\n\tRBTreeNode* temp= Node->Parent; // temp is used for parent\n\tRBTreeNode* child= Node->Left;\n\n\ttemp->Right= child;\n\tchild->Parent= temp;\n\n\ttemp= child->Right; // temp is now used for grandchild\n\tNode->Left= temp;\n\t/*if (temp != Sentinel)*/\n\ttemp->Parent= Node;\n\n\tchild->Right= Node;\n\tNode->Parent= child;\n}\n\nvoid RBTree_LeftSide_LeftRotate( RBTreeNode* Node ) {\n\tRBTreeNode* temp= Node->Parent; // temp is used for parent\n\tRBTreeNode* child= Node->Right;\n\n\ttemp->Left= child;\n\tchild->Parent= temp;\n\n\ttemp= child->Left; // temp is now used for grandchild\n\tNode->Right= temp;\n\t/*if (temp != Sentinel)*/\n\ttemp->Parent= Node;\n\n\tchild->Left= Node;\n\tNode->Parent= child;\n}\n\nvoid RBTree_LeftSide_RightRotate( RBTreeNode* Node ) {\n\tRBTreeNode* temp= Node->Parent; // temp is used for parent\n\tRBTreeNode* child= Node->Left;\n\n\ttemp->Left= child;\n\tchild->Parent= temp;\n\n\ttemp= child->Right; // temp is now used for grandchild\n\tNode->Left= temp;\n\t/*if (temp != Sentinel)*/\n\ttemp->Parent= Node;\n\n\tchild->Right= Node;\n\tNode->Parent= child;\n}\n\nvoid RBTree_RightSide_LeftRotate( RBTreeNode* Node ) {\n\tRBTreeNode* temp= Node->Parent; // temp is used for parent\n\tRBTreeNode* child= Node->Right;\n\n\ttemp->Right= child;\n\tchild->Parent= temp;\n\n\ttemp= child->Left; // temp is now used for grandchild\n\tNode->Right= temp;\n\t/*if (temp != Sentinel)*/\n\ttemp->Parent= Node;\n\n\tchild->Left= Node;\n\tNode->Parent= child;\n}\n\n// current is the parent node of the node just added.  The child is red.\nvoid RBTree_Balance( RBTreeNode* Current ) {\n\t// if Current is a black node, no rotations needed\n\twhile (Current->Color != RBTreeNode_Black) {\n//\t\tif (!Current->Parent) break;  XXX may not need this\n\t\t// Current is red, the imbalanced child is red, and parent is black.\n\n\t\tRBTreeNode *Parent= Current->Parent;\n\n\t\t// if the Current is on the right of the parent, the parent is to the left\n\t\tif (Parent->Right == Current) {\n\t\t\t// if the sibling is also red, we can pull down the color black from the parent\n\t\t\tif (Parent->Left->Color == RBTreeNode_Red) {\n\t\t\t\tParent->Left->Color= RBTreeNode_Black;\n\t\t\t\tCurrent->Color= RBTreeNode_Black;\n\t\t\t\tParent->Color= RBTreeNode_Red;\n\t\t\t\t// jump twice up the tree. if Current reaches the HeadSentinel (black node), the loop will stop\n\t\t\t\tCurrent= Parent->Parent;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// if the imbalance (red node) is on the left, and the parent is on the left,\n\t\t\t//  a \"prep-slide\" is needed. (see diagram)\n\t\t\tif (Current->Left->Color == RBTreeNode_Red)\n\t\t\t\tRBTree_RightSide_RightRotate( Current );\n\n\t\t\t// Now we can do our left rotation to balance the tree.\n\t\t\tif (Parent->Parent->Left == Parent)\n\t\t\t\tRBTree_LeftSide_LeftRotate( Parent );\n\t\t\telse\n\t\t\t\tRBTree_RightSide_LeftRotate( Parent );\n\t\t\tParent->Color= RBTreeNode_Red;\n\t\t\tParent->Parent->Color= RBTreeNode_Black;\n\t\t\treturn;\n\t\t}\n\t\t// else the parent is to the right\n\t\telse {\n\t\t\t// if the sibling is also red, we can pull down the color black from the parent\n\t\t\tif (Parent->Right->Color == RBTreeNode_Red) {\n\t\t\t\tParent->Right->Color= RBTreeNode_Black;\n\t\t\t\tCurrent->Color= RBTreeNode_Black;\n\t\t\t\tParent->Color= RBTreeNode_Red;\n\t\t\t\t// jump twice up the tree. if Current reaches the HeadSentinel (black node), the loop will stop\n\t\t\t\tCurrent= Parent->Parent;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// if the imbalance (red node) is on the right, and the parent is on the right,\n\t\t\t//  a \"prep-slide\" is needed. (see diagram)\n\t\t\tif (Current->Right->Color == RBTreeNode_Red)\n\t\t\t\tRBTree_LeftSide_LeftRotate( Current );\n\n\t\t\t// Now we can do our left rotation to balance the tree.\n\t\t\tif (Parent->Parent->Left == Parent)\n\t\t\t\tRBTree_LeftSide_RightRotate( Parent );\n\t\t\telse\n\t\t\t\tRBTree_RightSide_RightRotate( Parent );\n\t\t\tParent->Color= RBTreeNode_Red;\n\t\t\tParent->Parent->Color= RBTreeNode_Black;\n\t\t\treturn;\n\t\t}\n\t}\n\treturn;\n}\n\nbool RBTree_Prune( RBTreeNode* Current ) {\n\tRBTreeNode* Temp;\n\tif (Current->Color == RBTreeNode_Unassigned)\n\t\treturn false;\n\n\t// If this is a leaf node (or almost a leaf) we can just prune it\n\tif (Current->Left == &Sentinel || Current->Right == &Sentinel)\n\t\tRBTree_PruneLeaf(Current);\n\n\t// Otherwise we need a successor.  We are guaranteed to have one because\n\t//  the current node has 2 children.\n\telse {\n\t\tRBTreeNode* Successor= RBTree_GetNext( Current );\n\t\t// Do we like this successor?  If not, get the other one.\n\t\tif (Successor->Color == RBTreeNode_Black && Successor->Left == &Sentinel && Successor->Right == &Sentinel)\n\t\t\tSuccessor= RBTree_GetPrev( Current );\n\n\t\tRBTree_PruneLeaf( Successor );\n\n\t\t// now exchange the successor for the current node\n\t\tTemp= Current->Right;\n\t\tSuccessor->Right= Temp;\n\t\tTemp->Parent= Successor;\n\n\t\tTemp= Current->Left;\n\t\tSuccessor->Left= Temp;\n\t\tTemp->Parent= Successor;\n\n\t\tTemp= Current->Parent;\n\t\tSuccessor->Parent= Temp;\n\t\tif (Temp->Left == Current) Temp->Left= Successor; else Temp->Right= Successor;\n\t\tSuccessor->Color= Current->Color;\n\t}\n\tCurrent->Color= RBTreeNode_Unassigned;\n\treturn true;\n}\n\n// PruneLeaf performs pruning of nodes with at most one child node.\nvoid RBTree_PruneLeaf( RBTreeNode* Node ) {\n\tRBTreeNode *Parent= Node->Parent, *Current, *Sibling;\n\tbool LeftSide= (Parent->Left == Node);\n\n\t// if the node is red and has at most one child, then it has no child.\n\t// Prune it.\n\tif (Node->Color == RBTreeNode_Red) {\n\t\tif (LeftSide) Parent->Left= &Sentinel;\n\t\telse Parent->Right= &Sentinel;\n\t\treturn;\n\t}\n\n\t// Node is black here.  If it has a child, the child will be red.\n\tif (Node->Left != &Sentinel) {\n\t\t// swap with child\n\t\tNode->Left->Color= RBTreeNode_Black;\n\t\tNode->Left->Parent= Parent;\n\t\tif (LeftSide) Parent->Left= Node->Left;\n\t\telse Parent->Right= Node->Left;\n\t\treturn;\n\t}\n\tif (Node->Right != &Sentinel) {\n\t\t// swap with child\n\t\tNode->Right->Color= RBTreeNode_Black;\n\t\tNode->Right->Parent= Parent;\n\t\tif (LeftSide) Parent->Left= Node->Right;\n\t\telse Parent->Right= Node->Right;\n\t\treturn;\n\t}\n\n/*\tNow, we have determined that Node is a black leaf node with no children.\n\tThe tree must have the same number of black nodes along any path from root\n\tto leaf.  We want to remove a black node, disrupting the number of black\n\tnodes along the path from the root to the current leaf.  To correct this,\n\twe must either shorten all other paths, or add a black node to the current\n\tpath.  Then we can freely remove our black leaf.\n\n\tWhile we are pointing to it, we will go ahead and delete the leaf and\n\treplace it with the sentinel (which is also black, so it won't affect\n\tthe algorithm).\n*/\n\tif (LeftSide) Parent->Left= &Sentinel; else Parent->Right= &Sentinel;\n\n\tSibling= (LeftSide)? Parent->Right : Parent->Left;\n\tCurrent= Node;\n\n\t// Loop until the current node is red, or until we get to the root node.\n\t// (The root node's parent is the RootSentinel, which will have a NULL parent.)\n\twhile (Current->Color == RBTreeNode_Black && Parent->Parent != 0) {\n\t\t// If the sibling is red, we are unable to reduce the number of black\n\t\t//  nodes in the sibling tree, and we can't increase the number of black\n\t\t//  nodes in our tree..  Thus we must do a rotation from the sibling\n\t\t//  tree to our tree to give us some extra (red) nodes to play with.\n\t\t// This is Case 1 from the text\n\t\tif (Sibling->Color == RBTreeNode_Red) {\n\t\t\tParent->Color= RBTreeNode_Red;\n\t\t\tSibling->Color= RBTreeNode_Black;\n\t\t\tif (LeftSide) {\n\t\t\t\tif (Parent->Parent->Left == Parent)\n\t\t\t\t\tRBTree_LeftSide_LeftRotate( Parent );\n\t\t\t\telse\n\t\t\t\t\tRBTree_RightSide_LeftRotate( Parent );\n\t\t\t\tSibling= Parent->Right;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif (Parent->Parent->Left == Parent)\n\t\t\t\t\tRBTree_LeftSide_RightRotate( Parent );\n\t\t\t\telse\n\t\t\t\t\tRBTree_RightSide_RightRotate( Parent );\n\t\t\t\tSibling= Parent->Left;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\t// Sibling will be black here\n\n\t\t// If the sibling is black and both children are black, we have to\n\t\t//  reduce the black node count in the sibling's tree to match ours.\n\t\t// This is Case 2a from the text.\n\t\tif (Sibling->Right->Color == RBTreeNode_Black && Sibling->Left->Color == RBTreeNode_Black) {\n\t\t\tSibling->Color= RBTreeNode_Red;\n\t\t\t// Now we move one level up the tree to continue fixing the\n\t\t\t// other branches.\n\t\t\tCurrent= Parent;\n\t\t\tParent= Current->Parent;\n\t\t\tLeftSide= (Parent->Left == Current);\n\t\t\tSibling= (LeftSide)? Parent->Right : Parent->Left;\n\t\t\tcontinue;\n\t\t}\n\t\t// Sibling will be black with 1 or 2 red children here\n\n\t\t// << Case 2b is handled by the while loop. >>\n\n\t\t// If one of the sibling's children are red, we again can't make the\n\t\t//  sibling red to balance the tree at the parent, so we have to do a\n\t\t//  rotation.  If the \"near\" nephew is red and the \"far\" nephew is\n\t\t//  black, we need to do a \"prep-slide\" (aka \"double rotation\")\n\t\t// After doing a rotation and rearranging a few colors, the effect is\n\t\t//  that we maintain the same number of black nodes per path on the far\n\t\t//  side of the parent, and we gain a black node on the current side,\n\t\t//  so we are done.\n\t\t// This is Case 4 from the text. (Case 3 is the double rotation)\n\t\tif (LeftSide) {\n\t\t\tif (Sibling->Right->Color == RBTreeNode_Black) { // Case 3 from the text\n\t\t\t\tRBTree_RightSide_RightRotate( Sibling );\n\t\t\t\tSibling= Parent->Right;\n\t\t\t}\n\t\t\t// now Case 4 from the text\n\t\t\tSibling->Right->Color= RBTreeNode_Black;\n\t\t\tSibling->Color= Parent->Color;\n\t\t\tParent->Color= RBTreeNode_Black;\n\n\t\t\tCurrent= Parent;\n\t\t\tParent= Current->Parent;\n\t\t\t// I would have assigned to LeftSide here,\n\t\t\t//   but we are exiting the function, so why bother?\n\t\t\t// LeftSide= (Parent->Left == Current);\n\t\t\tif /*(LeftSide)*/(Parent->Left == Current)\n\t\t\t\tRBTree_LeftSide_LeftRotate( Current );\n\t\t\telse\n\t\t\t\tRBTree_RightSide_LeftRotate( Current );\n\t\t\treturn;\n\t\t}\n\t\telse {\n\t\t\tif (Sibling->Left->Color == RBTreeNode_Black) { // Case 3 from the text\n\t\t\t\tRBTree_LeftSide_LeftRotate( Sibling );\n\t\t\t\tSibling= Parent->Left;\n\t\t\t}\n\t\t\t// now Case 4 from the text\n\t\t\tSibling->Left->Color= RBTreeNode_Black;\n\t\t\tSibling->Color= Parent->Color;\n\t\t\tParent->Color= RBTreeNode_Black;\n\n\t\t\tCurrent= Parent;\n\t\t\tParent= Current->Parent;\n\t\t\t// I would have assigned to LeftSide here,\n\t\t\t//   but we are exiting the function, so why bother?\n\t\t\t// LeftSide= (Parent->Left == Current);\n\t\t\tif /*(LeftSide)*/(Parent->Left == Current)\n\t\t\t\tRBTree_LeftSide_RightRotate( Current );\n\t\t\telse\n\t\t\t\tRBTree_RightSide_RightRotate( Current );\n\t\t\treturn;\n\t\t}\n\t}\n\n\t// Now, make the current node black (to fulfill Case 2b)\n\t// Case 4 will have exited directly out of the function.\n\t// If we stopped because we reached the top of the tree,\n\t//   the head is black anyway so don't worry about it.\n\tCurrent->Color= RBTreeNode_Black;\n}\n\n//}\n"
  },
  {
    "path": "src/Contained_RBTree.h",
    "content": "/******************************************************************************\\\n*   Contained_RBTree.h              by: TheSilverDirk / Michael Conrad\n*   Created: 06/23/2000             Last Modified: 04/29/2005\n*\n*   2005-04-29: Hacked-up sufficiently to be compilable under C.\n*\n*   This is a red/black binary search tree implementation using the\n*   \"contained class\" system.  The \"inorder\" and \"compare\" function pointers\n*   allow you to do custom sorting.  These pointers MUST point to valid\n*   functions before you use the tree.\n\\******************************************************************************/\n\n#include \"Global.h\"\n\n#ifndef CONTAINED_RBTREE_H\n#define CONTAINED_RBTREE_H\n\n//namespace ContainedClass {\n\n/******************************************************************************\\\n*   Contained RBTree Data Structure\n\\******************************************************************************/\n\n#define RBTreeNode_Black 0\n#define RBTreeNode_Red 1\n#define RBTreeNode_Unassigned 2\ntypedef struct RBTreeNode_t {\n//\tenum NodeColor { Black= 0, Red= 1, Unassigned= 2 };\n\n\tstruct RBTreeNode_t* Left;\n\tstruct RBTreeNode_t* Right;\n\tstruct RBTreeNode_t* Parent;\n\tint         Color;\n\tvoid*       Object;\n} RBTreeNode;\n\n/******************************************************************************\\\n*   Base RBTree functions - all functions required to manipulate a R/B tree.\n*\n*   These functions are all ordinary functions in order to be compatible with\n*     other languages, such as C\n\\******************************************************************************/\ntypedef bool RBTree_inorder_func( const void* Obj_A, const void* Obj_B );\ntypedef int  RBTree_compare_func( const void* SearchKey, const void* Object );\n\nvoid RBTreeNode_Init( RBTreeNode* Node );\nbool RBTreeNode_IsSentinel( RBTreeNode *Node );\nvoid RBTree_InitRootSentinel( RBTreeNode *RootSentinel );\nvoid RBTree_Clear( RBTreeNode *RootSentinel );\nRBTreeNode* RBTree_GetPrev( RBTreeNode* Node );\nRBTreeNode* RBTree_GetNext( RBTreeNode* Node );\nRBTreeNode* RBTree_GetRightmost( RBTreeNode* Node );\nRBTreeNode* RBTree_GetLeftmost( RBTreeNode* Node );\n//inline const RBTreeNode* RBTree_GetLeftmost ( const RBTreeNode* Node ) { return RBTree_GetLeftmost (const_cast<RBTreeNode*>(Node)); }\n//inline const RBTreeNode* RBTree_GetRightmost( const RBTreeNode* Node ) { return RBTree_GetRightmost(const_cast<RBTreeNode*>(Node)); }\n//inline const RBTreeNode* RBTree_GetPrev     ( const RBTreeNode* Node ) { return RBTree_GetPrev     (const_cast<RBTreeNode*>(Node)); }\n//inline const RBTreeNode* RBTree_GetNext     ( const RBTreeNode* Node ) { return RBTree_GetNext     (const_cast<RBTreeNode*>(Node)); }\nvoid RBTree_LeftSide_LeftRotate( RBTreeNode* Node );\nvoid RBTree_LeftSide_RightRotate( RBTreeNode* Node );\nvoid RBTree_RightSide_RightRotate( RBTreeNode* Node );\nvoid RBTree_RightSide_LeftRotate( RBTreeNode* Node );\nbool RBTree_Add( RBTreeNode *RootSentinel, RBTreeNode* NewNode, RBTree_inorder_func* inorder );\nRBTreeNode* RBTree_Find( const RBTreeNode *RootSentinel, const void* SearchKey, RBTree_compare_func* compare );\nvoid RBTree_Balance( RBTreeNode* Node );\nbool RBTree_Prune( RBTreeNode* Node );\nvoid RBTree_PruneLeaf( RBTreeNode* Node );\n\nextern RBTreeNode Sentinel;\n\n/******************************************************************************\\\n*   Contained RBTree Class                                                     *\n\\******************************************************************************/\n/*\nclass ECannotAddNode {};\nclass ECannotRemoveNode {};\n\nclass RBTree {\npublic:\n\tclass Node: public RBTreeNode {\n\tpublic:\n\t\tNode()  { RBTreeNode_Init(this); }\n\t\t~Node() { if (RBTreeNode::Color != RBTreeNode::Unassigned) RBTree_Prune(this); }\n\n\t\t// The average user shouldn't need these, but they might come in handy.\n\t\tvoid* Left()   const { return RBTreeNode::Left->Object;   }\n\t\tvoid* Right()  const { return RBTreeNode::Right->Object;  }\n\t\tvoid* Parent() const { return RBTreeNode::Parent->Object; }\n\t\tint   Color()        { return RBTreeNode::Color; }\n\n\t\t// These let you use your nodes as a sequence.\n\t\tvoid* Next()   const { return RBTree_GetNext(this)->Object; }\n\t\tvoid* Prev()   const { return RBTree_GetPrev(this)->Object; }\n\n\t\tbool IsSentinel() { return RBTreeNode_IsSentinel(this); }\n\n\t\tfriend RBTree;\n\t};\n\nprivate:\n\tRBTreeNode RootSentinel; // the left child of the sentinel is the root node\npublic:\n\tRBTree_inorder_func *inorder;\n\tRBTree_compare_func *compare;\n\n\tRBTree() { RBTree_InitRootSentinel(RootSentinel); }\n\t~RBTree() { Clear(); }\n\n\tvoid Clear() { RBTree_Clear(RootSentinel); }\n\tbool IsEmpty() const { return RBTreeNode_IsSentinel(RootSentinel.Left); }\n\n\tvoid* GetRoot()  const { return RootSentinel.Left->Object; }\n\tvoid* GetFirst() const { return RBTree_GetLeftmost(RootSentinel.Left)->Object; }\n\tvoid* GetLast()  const { return RBTree_GetRightmost(RootSentinel.Left)->Object; }\n\n\tvoid Add( Node* NewNode ) { if (!RBTree_Add(RootSentinel, NewNode, inorder)) throw ECannotAddNode(); }\n\n\tvoid* Find( const void *SearchKey ) const { return RBTree_Find(RootSentinel, SearchKey, compare)->Object; }\n\n\tstatic void Remove( Node* Node ) { if (!RBTree_Prune(Node)) throw ECannotRemoveNode(); }\n};\n*/\n\ntypedef struct RBTree_t {\n\tRBTreeNode RootSentinel; // the left child of the sentinel is the root node\n\tRBTree_inorder_func *inorder;\n\tRBTree_compare_func *compare;\n} RBTree;\n\n/******************************************************************************\\\n*   Type-Safe Contained Red/Black Tree Class                                   *\n\\******************************************************************************/\n/*\ntemplate <class T>\nclass TypedRBTree: public RBTree {\npublic:\n\ttypedef RBTree Inherited;\n\n\tclass Node: public RBTree::Node {\n\tpublic:\n\t\ttypedef RBTree::Node Inherited;\n\n\t\t// The average user shouldn't need these, but they might come in handy.\n\t\tT* Left()   const { return (T*) Inherited::Left();   }\n\t\tT* Right()  const { return (T*) Inherited::Right();  }\n\t\tT* Parent() const { return (T*) Inherited::Parent(); }\n\t\tint Color() const { return Inherited::Color(); }\n\n\t\t// These let you use your nodes as a sequence.\n\t\tT* Next()   const { return (T*) Inherited::Next(); }\n\t\tT* Prev()   const { return (T*) Inherited::Prev(); }\n\n\t\tfriend TypedRBTree<T>;\n\t};\n\npublic:\n\tT* GetRoot()  const { return (T*) Inherited::GetRoot();  }\n\tT* GetFirst() const { return (T*) Inherited::GetFirst(); }\n\tT* GetLast()  const { return (T*) Inherited::GetLast();  }\n\n\tvoid Add( Node* NewNode ) { Inherited::Add(NewNode); }\n\n\tT* Find( const void *Val ) const { return (T*) Inherited::Find(Val); }\n\n\tstatic void Remove( Node* Node ) { Inherited::Remove(Node); }\n};\n\n}\n*/\n#endif\n\n"
  },
  {
    "path": "src/Font.c",
    "content": "#include <config.h>\n#include \"Global.h\"\n#include \"ParseGL.h\"\n#include \"ProcessInput.h\"\n#include \"SymbolHash.h\"\n\n#ifdef HAVE_LIBFTGL\n\n/*=head2 FTGL Font Functions\n\nThese functions come from the FTGL library.  They can open any font file that the FreeType\nlibrary can open.  A symbolic name takes the place of FTGL's C<FTfont*> pointer. You must\ncall one of the Create methods (and it must succeed) to initialize a symbolic name before\nit can be used in any of the rendering functions.\n\n=item ftglCreateBitmapFont NAME \"FONT_FILE_PATH\"\n\nCreate a 2-color font that renders directly to the framebuffer in 2D.\n\n=item ftglCreatePixmapFont NAME \"FONT_FILE_PATH\"\n\nCreate a 256-color-grayscale font that renders directly to the framebuffer in 2D.\n\n=item ftglCreateTextureFont NAME \"FONT_FILE_PATH\"\n\nCreate a font that renders each glyph into a texture, so that a small set of textures can\nsupply all your rendering needs.\n\n=item ftglCreateBufferFont NAME \"FONT_FILE_PATH\"\n\nCreate a texture-based font that renders each line of text into its own texture, so that common\nphrases can be drawn as a single polygon.\n\n=item ftglCreateExtrudeFont NAME \"FONT_FILE_PATH\"\n\nCreate 3D models to represent each glyph extruded as a solid object.\n\n=item ftglCreateOutlineFont NAME \"FONT_FILE_PATH\"\n\nCreate 2D model of GL lines that trace the outline of each glyph.\n\n=item ftglCreatePolygonFont NAME \"FONT_FILE_PATH\"\n\nCreate each glyph as a flat 2D mesh of polygons.\n\n=item ftglDestroyFont NAME\n\nFree resources and un-define the symbolic NAME.\n\n=cut */\n\nbool InitNamedFont(SymbVarEntry *sym, FTGLfont *font) {\n\tif (!font) {\n\t\t/* if newly created, remove the tree node so we don't have a null pointer dangling around */\n\t\tif (!sym->Data)\n\t\t\tDeleteSymbVar(sym);\n\t\treturn false;\n\t}\n\t/* If the font already existed, delete the old one */\n\tif (sym->Data)\n\t\tftglDestroyFont( (FTGLfont*) sym->Data );\n\t\n\tsym->Data= font;\n\treturn true;\n}\n\nCOMMAND(ftglCreateBitmapFont, \"F!/\") {\n\treturn InitNamedFont(parsed->objects[0], ftglCreateBitmapFont(parsed->strings[0]));\n}\nCOMMAND(ftglCreateBufferFont, \"F!/\") {\n\treturn InitNamedFont(parsed->objects[0], ftglCreateBufferFont(parsed->strings[0]));\n}\nCOMMAND(ftglCreateExtrudeFont, \"F!/\") {\n\treturn InitNamedFont(parsed->objects[0], ftglCreateExtrudeFont(parsed->strings[0]));\n}\nCOMMAND(ftglCreateOutlineFont, \"F!/\") {\n\treturn InitNamedFont(parsed->objects[0], ftglCreateOutlineFont(parsed->strings[0]));\n}\nCOMMAND(ftglCreatePixmapFont, \"F!/\") {\n\treturn InitNamedFont(parsed->objects[0], ftglCreatePixmapFont(parsed->strings[0]));\n}\nCOMMAND(ftglCreatePolygonFont, \"F!/\") {\n\treturn InitNamedFont(parsed->objects[0], ftglCreatePolygonFont(parsed->strings[0]));\n}\nCOMMAND(ftglCreateTextureFont, \"F!/\") {\n\treturn InitNamedFont(parsed->objects[0], ftglCreateTextureFont(parsed->strings[0]));\n}\n\nCOMMAND(ftglDestroyFont, \"F\") {\n\tSymbVarEntry *sym= parsed->objects[0];\n\tftglDestroyFont( (FTGLfont*) sym->Data );\n\tDeleteSymbVar(sym);\n\treturn true;\n}\n\n/*=item ftglSetFontCharMap NAME CMAP_CODE\n\nSet the charmap to one of the codes known by the FreeType library.\n\n=item ftglSetFontFaceSize NAME SIZE\n\nFor texture and raster fonts, render each glyph at SIZE pixels.  For Vector fonts, render each\nglyph at SIZE logical units.\n\n=item ftglSetFontDepth NAME SIZE\n\nFor extruded fonts, set the depth to SIZE units.\n\n=item ftglSetFontOutset NAME FRONT BACK\n\nFor extruded fonts.\n\n=cut */\n\nCOMMAND(ftglSetFontCharMap, \"Fi\") {\n\tFTGLfont *font= (FTGLfont*) parsed->objects[0]->Data;\n\tftglSetFontCharMap(font, parsed->ints[0]);\n\treturn true;\n}\n\nCOMMAND(ftglSetFontFaceSize, \"Fii\") {\n\tFTGLfont *font= (FTGLfont*) parsed->objects[0]->Data;\n\tftglSetFontFaceSize(font, parsed->ints[0], parsed->ints[1]);\n\treturn true;\n}\n\nCOMMAND(ftglSetFontDepth, \"Ff\") {\n\tFTGLfont *font= (FTGLfont*) parsed->objects[0]->Data;\n\tftglSetFontDepth(font, parsed->floats[0]);\n\treturn true;\n}\n\nCOMMAND(ftglSetFontOutset, \"Fff\") {\n\tFTGLfont *font= (FTGLfont*) parsed->objects[0]->Data;\n\tftglSetFontOutset(font, parsed->floats[0], parsed->floats[1]);\n\treturn true;\n}\n\n/*=item ftglRenderFont NAME TEXT FLAGS[...]\n\nRenter TEXT using NAMEd font, affected by FLAGS.  In the C API, the flags are combined, but in\nthis command each flag is given as another parameter.  Flags are: FTGL_RENDER_FRONT,\nFTGL_RENDER_BACK, FTGL_RENDER_SIDE, FTGL_RENDER_ALL, FTGL_ALIGN_LEFT, FTGL_ALIGN_RIGHT,\nFTGL_ALIGN_CENTER, FTGL_ALIGN_JUSTIFY.\n\n=cut */\n\nCOMMAND(ftglRenderFont, \"Fsi*\") {\n\tFTGLfont *font= (FTGLfont*) parsed->objects[0]->Data;\n\tint flags= 0, i;\n\tfor (i=0; i< parsed->iCnt; i++)\n\t\tflags |= parsed->ints[i];\n\tftglRenderFont(font, parsed->strings[0], flags);\n\treturn true;\n}\n\n#endif\n"
  },
  {
    "path": "src/Font.h",
    "content": "#ifndef FONT_H\n#define FONT_H\n\n#endif\n"
  },
  {
    "path": "src/Global.c",
    "content": "#include <config.h>\n#include \"Global.h\"\n\n#ifdef _WIN32\nvoid WinPerror(char *msg) {\n\tchar* BuffPtr= NULL;\n\tFormatMessage(\n\t\tFORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,\n\t\tNULL,\n\t\tGetLastError(),\n\t\t0,\n\t\t(LPTSTR) &BuffPtr,\n\t\t0,\n\t\tNULL);\n\tfprintf(stderr, \"%s: %s\", msg, BuffPtr? BuffPtr : \"Error message lookup failed\");\n\tif (BuffPtr) LocalFree(BuffPtr);\n}\n#endif\n\n#ifndef NDEBUG\nvoid DebugMsg(char *msg, ...) {\n\tva_list ap;\n\tva_start(ap, msg);\n\tvfprintf(stderr, msg, ap);\n\tva_end(ap);\n\tfflush(stderr);\n}\n#endif\n\n"
  },
  {
    "path": "src/Global.h",
    "content": "#ifndef GLOBAL_H\n#define GLOBAL_H\n\n/* ------------------------------------\n * Settings for the program.\n */\n\n#ifndef MAX_COMMAND_BATCH\n#  define MAX_COMMAND_BATCH 8\n#endif\n#ifndef MAX_GL_PARAMS\n#  define MAX_GL_PARAMS 32\n#endif\n\nstruct ParseParamsResult;\n#define COMMAND(name,fmt) bool cmd_##name(struct ParseParamsResult *parsed)\n\n#ifndef NDEBUG\n#  define DEBUGMSG(a) DebugMsg a\n  void DebugMsg(char *str, ...);\n#else\n  #define DEBUGMSG(a) do{}while(0)\n#endif\n\n#ifdef _WIN32\nvoid WinPerror(char *msg);\n#endif\n\n#endif\n"
  },
  {
    "path": "src/ImageLoader.c",
    "content": "#define INCLUDE_GL\n#define INCLUDE_SDL\n#include <config.h>\n#include \"Global.h\"\n#include \"ParseGL.h\"\n#include \"ImageLoader.h\"\n#include \"ProcessInput.h\"\n\nbool UsableByGL(SDL_Surface *Img) {\n\tint dim;\n\t// images must be square (could get into the ARB_rectangular_texture mess, but then\n\t// users of CmdlineGL would have to deal with the detection)\n\tif (Img->w != Img->h) {\n\t\tfprintf(stderr, \"OpenGL requires square images. (image is %dx%d)\\n\", (int)Img->w, (int)Img->h);\n\t\treturn false;\n\t}\n\t// image dimensions must be a power of 2\n\tfor (dim= Img->w; dim != 1; dim>>=1)\n\t\tif (dim&1) {\n\t\t\tfprintf(stderr, \"OpenGL requires image dimensions to be a power of 2. (%d is not)\\n\", (int)Img->w);\n\t\t\treturn false;\n\t\t}\n\tif (Img->format->BytesPerPixel < 2 || Img->format->BytesPerPixel > 4) {\n\t\tfprintf(stderr, \"Image pixel format not handled by CmdlineGL. Expecting 16/24/32bpp\\n\");\n\t\treturn false;\n\t}\n\t// we need a contiguous byte array of pixels\n\t//if (Img->pitch != Img->w * Img->format->BytesPerPixel) {\n\t//\tfprintf(stderr, \"SDL did not load the pixels as a contiguous array of bytes.\\n\");\n\t//\treturn false;\n\t//}\n\treturn true;\n}\n\nSDL_Surface* LoadImg(const char *FName) {\n\tSDL_Surface *Img;\n#ifdef HAVE_LIBSDL_IMAGE\n\tImg= IMG_Load(FName);\n#else\n\tImg= SDL_LoadBMP(FName);\n#endif\n\tif (!Img)\n\t\tfprintf(stderr, \"Error loading image '%s'\"\n\t\t#ifndef HAVE_LIBSDL_IMAGE\n\t\t\t\"; SDL_image not available, so file must be plain bitmap\"\n\t\t#endif\n\t\t\t, FName);\n\telse if (!UsableByGL(Img)) {\n\t\tfprintf(stderr, \"Unable to use image '%s'\\n\", FName);\n\t\tSDL_FreeSurface(Img);\n\t\tImg= NULL;\n\t}\n\telse\n\t\tDEBUGMSG((\"Loaded image '%s', %dx%d %dbpp\\n\", FName, Img->w, Img->h, Img->format->BitsPerPixel));\n\treturn Img;\n}\n\n// This code seems dirty... but I don't have enough experience with SDL & OpenGL\n// on both architecture endiannesses to optimize it.\nbool LoadImgIntoTexture(SDL_Surface *Img) {\n\tint format, type, internalformat, pitchpix=0, remainder=0;\n\tSDL_PixelFormat *fmt= Img->format;\n\t#if SDL_BYTEORDER == SDL_BIG_ENDIAN\n\tif (fmt->Rmask == 0xFF000000 && fmt->Gmask == 0x00FF0000 && fmt->Bmask == 0x0000FF00) {\n\t#else\n\tif (fmt->Rmask == 0x000000FF && fmt->Gmask == 0x0000FF00 && fmt->Bmask == 0x00FF0000) {\n\t#endif\n\t\tformat= fmt->Amask? GL_RGBA : GL_RGB;\n\t\tinternalformat= format;\n\t\ttype= GL_UNSIGNED_BYTE;\n\t\tDEBUGMSG((\"Image seems to be %s/GL_UNSIGNED_BYTE\\n\", format==GL_RGBA?\"GL_RGBA\":\"GL_RGB\"));\n\t}\n\t#if SDL_BYTEORDER == SDL_BIG_ENDIAN\n\telse if (fmt->Bmask == 0xFF000000 && fmt->Gmask == 0x00FF0000 && fmt->Rmask == 0x0000FF00) {\n\t#else\n\telse if (fmt->Bmask == 0x000000FF && fmt->Gmask == 0x0000FF00 && fmt->Rmask == 0x00FF0000) {\n\t#endif\n\t\tformat= fmt->Amask? GL_BGRA : GL_BGR;\n\t\tinternalformat= format;\n\t\ttype= GL_UNSIGNED_BYTE;\n\t\tDEBUGMSG((\"Image seems to be %s/GL_UNSIGNED_BYTE\\n\", format==GL_BGRA?\"GL_BGRA\":\"GL_BGR\"));\n\t}\n\telse {\n\t\t// I don't want to implement the rest until I actually have some way to test it.\n\t\t// Really, I haven't even tested anything other than BGR.\n\t\tfprintf(stderr, \"Currently the only supported formats are BGR(A) or RGB(A).\\n\");\n\t\treturn false;\n\t}\n\t\n\t// This should probably never happen, since dimensions are powers of two, but just in case...\n\tif (Img->pitch != Img->w * Img->format->BytesPerPixel) {\n\t\tpitchpix= Img->pitch / Img->format->BytesPerPixel;\n\t\tremainder= Img->pitch % Img->format->BytesPerPixel;\n\t\tglPixelStorei(GL_UNPACK_ROW_LENGTH, pitchpix);\n\t\tif (remainder)\n\t\t\tglPixelStorei(GL_UNPACK_ALIGNMENT, 1+(remainder|(remainder>>1)|(remainder>>2)));\n\t}\n\tglTexImage2D(GL_TEXTURE_2D, 0, internalformat, Img->w, Img->h, 0, format, type, Img->pixels);\n\t// Restore defaults\n\tif (pitchpix)  glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);\n\tif (remainder) glPixelStorei(GL_UNPACK_ALIGNMENT, 1);\n\treturn true;\n}\n\n/*=head2 Texture Commands\n\n=item cglLoadImage2D \"FILE_PATH\"\n\nLoad image data into the texture currently bound to GL_TEXTURE_2D.  If compiled with support\nfor the SDL_image library, you may supply any image format handled by that library, else you\nare limited to Windows Bitmaps \".BMP\".  The image must contain RGB or RGBA pixels.\n\n=cut */\n\nCOMMAND(cglLoadImage2D, \"/\") {\n\tint success;\n\tSDL_Surface *Img;\n\n\tif (!(Img= LoadImg(parsed->strings[0])))\n\t\treturn false;\n\t// Then, load the image data into OpenGL\n\tSDL_LockSurface(Img);\n\tsuccess= LoadImgIntoTexture(Img);\n\tSDL_UnlockSurface(Img);\n\tSDL_FreeSurface(Img);\n\treturn success;\n}\n\n"
  },
  {
    "path": "src/ImageLoader.h",
    "content": "#ifndef IMAGE_LOADER_H\n#define IMAGE_LOADER_H\n\n#endif\n"
  },
  {
    "path": "src/ParseGL.c",
    "content": "#define INCLUDE_GL\n#include <config.h>\n#include \"Global.h\"\n#include \"ParseGL.h\"\n#include \"Server.h\"\n#include \"SymbolHash.h\"\n#include \"ImageLoader.h\"\n#include \"Font.h\"\n\nbool PointsInProgress= false; // Whenever glBegin is active, until glEnd\nbool FrameInProgress= false;  // True after any gl command, until cglSwapBuffers\n\n/*=head2 GL Setup Commands\n\n=item glEnable FEATURE [FEATURE...]\n\nEnable one or more GL feature bits.\n\n=item glDisable FEATURE [FEATURE...]\n\nDisable one or more GL feature bits.\n\n=item glHint TARGET MODE\n\nAdjust GL optional behavior.\n\n=item glBlendFunc SOURCE_FACTOR DEST_FACTOR\n\nControl how new pixel colors are blended into the existing frame buffer.  SOURCE_FACTOR and\nDEST_FACTOR each an enum constant describing the equation used.\n\n=item glShadeModel GL_SMOOTH|GL_FLAT\n\nControl whether lighting is calculated per-pixel or per-vertex.\n\n=cut */\n\nCOMMAND(glEnable, \"i*\") {\n\twhile (parsed->iCnt > 0)\n\t\tglEnable(parsed->ints[--parsed->iCnt]);\n\treturn true;\n}\n\nCOMMAND(glDisable, \"i*\") {\n\twhile (parsed->iCnt > 0)\n\t\tglDisable(parsed->ints[--parsed->iCnt]);\n\treturn true;\n}\n\nCOMMAND(glHint, \"ii\") {\n\tglHint(parsed->ints[0], parsed->ints[1]);\n\treturn true;\n}\n\nCOMMAND(glBlendFunc, \"ii\") {\n\tglBlendFunc(parsed->ints[0], parsed->ints[1]);\n\treturn true;\n}\n\nCOMMAND(glShadeModel, \"i\") {\n\tglShadeModel(parsed->ints[0]);\n\treturn true;\n}\n\n/*=head2 GL Lighting Setup Commands\n\nThese settings affect the overall lighting calculation\n\n=item glColorMaterial FACE MODE\n\nSet one or both faces of polygons to use the current color as one or more color components of\nthe \"material\" in the lighting equation.  FACE is: GL_FRONT, GL_BACK, GL_FRONT_AND_BACK, and\nMODE is: GL_EMISSION, GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR, GL_AMBIENT_AND_DIFFUSE.\n\n=item glFog PNAME [PARAMS...]\n\nApply a fog setting.  PNAME selects which value to change, and PARAMS depends on PNAME.\nIf PNAME is a color, you may use HTML color notation.  See L</Colors>.\n\n=item glLightModel PNAME [PARAMS...]\n\nApply a lighting setting.  PNAME is the setting to change, and PARAMS depend on PNAME.  If the\nPARAMS are a color, you may use HTML color notation.  See L</Colors>.\n\n=item glLight LIGHT PNAME [PARAMS...]\n\nApply a per-light setting.  LIGHT is the enum or number of the light to be altered, and PNAME\nselects which parameter to change.  PARAMS depends on PNAME. If PARAMS is a color, you may use\nHTML color notation.  See L</Colors>.\n\n=cut */\n\nCOMMAND(glColorMaterial, \"ii\") {\n\tglColorMaterial(parsed->ints[0], parsed->ints[1]);\n\treturn true;\n}\n\nCOMMAND(glFog, \"ib\") {\n\tint mode= parsed->ints[0];\n\n\t// The parameter to this one really matters, since floats get fixed-point\n\t//  multiplied, and colors need special treatment.\n\tswitch (mode) {\n\tcase GL_FOG_MODE:\n\tcase GL_FOG_INDEX:\n\t\tif (!ParseParams(&parsed->strings[0], \"i\", parsed))\n\t\t\treturn false;\n\t\tglFogi(mode, parsed->ints[1]);\n\t\treturn true;\n\tcase GL_FOG_DENSITY:\n\tcase GL_FOG_START:\n\tcase GL_FOG_END:\n\t\tif (!ParseParams(&parsed->strings[0], \"f\", parsed))\n\t\t\treturn false;\n\t\tglFogf(mode, parsed->floats[0]);\n\t\treturn true;\n\tcase GL_FOG_COLOR:\n\t\tif (!ParseParams(&parsed->strings[0], \"c\", parsed))\n\t\t\treturn false;\n\t\tglFogfv(mode, parsed->floats);\n\t\treturn true;\n\tdefault:\n\t\tsnprintf(parsed->errmsg_buf, sizeof(parsed->errmsg_buf), \"Unsupported mode constant for glFog: %d\", mode);\n\t\tparsed->errmsg= parsed->errmsg_buf;\n\t}\n\treturn false;\n}\n\nCOMMAND(glLightModel, \"ib\") {\n\tint pname= parsed->ints[0];\n\n\tswitch (pname) {\n\tcase GL_LIGHT_MODEL_AMBIENT:\n\t\tif (!ParseParams(&parsed->strings[0], \"c\", parsed))\n\t\t\treturn false;\n\t\tglLightModelfv(pname, parsed->floats);\n\t\treturn true;\n\t#ifdef GL_LIGHT_MODEL_COLOR_CONTROL\n\tcase GL_LIGHT_MODEL_COLOR_CONTROL:\n\t#endif\n\tcase GL_LIGHT_MODEL_LOCAL_VIEWER:\n\tcase GL_LIGHT_MODEL_TWO_SIDE:\n\t\tif (!ParseParams(&parsed->strings[0], \"i\", parsed))\n\t\t\treturn false;\n\t\tglLightModeliv(pname, parsed->ints+1);\n\t\treturn true;\n\tdefault:\n\t\tsnprintf(parsed->errmsg_buf, sizeof(parsed->errmsg_buf), \"Unsupported pname constant for glLightModel: %d\", pname);\n\t\tparsed->errmsg= parsed->errmsg_buf;\n\t}\n\treturn false;\n}\n\nCOMMAND(glLight, \"iib\") {\n\tint light= parsed->ints[0], pname= parsed->ints[1];\n\n\tswitch (pname) {\n\tcase GL_AMBIENT:\n\tcase GL_DIFFUSE:\n\tcase GL_SPECULAR:\n\t\tif (!ParseParams(&parsed->strings[0], \"c\", parsed))\n\t\t\treturn false;\n\t\tassert(parsed->fCnt == 4);\n\t\tbreak;\n\tcase GL_POSITION:\n\t#ifdef GL_SPOT_DIRECTION\n\tcase GL_SPOT_DIRECTION:\n\t#endif\n\t\tif (!ParseParams(&parsed->strings[0], \"ffff?\", parsed))\n\t\t\treturn false;\n\t\tassert(parsed->fCnt >= 3 && parsed->fCnt <= 4);\n\t\tbreak;\n\t#ifdef GL_SPOT_EXPONENT\n\tcase GL_SPOT_EXPONENT:\n\tcase GL_SPOT_CUTOFF:\n\t#endif\n\t#ifdef GL_CONSTANT_ATTENUATION\n\tcase GL_CONSTANT_ATTENUATION:\n\tcase GL_LINEAR_ATTENUATION:\n\tcase GL_QUADRATIC_ATTENUATION:\n\t#endif\n\t\tif (!ParseParams(&parsed->strings[0], \"f\", parsed))\n\t\t\treturn false;\n\t\tassert(parsed->fCnt == 1);\n\t\tbreak;\n\tdefault:\n\t\tsnprintf(parsed->errmsg_buf, sizeof(parsed->errmsg_buf), \"Unsupported pname constant for glLight: %d\", pname);\n\t\tparsed->errmsg= parsed->errmsg_buf;\n\t\treturn false;\n\t}\n\tglLightfv(light, pname, parsed->floats);\n\treturn true;\n}\n\n/*=head2 Render Loop Commands\n\n=item glClear ENUM [ENUM...]\n\nClear one or more aspects of the frame buffer.  Normally the constants are combined as a bit\nmask, but for this protocol they are just given as multiple arguments.\n\n=item glClearColor COLOR | R G B [A]\n\nSpecify what color to use when clearing the frame buffer.  You may use a single HTML-style\ncolor code, or individual floating point components.  See L</Colors>\n\n=item glClearDepth DEPTH\n\nSelect what depth to assign when clearing the depth buffer.\n\n=item glFlush\n\nPush any un-written commands through to the graphics layer.\n\n=cut */\nCOMMAND(glClear, \"i*\") {\n\tint flags= 0;\n\twhile (parsed->iCnt > 0)\n\t\tflags|= parsed->ints[--parsed->iCnt];\n\tglClear(flags);\n\tFrameInProgress= true;\n\treturn true;\n}\n\nCOMMAND(glClearColor, \"c\") {\n\tglClearColor(parsed->floats[0], parsed->floats[1], parsed->floats[2], parsed->floats[3]);\n\treturn true;\n}\n\nCOMMAND(glClearDepth, \"d\") {\n\tglClearDepth(parsed->doubles[0]);\n\treturn true;\n}\n\nCOMMAND(glFlush, \"\") {\n\tglFlush();\n\treturn true;\n}\n\n/*=head2 Geometry Plotting Commands\n\n=item glBegin MODE\n\nBegin plotting points of geometry type MODE.\n\n=item glEnd\n\nStop plotting points.\n\n=item glVertex X Y [Z] [w]\n\nPlot a vertex at (X,Y), (X,Y,Z), or (X,Y,Z,W)\n\n=item glNormal X Y Z\n\nSpecify the Normal vector for the next Vertex.\n\n=item glTexCoord S T [R] [Q]\n\nSpecify texture coordinates to use for the next Vertex.\n\n=item glColor COLORCODE | R G B [A]\n\nSpecify a color value to be used in the calculation of the color for the next vertex.\nThe color may be specified in HTML notation or as separate components.  See L</Colors>.\n\n=item glMaterial FACE PNAME [PARAMS...]\n\nApply a Material property that affects how future vertices will be affected by various lighting\nparameters.  See OpenGL documentation for details, but FACE and PNAME should be symbolic\nconstants, and PARAMS depends on PNAME.  If PARAMS are a color, you may use HTML notation.\nSee L</Colors>.\n\n=cut */\n\nCOMMAND(glBegin, \"i\") {\n\tif (PointsInProgress) {\n\t\tparsed->errmsg= \"multiple calls to glBegin without glEnd\";\n\t\treturn false;\n\t}\n\tglBegin(parsed->ints[0]);\n\tPointsInProgress= true;\n\tFrameInProgress= true;\n\treturn true;\n}\n\nCOMMAND(glEnd, \"\") {\n\tif (!PointsInProgress) {\n\t\tparsed->errmsg= \"glEnd without glBegin\";\n\t\treturn false;\n\t}\n\tglEnd();\n\tPointsInProgress= false;\n\treturn true;\n}\n\nCOMMAND(glVertex, \"ddd?d?\") {\n\tswitch (parsed->dCnt) {\n\tcase 2: glVertex2dv(parsed->doubles); break;\n\tcase 3: glVertex3dv(parsed->doubles); break;\n\tcase 4: glVertex4dv(parsed->doubles); break;\n\tdefault:\n\t\treturn false;\n\t}\n\treturn true;\n}\n\nCOMMAND(glNormal, \"ddd\") {\n\tglNormal3dv(parsed->doubles);\n\treturn true;\n}\n\nCOMMAND(glTexCoord, \"dd?d?d?\") {\n\tassert( parsed->dCnt >= 1 && parsed->dCnt <= 4 );\n\tswitch (parsed->dCnt) {\n\tcase 1: glTexCoord1dv(parsed->doubles); break;\n\tcase 2: glTexCoord2dv(parsed->doubles); break;\n\tcase 3: glTexCoord3dv(parsed->doubles); break;\n\tcase 4: glTexCoord4dv(parsed->doubles); break;\n\t}\n\treturn true;\n}\n\nCOMMAND(glColor, \"c\") {\n\tglColor4fv(parsed->floats);\n\treturn true;\n}\n\nCOMMAND(glMaterial, \"iib\") {\n\tint face= parsed->ints[0], pname= parsed->ints[1];\n\t\n\tswitch (pname) {\n\tcase GL_COLOR_INDEXES:\n\t\tif (!ParseParams(&parsed->strings[0], \"iii\", parsed))\n\t\t\treturn false;\n\t\tglMaterialiv(face, pname, parsed->ints+2);\n\t\treturn true;\n\tcase GL_AMBIENT:\n\tcase GL_DIFFUSE:\n\tcase GL_AMBIENT_AND_DIFFUSE:\n\tcase GL_SPECULAR:\n\tcase GL_EMISSION:\n\t\tif (!ParseParams(&parsed->strings[0], \"c\", parsed))\n\t\t\treturn false;\n\t\tglMaterialfv(face, pname, parsed->floats);\n\t\treturn true;\n\tcase GL_SHININESS:\n\t\tif (!ParseParams(&parsed->strings[0], \"f\", parsed))\n\t\t\treturn false;\n\t\tglMaterialfv(face, pname, parsed->floats);\n\t\treturn true;\n\tdefault:\n\t\tsnprintf(parsed->errmsg_buf, sizeof(parsed->errmsg_buf), \"Unsupported pname constant for glMaterial: %d\", pname);\n\t\tparsed->errmsg= parsed->errmsg_buf;\n\t}\n\treturn false;\n}\n\n/*=head2 Texture Commands\n\n=item glBindTextue TARGET TEXTURENAME\n\nSelect the current texture object for purpose TARGET.  (TARGET is usually GL_TEXTURE_2D)\n\n=item glTexParameter TARGET PNAME [PARAMS...]\n\nChange an attribute of the texture object currently bount to TARGET.  PNAME is the name of\nthe attribute, and PARAMS depend on PNAME.  If PARAMS is a color, you may use HTML hex\nnotation; see L</Colors>.\n\n=cut */\n\nCOMMAND(glBindTexture, \"iT!\") {\n\tglBindTexture(parsed->ints[0], parsed->objects[0]->Value);\n\treturn true;\n}\nCOMMAND(glTexParameter, \"iib\") {\n\tint target= parsed->ints[0], pname= parsed->ints[1];\n\t\n\tswitch (pname) {\n\t/* one enum */\n\tcase GL_TEXTURE_MIN_FILTER:\n\tcase GL_TEXTURE_MAG_FILTER:\n\tcase GL_TEXTURE_WRAP_S:\n\tcase GL_TEXTURE_WRAP_T:\n\tcase GL_TEXTURE_WRAP_R:\n\t#ifdef GL_TEXTURE_COMPARE_MODE\n\tcase GL_TEXTURE_COMPARE_MODE:\n\tcase GL_TEXTURE_COMPARE_FUNC:\n\tcase GL_DEPTH_TEXTURE_MODE:\n\tcase GL_GENERATE_MIPMAP:\n\t#endif\n\t/* one integer */\n\tcase GL_TEXTURE_BASE_LEVEL:\n\tcase GL_TEXTURE_MAX_LEVEL:\n\t\tif (!ParseParams(&parsed->strings[0], \"i\", parsed))\n\t\t\treturn false;\n\t\tglTexParameteri(target, pname, parsed->ints[2]);\n\t\treturn true;\n\n\t/* one float */\n\t#ifdef GL_TEXTURE_MIN_LOD\n\tcase GL_TEXTURE_MIN_LOD:\n\tcase GL_TEXTURE_MAX_LOD:\n\t#endif\n\tcase GL_TEXTURE_PRIORITY:\n\t\tif (!ParseParams(&parsed->strings[0], \"f\", parsed))\n\t\t\treturn false;\n\t\tglTexParameterf(target, pname, parsed->floats[0]);\n\t\treturn true;\n\n\t/* one color */\n\tcase GL_TEXTURE_BORDER_COLOR:\n\t\tif (!ParseParams(&parsed->strings[0], \"c\", parsed))\n\t\t\treturn false;\n\t\tglTexParameterfv(target, pname, parsed->floats);\n\t\treturn true;\n\tdefault:\n\t\tsnprintf(parsed->errmsg_buf, sizeof(parsed->errmsg_buf), \"Unsupported pname constant for glTexparameter: %d\", pname);\n\t\tparsed->errmsg= parsed->errmsg_buf;\n\t}\n\treturn false;\n}\n\n/*=head2 Matrix Commands\n\n=item glMatrixMode MODE\n\nSelect which matrix stack will be affected by future matrix commands.\n\n=item glPushMatrix\n\nSave a copy of the current matrix onto the current matrix stack.\n\n=item glPopMatrix\n\nRestore the previous saved matrix.\n\n=item glLoadIdentity\n\nOverwrite the current matrix with a matrix that has no effect on vertices.\n\n=item glLoadMatrix I1 I2 I3 I4 J1 J2 J3 J4 K1 K2 K3 K4 L1 L2 L3 L4\n\nDirectly overwrite the matrix with 16 values.\n\n=item glMultMatrix I1 I2 I3 I4 J1 J2 J3 J4 K1 K2 K3 K4 L1 L2 L3 L4\n\nMultiply the current matrix by this specified matrix\n\n=item glScale SCALE [SCALE_Y [SCALE_Z]]\n\nWhen given one argument, scale the X, Y, and Z axis by the specified value.\nWhen given two arguments, scale X and Y, leaving Z unchanged.\nWhen given three arguments,scale X, Y, and Z.\n\n=item glTranslate X Y [Z]\n\nApply a translation to the matrix.  The Z coordinate is optional and\ndefaults to 0.\n\n=item glRotate DEGREES X Y Z\n\nRotate DEGREES around the axis defined by (X,Y,Z)\n\n=item gluLookAt EYE_X EYE_Y EYE_Z CENTER_X CENTER_Y CENTER_Z UP_X UP_Y UP_Z\n\nChange the current matrix to \"look at\" CENTER from EYE.\n\n=item glViewport X Y WIDTH HEIGHT\n\nDefine the 2D region of the screen to be rendered by the current matrix.\n\n=item glOrtho\n\nSet up a projection matrix that maps the given coordinate values to the\nedges of the viewport, and sets the near and far clipping plane.\n\n=item glFrustum\n\nSet up a projection matrix where the given coordinates are the edges of the\nscreen B<at> the near clipping plane, and scale proportionally as the Z\ncoordinate gets farther from the near plane.\n\n=cut */\n\nCOMMAND(glMatrixMode, \"i\") {\n\tglMatrixMode((GLint) parsed->ints[0]);\n\treturn true;\n}\nCOMMAND(glPushMatrix, \"\") {\n\tglPushMatrix();\n\treturn true;\n}\nCOMMAND(glPopMatrix, \"\") {\n\tglPopMatrix();\n\treturn true;\n}\nCOMMAND(glLoadIdentity, \"\") {\n\tglLoadIdentity();\n\treturn true;\n}\nCOMMAND(glLoadMatrix, \"dddddddddddddddd\") {\n\tglLoadMatrixd(parsed->doubles);\n\treturn true;\n}\nCOMMAND(glMultMatrix, \"dddddddddddddddd\") {\n\tglMultMatrixd(parsed->doubles);\n\treturn true;\n}\nCOMMAND(glScale, \"dd?d?\") {\n\tassert( parsed->dCnt >= 1 && parsed->dCnt <= 3 );\n\tif (parsed->dCnt == 1)\n\t\tparsed->doubles[2]= parsed->doubles[1]= parsed->doubles[0];\n\telse if (parsed->dCnt == 2)\n\t\tparsed->doubles[2]= 1.0;\n\tglScaled(parsed->doubles[0], parsed->doubles[1], parsed->doubles[2]);\n\treturn true;\n}\nCOMMAND(glTranslate, \"ddd?\") {\n\tassert( parsed->dCnt >= 2 && parsed->dCnt <= 3 );\n\tif (parsed->dCnt == 2) parsed->doubles[2]= 0.0;\n\tglTranslated(parsed->doubles[0], parsed->doubles[1], parsed->doubles[2]);\n\treturn true;\n}\nCOMMAND(glRotate, \"dddd\") {\n\tglRotated(parsed->doubles[0], parsed->doubles[1], parsed->doubles[2], parsed->doubles[3]);\n\treturn true;\n}\n\nCOMMAND(glViewport, \"iiii\") {\n\tglViewport(parsed->ints[0], parsed->ints[1], parsed->ints[2], parsed->ints[3]);\n\treturn true;\n}\nCOMMAND(glOrtho, \"dddddd\") {\n\tglOrtho(parsed->doubles[0], parsed->doubles[1], parsed->doubles[2], parsed->doubles[3], parsed->doubles[4], parsed->doubles[5]);\n\treturn true;\n}\nCOMMAND(glFrustum, \"dddddd\") {\n\tglFrustum(parsed->doubles[0], parsed->doubles[1], parsed->doubles[2],\n\t          parsed->doubles[3], parsed->doubles[4], parsed->doubles[5]);\n\treturn true;\n}\n\n/*=head2 Display List Commands\n\n=item glNewList LISTNAME MODE\n\nBegin recording a new display list, either creating or overwriting LISTNAME.\nMODE can either be GL_COMPILE or GL_COMPILE_AND_EXECUTE.  LISTNAME can be any\nstring of text and is not limited to OpenGL's integer \"names\".\n\n=item glEndList\n\nEnd the recording.\n\n=item glCallList LISTNAME\n\nReplay a recorded list.\n\n=cut */\n\nCOMMAND(glNewList, \"L!i\") {\n\tglNewList(parsed->objects[0]->Value, parsed->ints[0]);\n\treturn true;\n}\nCOMMAND(glEndList, \"\") {\n\tglEndList();\n\treturn true;\n}\nCOMMAND(glCallList, \"L\") {\n\tglCallList(parsed->objects[0]->Value);\n\treturn true;\n}\n\n/*=head2 Quadric Commands\n\n=item gluNewQuadric NAME\n\nQuadric objects must be created before they can be used.\n\n=item gluQuadricDrawStyle NAME DRAW\n\nSet the DRAW style of the NAMEd quadric: GLU_FILL, GLU_LINE, GLU_SILHOUETTE, GLU_POINT\n\n=item gluQuadricNormals NAME NORMAL\n\nSet the type of NORMALs to calculate when using the NAMEd quadric: GLU_NONE, GLU_FLAT, GLU_SMOOTH\n\n=item gluQuadricOrientation NAME ORIENTATION\n\nSet the in/out ORIENTATION of polygons when using the NAMEd quadric: GLU_OUTSIDE, GLU_INSIDE\n\n=item gluQuadricTexture NAME MODE\n\nSet whether or not to generate texture coordinates when drawing with the NAMEd quadric: GLU_TRUE, GLU_FALSE\n\n=item gluCylinder NAME BASE TOP HEIGHT SLICES STACKS\n\nDraw a cylinder (or cone) with BASE radius at z=0 and TOP radius at z=height, traveling HEIGHT\ndistance on the Z axis, composed of n=SLICES polygons radially around the body and n=STACKS\npolygons along the height.  NAME selects a set of quadric parameters for the polygons.\n\n=item gluSphere NAME RADIUS SLICES STACKS\n\nDraw a sphere of RADIUS around the origin, composed of n=SLICES polygons radially around the\nZ axis and n=STACKS polygons along the z axis.\n\n=item gluDisk NAME INNER OUTER SLICES LOOPS\n\nDraw a flat disk (C<inner = 0>) or donought (C<<inner > 0>>) around the Z axis with the given\nOUTER radius and INNER radius, composed of SLICES polygons radially around Z and LOOPS\nconcentric rings.\n\n=item gluPartialDisk NAME INNER OUTER SLICES LOOPS START SWEEP\n\nSame as above, but only from START degrees around Z axis until and SWEEP degrees afterward.\n\n=cut */\n\nCOMMAND(gluLookAt, \"ddddddddd\") {\n\tgluLookAt(\n\t\tparsed->doubles[0], parsed->doubles[1], parsed->doubles[2],\n\t\tparsed->doubles[3], parsed->doubles[4], parsed->doubles[5],\n\t\tparsed->doubles[6], parsed->doubles[7], parsed->doubles[8]\n\t);\n\treturn true;\n}\nCOMMAND(gluNewQuadric, \"Q!\") {\n\t/* auto-create handled by ParseParams */\n\treturn true;\n}\nCOMMAND(gluQuadricDrawStyle, \"Qi\") {\n\tgluQuadricDrawStyle((GLUquadric*) parsed->objects[0]->Data, parsed->ints[0]);\n\treturn true;\n}\nCOMMAND(gluQuadricNormals, \"Qi\") {\n\tgluQuadricNormals((GLUquadric*) parsed->objects[0]->Data, parsed->ints[0]);\n\treturn true;\n}\nCOMMAND(gluQuadricOrientation, \"Qi\") {\n\tgluQuadricOrientation((GLUquadric*) parsed->objects[0]->Data, parsed->ints[0]);\n\treturn true;\n}\nCOMMAND(gluQuadricTexture, \"Qi\") {\n\tgluQuadricTexture((GLUquadric*) parsed->objects[0]->Data, parsed->ints[0]);\n\treturn true;\n}\nCOMMAND(gluCylinder, \"Qdddii\") {\n\tgluCylinder((GLUquadric*) parsed->objects[0]->Data,\n\t\tparsed->doubles[0], parsed->doubles[1], parsed->doubles[2],\n\t\tparsed->ints[0], parsed->ints[1]);\n\tFrameInProgress= true;\n\treturn true;\n}\nCOMMAND(gluSphere, \"Qdii\") {\n\tgluSphere((GLUquadric*) parsed->objects[0]->Data, parsed->doubles[0],\n\t\tparsed->ints[0], parsed->ints[1]);\n\tFrameInProgress= true;\n\treturn true;\n}\nCOMMAND(gluDisk, \"Qddii\") {\n\tgluDisk((GLUquadric*) parsed->objects[0]->Data, parsed->doubles[0], parsed->doubles[1],\n\t\tparsed->ints[0], parsed->ints[1]);\n\tFrameInProgress= true;\n\treturn true;\n}\nCOMMAND(gluPartialDisk, \"Qddiidd\") {\n\tgluPartialDisk((GLUquadric*) parsed->objects[0]->Data, parsed->doubles[0], parsed->doubles[1],\n\t\tparsed->ints[0], parsed->ints[1], parsed->doubles[2], parsed->doubles[3]);\n\tFrameInProgress= true;\n\treturn true;\n}\n"
  },
  {
    "path": "src/ParseGL.h",
    "content": "#ifndef PARSEGL_H\n#define PARSEGL_H\n\n#include \"Global.h\"\n\nextern bool PointsInProgress; // Whenever glBegin is active, until glEnd\nextern bool FrameInProgress;  // True after any gl command, until cglSwapBuffers\n\n#endif\n"
  },
  {
    "path": "src/ProcessInput.c",
    "content": "#define INCLUDE_GL\n#include <config.h>\n\n#include \"ProcessInput.h\"\n#include \"ParseGL.h\"\n#include \"SymbolHash.h\"\n\n#define READ_BUFFER_SIZE 1024\n\n/* CmdlineGL supports fixed-point numbers on stdin, by multiplying\n * all float values by this multiplier.  Naturally, it defaults to 1.0\n */\ndouble FixedPtMultiplier= 1.0;\ndouble DivisorStack[16];\nint DivisorStackPos= -1;\nconst int DivisorStackMax= sizeof(DivisorStack)/sizeof(double) - 1;\n\n/*=head2 Default-Divisor Commands\n\n=item cglPushDivisor DIVISOR\n\nAll future floating-point numbers receive this implied \"/DIVISOR\".\nThis does not replace a divisor that is manually specified.\n\nFor example,\n\n    cglPushDivisor 100\n    glRotate 12/1 100 100 100\n\nbecomes\n\n    glRotated(12, 1, 1, 1);\n\n=item cglPopDivisor\n\nClear the current default  divisor, returning to whatever default\nwas set before that.  The initial default is 1.\n\n=cut*/\n\nCOMMAND(cglPushDivisor, \"t\") {\n\tchar *EndPtr;\n\tdouble newval;\n\tif (DivisorStackPos >= DivisorStackMax) {\n\t\tparsed->errmsg= \"divisor stack overflow\";\n\t\treturn false;\n\t}\n\t// We don't want to scale the new scale... so don't use ParseParams(\"d\").\n\tnewval= strtod(parsed->strings[0], &EndPtr);\n\tif (*EndPtr != '\\0') {\n\t\tparsed->errmsg= \"expected Float\";\n\t\treturn false;\n\t}\n\tDivisorStack[++DivisorStackPos]= newval;\n\tFixedPtMultiplier= 1.0 / newval;\n\treturn true;\n}\n\nCOMMAND(cglPopDivisor, \"\") {\n\tif (DivisorStackPos < 0)  {\n\t\tparsed->errmsg= \"divisor stack underflow\";\n\t\treturn false;\n\t}\n\tFixedPtMultiplier= (--DivisorStackPos >= 0)? 1.0 / DivisorStack[DivisorStackPos] : 1.0;\n\treturn true;\n}\n\n/* Below is \"class LineBuffer\".\n * I had to write my own because I wanted a readline function that wouldn't\n * block, and wouldn't return a partial string.\n *\n * There's only one used in the whole prog, and I see it staying that way, so I\n * 'optimized' a bit by making it global.\n *\n * If it ever becomes necessary to make more than one, uncomment and propogate.\n * Also, it will then be necessary to make a constructor function, and call it\n * before each gets used the first time.\n */\n//typedef struct LineBuffer_t {\n\tchar ReadBuffer[READ_BUFFER_SIZE];\n\tchar const *StopPos;\n\tchar *Pos;\n\tchar *DataPos;\n\tchar *LineStart;\n\t#ifndef _WIN32\n\tint fd;\n\t#else\n\tHANDLE fd;\n\t#endif\n//} LineBuffer;\n\n#ifndef _WIN32\nvoid InitLineBuffer(int FileHandle /*, LineBuffer *this */) {\n#else\nvoid InitLineBuffer(HANDLE FileHandle /*, LineBuffer *this */) {\n#endif\n\tfd= FileHandle;\n\tStopPos= ReadBuffer+READ_BUFFER_SIZE;\n\tPos= ReadBuffer;\n\tDataPos= ReadBuffer;\n\tLineStart= ReadBuffer;\n}\n\nvoid ShiftBuffer(/* LineBuffer *this */) {\n\tint shift= LineStart - ReadBuffer;\n\tif (DataPos != LineStart)\n\t\tmemmove(ReadBuffer, LineStart, DataPos - LineStart);\n\tDataPos-= shift;\n\tPos-= shift;\n\tLineStart= ReadBuffer;\n}\n\nchar* ReadLine(/* LineBuffer *this */) {\n\tint red;\n\tchar *Result;\n\n\tif (LineStart != ReadBuffer && DataPos - LineStart < 16)\n\t\tShiftBuffer();\n\tdo {\n\t\t// do we need more?\n\t\tif (Pos == DataPos) {\n\t\t\t// do we need to shift?\n\t\t\tif (DataPos == StopPos) {\n\t\t\t\t// can we shift?\n\t\t\t\tif (LineStart != ReadBuffer)\n\t\t\t\t\tShiftBuffer();\n\t\t\t\telse {\n\t\t\t\t\t// Full buffer.  Abort, and reset the buffer pointers.\n\t\t\t\t\tLineStart= DataPos= Pos= ReadBuffer;\n\t\t\t\t\tfprintf(stderr, \"Input line too long\\n\");\n\t\t\t\t\treturn NULL;\n\t\t\t\t}\n\t\t\t}\n\t\t\t#ifndef _WIN32\n\t\t\tred= read(fd, DataPos, StopPos-DataPos);\n\t\t\tif (red <= 0)\n\t\t\t\treturn NULL;\n\t\t\t#else\n\t\t\t// no non-blocking mode, so we need to test the status of the object\n\t\t\tif (WaitForSingleObject(fd, 0) == WAIT_OBJECT_0)\n\t\t\t\tsuccess= ReadFile(fd, DataPos, StopPos-DataPos, &red, NULL);\n\t\t\telse\n\t\t\t\treturn NULL;\n\t\t\tif (!success || red<=0)\n\t\t\t\treturn NULL;\n\t\t\t#endif\n\t\t\tDataPos+= red;\n\t\t}\n\t\twhile (Pos < DataPos && *Pos != '\\n')\n\t\t\tPos++;\n\t} while (*Pos != '\\n');\n\t*Pos= '\\0';\n\tif (Pos > LineStart)\n\t\tif (Pos[-1] == '\\r')\n\t\t\tPos[-1]= 0;\n\tResult= LineStart;\n\tLineStart= ++Pos;\n\treturn Result;\n}\n\nchar * next_token(char **input) {\n\tchar q, *out, *in, *rewrite;\n\tif (!input) return NULL;\n\tin= *input;\n\t/* skip delim characters */\n\twhile (*in == ' ' || *in == '\\t') in++;\n\t/* quoting support */\n\tif (*in == '\\'' || *in == '\"') {\n\t\tq= *in++;\n\t\tout= rewrite= in;\n\t\twhile (*in && *in != q) {\n\t\t\tif (*in == '\\\\') {\n\t\t\t\tswitch (* ++in) {\n\t\t\t\tcase 'n': *in= '\\n'; break;\n\t\t\t\tcase 'r': *in= '\\r'; break;\n\t\t\t\tcase '\\0': --in; break; /* don't run over end of string */\n\t\t\t\tdefault: break; /* every other value remains itself */\n\t\t\t\t}\n\t\t\t}\n\t\t\t*rewrite++ = *in++;\n\t\t}\n\t\tif (*in) in++; /* advance past the end-quote, if not end of string */\n\t\t*rewrite= '\\0';\n\t\t/* always consider a token found, even if empty or missing end quote */\n\t}\n\t/* else just look for end of token */\n\telse {\n\t\tout= in;\n\t\twhile (*in && *in != ' ' && *in != '\\t') in++;\n\t\tif (*in) *in++= '\\0';\n\t\tif (!*out) out= NULL; /* return null unless found a token */\n\t}\n\twhile (*in == ' ' || *in == '\\t') in++;\n\t*input= in; /* give caller back the modified pointer */\n\treturn out;\n}\n\nchar *sanitize_for_print(char *string) {\n\tchar *c;\n\tfor (c= string; *c; c++)\n\t\tif (*c <= ' ' || *c == 0x7F)\n\t\t\t*c= '_';\n\treturn string;\n}\n\n/* ProcessCommand bites off the first word and dispatches to a command of that name.\n * It destroys \"Line\" with strtok in the process.\n */\nint ProcessCommand(char *Line) {\n\tconst CmdListEntry *Cmd;\n\tstruct ParseParamsResult parsed;\n\tint GLErr;\n\t\n\tparsed.iCnt= parsed.lCnt= parsed.fCnt= parsed.dCnt= parsed.sCnt= parsed.oCnt= 0;\n\tparsed.errmsg= NULL;\n\n\tchar *command= next_token(&Line);\n\t// Ignore blank lines or comments\n\tif (!command || !*command || *command == '#')\n\t\treturn P_IGNORE;\n\t\n\tCmd= GetCmd(command);\n\tsanitize_for_print(command);\n\tif (!Cmd) {\n\t\tfprintf(stderr, \"Unknown command: \\\"%s\\\".\\n\", command);\n\t\treturn P_NOT_FOUND;\n\t}\n\t\n\t/* use command's format string to parse each argument to the correct type */\n\tif (!ParseParams(&Line, Cmd->ArgFormat, &parsed)) {\n\t\tfprintf(stderr, \"Error parsing params of %s%s%s\\n\", command,\n\t\t\tparsed.errmsg? \": \":\"\\n\", parsed.errmsg? parsed.errmsg : \"\");\n\t\treturn P_CMD_ERR;\n\t}\n\t/* dispatch command. Command may return extra error info in errbuf */\n\tif (!Cmd->Handler(&parsed)) {\n\t\tfprintf(stderr, \"Error during execution of %s%s%s\\n\", command,\n\t\t\tparsed.errmsg? \": \":\"\\n\", parsed.errmsg? parsed.errmsg : \"\");\n\t\treturn P_CMD_ERR;\n\t}\n\t\n\t/* Check GL status, unless in the middle of begin/end */\n\tif (!PointsInProgress) {\n\t\tGLErr= glGetError();\n\t\tif (GLErr) { // command was successful\n\t\t\twhile (GLErr) {\n\t\t\t\tfprintf(stderr, \"GL error while executing %s: %s.\\n\", command, gluErrorString(GLErr));\n\t\t\t\tGLErr= glGetError();\n\t\t\t}\n\t\t\treturn P_CMD_ERR;\n\t\t}\n\t}\n\n\treturn P_SUCCESS;\n}\n\nSymbVarEntry* CreateNamedObj(const char* Name, int Type);\n\nbool ParseParams(char **line, const char *format, struct ParseParamsResult *parsed) {\n\tconst char *tok= \"\", *fmt_next;\n\tSymbVarEntry *obj;\n\tconst char *autocreate_name[sizeof(parsed->objects)/sizeof(parsed->objects[0])];\n\tint autocreate_type[sizeof(parsed->objects)/sizeof(parsed->objects[0])];\n\tint objtyp, autocreate= 0, optional= 0, repeat= 0, oCnt_start= parsed->oCnt, i;\n\t\n\twhile (*format) {\n\t\t//DEBUGMSG((\"Parse %s from \\\"%s\\\"\\n\", format, *line));\n\t\t/* parse out the next format specifier */\n\t\tfmt_next= format+1;\n\t\tautocreate= (*fmt_next == '!');\n\t\tif (autocreate) fmt_next++;\n\t\toptional= (*fmt_next == '?');\n\t\tif (optional) fmt_next++;\n\t\trepeat= (*fmt_next == '*');\n\t\tif (repeat) {\n\t\t\t++fmt_next;\n\t\t\t/* repeat must be end of list, otherwise no way to know how many it captured */\n\t\t\tassert(*fmt_next == '\\0');\n\t\t}\n\t\t\n\t\t/* if there is no input left to parse, consider 'optional' and return accordingly */\n\t\tif (!**line) {\n\t\t\tif (optional || repeat) break;\n\t\t\telse {\n\t\t\t\tparsed->errmsg= \"Not enough arguments\";\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\t\n\t\tswitch (*format) {\n\t\t// Integer value\n\t\tcase 'i': if (!ParseInt(line, parsed)) return false; break;\n\t\t//case 'l': if (!ParseLong(line, parsed)) return false; break;\n\t\t// Floating value\n\t\tcase 'f': if (!ParseFloat(line, parsed)) return false; break;\n\t\tcase 'd': if (!ParseDouble(line, parsed)) return false; break;\n\t\t// Color, either \"#xxxxxx\" or 3xFloat or 4xFloat (always stored as 4x float)\n\t\tcase 'c': if (!ParseColor(line, parsed)) return false; break;\n\t\t// Single Token string\n\t\tcase 't': if (!ParseToken(line, parsed)) return false; break;\n\t\t// remainder of buffer\n\t\tcase 'b': if (!CaptureRemainder(line, parsed)) return false; break;\n\t\t// string, either one token or rest of line if quoted\n\t\tcase 's':\n\t\t// File name, same as string but check that it exists\n\t\tcase '/':\n\t\t\tif (!(**line == '\"'? ParseToken(line, parsed) : CaptureRemainder(line, parsed)))\n\t\t\t\treturn false;\n\t\t\tassert(parsed->sCnt > 0);\n\t\t\ttok= parsed->strings[parsed->sCnt - 1];\n\t\t\tif (*format == '/' && !FileExists(tok)) {\n\t\t\t\tsnprintf(parsed->errmsg_buf, sizeof(parsed->errmsg_buf), \"No such file '%s'\", tok);\n\t\t\t\tparsed->errmsg= parsed->errmsg_buf;\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tbreak;\n\t\t// Display list\n\t\tif (0) case 'L': objtyp= NAMED_LIST;\n\t\t// Quadric\n\t\tif (0) case 'Q': objtyp= NAMED_QUADRIC;\n\t\t// Texture\n\t\tif (0) case 'T': objtyp= NAMED_TEXTURE;\n\t\t// Font\n\t\tif (0) case 'F': objtyp= NAMED_FONT;\n\t\t\t\n\t\t\tif (parsed->oCnt >= sizeof(parsed->objects)/sizeof(parsed->objects[0])) {\n\t\t\t\tparsed->errmsg= \"Argument count exceeded (object)\";\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\ttok= next_token(line);\n\t\t\tif (!tok || !*tok) {\n\t\t\t\tsnprintf(parsed->errmsg_buf, sizeof(parsed->errmsg_buf), \"Expected named %s\", SymbVarTypeName[objtyp]);\n\t\t\t\tparsed->errmsg= parsed->errmsg_buf;\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\telse if ((obj= GetSymbVar(tok, objtyp))) {\n\t\t\t\tparsed->objects[parsed->oCnt++]= obj;\n\t\t\t}\n\t\t\telse if (autocreate) {\n\t\t\t\t/* Doesn't exist.  If autocreate, wait until rest of parsing has succeeded.\n\t\t\t\t   Otherwise the handler won't get to see it, and could end up with dangling\n\t\t\t\t   NULL pointers in the variables tree for things like fonts. */\n\t\t\t\tautocreate_name[parsed->oCnt]= tok;\n\t\t\t\tautocreate_type[parsed->oCnt]= objtyp;\n\t\t\t\tparsed->objects[parsed->oCnt++]= NULL;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tsnprintf(parsed->errmsg_buf, sizeof(parsed->errmsg_buf), \"Named %s '%s' does not exist\",\n\t\t\t\t\tSymbVarTypeName[objtyp], tok);\n\t\t\t\tparsed->errmsg= parsed->errmsg_buf;\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tassert(0 == \"all formats handled\");\n\t\t\treturn false;\n\t\t}\n\t\t/* advance to next format specifier */\n\t\tif (!repeat) format= fmt_next;\n\t}\n\t/* all format specifiers have been satisfied.  Check for leftover input */\n\tif (**line) {\n\t\tparsed->errmsg= \"unpexpected extra arguments\";\n\t\treturn false;\n\t}\n\t/* Now, for any object that didn't exist and was marked autocreate, create it. */\n\tfor (i= oCnt_start; i < parsed->oCnt; i++) {\n\t\tif (!parsed->objects[i]) {\n\t\t\tassert(autocreate_type[i] >= 1 && autocreate_type[i] <= 4);\n\t\t\tassert(autocreate_name[i] != NULL && *autocreate_name[i]);\n\t\t\tparsed->objects[i]= CreateSymbVar(autocreate_name[i], autocreate_type[i]);\n\t\t\tswitch (autocreate_type[i]) {\n\t\t\tcase NAMED_LIST:    parsed->objects[i]->Value= glGenLists(1); break;\n\t\t\tcase NAMED_QUADRIC: parsed->objects[i]->Data= gluNewQuadric(); break;\n\t\t\tcase NAMED_TEXTURE: glGenTextures(1, (GLuint*) &(parsed->objects[i]->Value)); break;\n\t\t\t/* can't auto-create FTfont* object.  Caller needs to handle that. */\n\t\t\tdefault:            parsed->objects[i]->Data= NULL; break;\n\t\t\t}\n\t\t}\n\t}\n\treturn true;\n}\n\nbool ParseInt(char **line, struct ParseParamsResult *parsed) {\n\tconst IntConstListEntry *SymConst;\n\tchar *tok, *EndPtr;\n\tlong l;\n\n\tif (parsed->iCnt >= sizeof(parsed->ints)/sizeof(parsed->ints[0])) {\n\t\tparsed->errmsg= \"Argument count exceeded (int)\";\n\t\treturn false;\n\t}\n\tif (!(tok= next_token(line)) || !*tok) {\n\t\tparsed->errmsg= \"expected Integer\";\n\t\treturn false;\n\t}\n\t\n\tif (tok[0] >= '0' && tok[0] <= '9') {\n\t\tl= strtol(tok, &EndPtr, (tok[0] == '0' && tok[1] == 'x')? 16 : 10);\n\t\tif (*EndPtr == '\\0') {\n\t\t\tparsed->ints[parsed->iCnt++]= l;\n\t\t\treturn true;\n\t\t} else {\n\t\t\tsnprintf(parsed->errmsg_buf, sizeof(parsed->errmsg_buf), \"Can't parse int '%s'\", tok);\n\t\t\tparsed->errmsg= parsed->errmsg_buf;\n\t\t\treturn false;\n\t\t}\n\t}\n\telse {\n\t\t//DEBUGMSG((\"Searching for %s...\", tok));\n\t\tif ((SymConst= GetIntConst(tok))) {\n\t\t\t//DEBUGMSG((\" Found: %i\\n\", SymConst->Value));\n\t\t\tparsed->ints[parsed->iCnt++]= SymConst->Value;\n\t\t\treturn true;\n\t\t}\n\t\telse {\n\t\t\t//DEBUGMSG((\"not found.\\n\"));\n\t\t\tsnprintf(parsed->errmsg_buf, sizeof(parsed->errmsg_buf), \"Unknown constant '%s'\", tok);\n\t\t\tparsed->errmsg= parsed->errmsg_buf;\n\t\t\treturn false;\n\t\t}\n\t}\n}\n\nbool ParseFloat(char **line, struct ParseParamsResult *parsed) {\n\tif (parsed->fCnt >= sizeof(parsed->floats)/sizeof(parsed->floats[0])) {\n\t\tparsed->errmsg= \"Argument count exceeded (float)\";\n\t\treturn false;\n\t}\n\tif (!ParseDouble(line, parsed)) return false;\n\tparsed->floats[parsed->fCnt++]= parsed->doubles[--parsed->dCnt];\n\treturn true;\n}\n\nbool ParseDouble(char **line, struct ParseParamsResult *parsed) {\n\tchar *tok, *EndPtr;\n\tdouble num, denom;\n\t\n\tif (parsed->dCnt >= sizeof(parsed->doubles)/sizeof(parsed->doubles[0])) {\n\t\tparsed->errmsg= \"Argument count exceeded (double)\";\n\t\treturn false;\n\t}\n\tif (!(tok= next_token(line))) {\n\t\tparsed->errmsg= \"expected Float\";\n\t\treturn false;\n\t}\n\t/* ignore double negatives */\n\tif (tok[0] == '-' && tok[1] == '-') tok+= 2;\n\tnum= strtod(tok, &EndPtr);\n\tif (*EndPtr == '/') {\n\t\tdenom= strtod(EndPtr+1, &EndPtr);\n\t\tif (!denom) {\n\t\t\tparsed->errmsg= \"Division by zero\";\n\t\t\treturn false;\n\t\t}\n\t\tnum /= denom;;\n\t} else {\n\t\tnum *= FixedPtMultiplier;\n\t}\n\tif (*EndPtr != '\\0') {\n\t\tsnprintf(parsed->errmsg_buf, sizeof(parsed->errmsg_buf), \"Can't parse float '%s'\", tok);\n\t\tparsed->errmsg= parsed->errmsg_buf;\n\t\treturn false;\n\t}\n\tparsed->doubles[parsed->dCnt++]= num;\n\treturn true;\n}\n\nbool ParseToken(char **line, struct ParseParamsResult *parsed) {\n\tchar *tok;\n\t/* buffer space check */\n\tif (parsed->sCnt >= sizeof(parsed->strings)/sizeof(parsed->strings[0])) {\n\t\tparsed->errmsg= \"Argument count exceeded (string)\";\n\t\treturn false;\n\t}\n\tif (!(tok= next_token(line))) {\n\t\tparsed->errmsg= \"expected Token\";\n\t\treturn false;\n\t}\n\tparsed->strings[parsed->sCnt++]= tok;\n\treturn true;\n}\n\nbool CaptureRemainder(char **line, struct ParseParamsResult *parsed) {\n\tif (parsed->sCnt >= sizeof(parsed->strings)/sizeof(parsed->strings[0])) {\n\t\tparsed->errmsg= \"Argument count exceeded (string)\";\n\t\treturn false;\n\t}\n\tparsed->strings[parsed->sCnt++]= *line;\n\t*line += strlen(*line);\n\treturn true;\n}\n\nbool ParseHexByte(const char *str, float *Result);\nbool ParseHexColor(const char* str, float Result[4]);\nbool ParseColor(char **line, struct ParseParamsResult *parsed) {\n\tint n;\n\t\n\t/* always stored as four floating point components */\n\tif (parsed->fCnt + 4 > sizeof(parsed->floats)/sizeof(parsed->floats[0])) {\n\t\tparsed->errmsg= \"Argument count exceeded (float)\";\n\t\treturn false;\n\t}\n\t// hash indicates a hex code\n\tif (**line == '#' || ((**line == '\"' || **line == '\\'') && (*line)[1] == '#')) {\n\t\tif (!ParseHexColor(next_token(line), parsed->floats + parsed->fCnt)) {\n\t\t\tparsed->errmsg= \"Invalid color code\";\n\t\t\treturn false;\n\t\t} else {\n\t\t\tparsed->fCnt+= 4;\n\t\t\treturn true;\n\t\t}\n\t}\n\telse {\n\t\t// else look for 3 or 4 numbers\n\t\tfor (n= 0; n < 4; n++) {\n\t\t\tif (!ParseFloat(line, parsed))\n\t\t\t\tbreak;\n\t\t}\n\t\tif (n < 3) {\n\t\t\tparsed->fCnt -= n;\n\t\t\tparsed->errmsg= \"Not enough components for color\";\n\t\t\treturn false;\n\t\t}\n\t\t/* alpha= 1.0 unless specified otherwise */\n\t\tif (n < 4) parsed->floats[parsed->fCnt++]= 1.0;\n\t\treturn true;\n\t}\n}\nbool ParseHexColor(const char* Text, float Result[4]) {\n\tif (!Text || Text[0] != '#') return false;\n\t// could use strtol instead of this, but then would have to worry about endian issues,\n\t// made more awkward by presence or absence of Alpha channel\n\tif (!ParseHexByte(Text+1, Result+0)) return false;\n\tif (!ParseHexByte(Text+3, Result+1)) return false;\n\tif (!ParseHexByte(Text+5, Result+2)) return false;\n\tif (Text[7]) {\n\t\tif (!ParseHexByte(Text+7, Result+3)) return false;\n\t} else {\n\t\tResult[3]= 0xFF;\n\t}\n\treturn true;\n}\nbool ParseHexByte(const char *str, float *Result) {\n\tGLubyte x;\n\tchar h= str[0], l= str[1];\n\tif      (h >= '0' && h <= '9') x= h -  '0';\n\telse if (h >= 'A' && h <= 'F') x= h - ('A' - 10);\n\telse if (h >= 'a' && h <= 'f') x= h - ('a' - 10);\n\telse return false;\n\tx <<= 4;\n\tif      (l >= '0' && l <= '9') x|= l -  '0';\n\telse if (l >= 'A' && l <= 'F') x|= l - ('A' - 10);\n\telse if (l >= 'a' && l <= 'f') x|= l - ('a' - 10);\n\telse return false;\n\t*Result= x * 1.0/255;\n\treturn true;\n}\n\nbool FileExists(const char *Name) {\n#ifdef _WIN32\n\treturn PathFileExists(Name);\n#else\n\tstruct stat s;\n\treturn stat(Name, &s) == 0;\n#endif\n}\n"
  },
  {
    "path": "src/ProcessInput.h",
    "content": "#ifndef PROCESS_INPUT_H\n#define PROCESS_INPUT_H\n\n#include \"Global.h\"\n\n#define P_SUCCESS 0\n#define P_IGNORE 1\n#define P_CMD_ERR 2\n#define P_NOT_FOUND 3\n#define P_EOF 4\n\n#ifndef _WIN32\nvoid InitLineBuffer(int FileHandle);\n#else\nvoid InitLineBuffer(HANDLE FileHandle);\n#endif\nchar* ReadLine();\n\nint ProcessCommand(char *Line);\n\nstruct SymbVarEntry_t;\n\n\n/* The ParseParams function family returns all parsed values into a collection\n * of fixed-size arrays.  So, a format of \"iiff\" will store two items into the\n * array of ints, and two items into the array of floats.  This saves a lot of\n * bookkeeping over dynamic allocation, or messing with unions, or trusting that\n * the union is of the type you think it is.\n */\n\n#define PARSEPARAMS_MAX_OBJECTS 32\n#define PARSEPARAMS_MAX_FLOATS  32\n#define PARSEPARAMS_MAX_STRINGS 32\n#define PARSEPARAMS_MAX_INTS    32\n\nstruct ParseParamsResult {\n\t//long     longs[PARSEPARAMS_MAX_INTS];\n\tGLint    ints [PARSEPARAMS_MAX_INTS];\n\tGLfloat  floats[PARSEPARAMS_MAX_FLOATS];\n\tGLdouble doubles[PARSEPARAMS_MAX_FLOATS];\n\tchar*    strings[PARSEPARAMS_MAX_STRINGS];\n\tstruct SymbVarEntry_t *objects[PARSEPARAMS_MAX_OBJECTS];\n\tint iCnt, lCnt, fCnt, dCnt, sCnt, oCnt;\n\tchar *errmsg, errmsg_buf[128];\n};\n\nextern bool ParseParams  (char **line, const char *format, struct ParseParamsResult *result);\nextern char* next_token  (char **line);\nextern bool ParseToken   (char **line, struct ParseParamsResult *result);\nextern bool ParseInt     (char **line, struct ParseParamsResult *result);\n//extern bool ParseLong    (char **line, struct ParseParamsResult *result);\nextern bool ParseFloat   (char **line, struct ParseParamsResult *result);\nextern bool ParseDouble  (char **line, struct ParseParamsResult *result);\nextern bool ParseColor   (char **line, struct ParseParamsResult *result);\nextern bool FileExists   (const char *Name);\nextern bool CaptureRemainder(char **line, struct ParseParamsResult *result);\n\n#endif\n"
  },
  {
    "path": "src/Server.c",
    "content": "#define INCLUDE_GL\n#define INCLUDE_SDL\n#include <config.h>\n#include \"Global.h\"\n#include \"Version.h\"\n#include \"Server.h\"\n#include \"ProcessInput.h\"\n#include \"SymbolHash.h\"\n#include \"ParseGL.h\"\n\nbool Shutdown= false;\n\ntypedef struct {\n\tchar *FifoName;\n\tbool TerminateOnEOF;\n\tbool ShowCmds, ShowConsts;\n\tbool WantHelp;\n\tbool NeedHelp;\n\tbool VersionOnly;\n\tchar *WndTitle;\n\tbool NoEmitEvents;\n\tbool ManualSDLSetup;\n\tbool ManualViewport;\n\tbool ManualProjection;\n\tint Width;\n\tint Height;\n\tint X, Y;\n\tint Bpp;\n} CmdlineOptions;\n\nvoid SetParamDefaults(CmdlineOptions *Options);\nvoid ReadParams(char **args, CmdlineOptions *Options);\nvoid PrintUsage(bool error);\nvoid CheckInput();\nvoid CheckSDLEvents();\nvoid InitGL(int, int);\nvoid EmitKey(const SDL_KeyboardEvent *E);\n\nbool PendingResize= false;\nint Resize_w, Resize_h;\nvoid FinishResize();\n\nchar Buffer[1024];\n#ifndef _WIN32\nint InputFD= 0;\n#else\nHANDLE InputFD;\n#endif\nSDL_Surface *MainWnd= NULL;\n\nlong StartTime;\nint DefaultSDLFlags= SDL_OPENGL | SDL_ANYFORMAT | SDL_RESIZABLE;\n\nCmdlineOptions Options;\n\nint main(int Argc, char**Args) {\n\tSetParamDefaults(&Options);\n\tReadParams(Args, &Options);\n\tchar wnd_xy_buf[48];\n\t\n\tif (Options.WantHelp || Options.NeedHelp) {\n\t\tPrintUsage(!Options.WantHelp);\n\t\treturn Options.WantHelp? 0 : -1;\n\t}\n\tif (Options.VersionOnly) {\n\t\tprintf(\"Version %s\\n\", CGLVER_String);\n\t\treturn 0;\n\t}\n\tif (Options.ShowCmds) {\n\t\tDumpCommandList(stdout);\n\t\treturn 0;\n\t}\n\tif (Options.ShowConsts) {\n\t\tDumpConstList(stdout);\n\t\treturn 0;\n\t}\n\n\t#ifndef WIN32\n\tif (Options.FifoName) {\n\t\tif (mkfifo(Options.FifoName, 0x1FF) < 0) {\n\t\t\tperror(\"mkfifo\");\n\t\t\treturn 2;\n\t\t}\n\t\tInputFD= open(Options.FifoName, O_RDONLY | O_NONBLOCK);\n\t\tif (InputFD < 0) {\n\t\t\tperror(\"open(fifo, read|nonblock)\");\n\t\t\treturn 3;\n\t\t}\n\t\tclose(0); // Done with stdin.\n\t}\n\telse if (isatty(InputFD)) {\n\t\tfprintf(stderr, \"Warning: STDIN is a terminal; will use blocking reads\\n\");\n\t}\n\telse {\n\t\tDEBUGMSG((\"Enabling nonblocking mode on stdin\\n\"));\n\t\tif (fcntl(InputFD, F_SETFL, O_NONBLOCK) < 0) {\n\t\t\tperror(\"fnctl(stdin, F_SETFL, O_NONBLOCK)\");\n\t\t\treturn 3;\n\t\t}\n\t}\n\t#else\n\tInputFD= GetStdHandle(STD_INPUT_HANDLE);\n\t#endif\n\tInitLineBuffer(InputFD); // this initializes a static global LineBuffer.  See ProcessInput.c\n\n\tif (!Options.ManualSDLSetup) {\n\t\tDEBUGMSG((\"Initializing SDL\\n\"));\n\t\tif (SDL_Init(SDL_INIT_VIDEO) < 0) {\n\t\t\tfprintf(stderr, \"CmdlineGL: SDL_Init: %s\\n\", SDL_GetError());\n\t\t\treturn 4;\n\t\t}\n\t\tatexit(SDL_Quit);\n\n//\t\tSdlVid= SDL_GetVideoInfo();\n\t\tSDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);\n\n\t\tDEBUGMSG((\"Setting video mode\\n\"));\n\t\t// Silly, but don't see a better way right now\n\t\tif (Options.X || Options.Y) {\n\t\t\tsnprintf(wnd_xy_buf, sizeof(wnd_xy_buf), \"%d,%d\", Options.X, Options.Y);\n\t\t\tsetenv(\"SDL_VIDEO_WINDOW_POS\", wnd_xy_buf, 1);\n\t\t}\n\t\tMainWnd= SDL_SetVideoMode(Options.Width, Options.Height, Options.Bpp, DefaultSDLFlags);\n\t\tif (!MainWnd) {\n\t\t\tfprintf(stderr, \"Couldn't set video mode: %s\\n\", SDL_GetError());\n\t\t\texit(5);\n\t\t}\n\n\t\tSDL_EnableUNICODE(1);\n\t\tif (SDL_EnableKeyRepeat(0, 0) < 0)\n\t\t\tfprintf(stderr, \"Can't disable key repeat. %s\\n\", SDL_GetError());\n\n\t\tInitGL(Options.Width, Options.Height);\n\n\t\tif (!Options.WndTitle) Options.WndTitle= \"CmdlineGL\";\n\t\tSDL_WM_SetCaption(Options.WndTitle, Options.WndTitle);\n\t}\n\n\tDEBUGMSG((\"Recording time\\n\"));\n\tStartTime= SDL_GetTicks();\n\n\tDEBUGMSG((\"Entering main loop\\n\"));\n\twhile (!Shutdown) {\n\t\tCheckInput();\n\t\tCheckSDLEvents();\n\t\tSDL_Delay(1); // yield processor to the script\n\t}\n\tDEBUGMSG((\"Shutting down.\\n\"));\n\n\t#ifndef _WIN32\n\tclose(InputFD);\n\t#else\n\tCloseHandle(InputFD);\n\t#endif\n\t// this might be a socket\n\tif (Options.FifoName) {\n\t\tunlink(Options.FifoName);\n\t}\n\n\treturn 0;\n}\n\nvoid SetParamDefaults(CmdlineOptions *Options) {\n\tmemset(Options, 0, sizeof(CmdlineOptions));\n\tOptions->Width= 640;\n\tOptions->Height= 480;\n\t// Options->Bpp= 0; zero tells to use display default\n}\n\nvoid PrintMissingParamMessage(char* ArgName, CmdlineOptions *Options) {\n\tfprintf(stderr, \"Option %s requires a parameter\\n\", ArgName);\n\tOptions->NeedHelp= true;\n}\n\nvoid ReadParams(char **Args, CmdlineOptions *Options) {\n\tchar **NextArg= Args+1, *tmp;\n\tbool ReadingArgs= true;\n\tint n, w, h, x, y;\n\t// Note: this function takes advantage of the part of the program argument specification\n\t//   that says all argv lists must end with a NULL pointer.\n\twhile (ReadingArgs && *NextArg && (*NextArg)[0] == '-') {\n\t\tswitch ((*NextArg)[1]) {\n\t\t#ifndef WIN32\n\t\tcase 'f':\n\t\t\tOptions->FifoName= *++NextArg;\n\t\t\tif (!Options->FifoName) {\n\t\t\t\tPrintMissingParamMessage(\"-f\", Options);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tbreak; // '-f <blah>' = read from FIFO \"blah\"\n\t\t#endif\n\t\tcase 't': Options->TerminateOnEOF= true; break;\n\t\tcase 'v': Options->VersionOnly= true; break;\n\t\tcase 'h':\n\t\tcase '?': Options->WantHelp= true; break;\n\t\tcase '\\0': ReadingArgs= false; break; // \"-\" = end of arguments\n\t\tcase '-': // \"--\" => long-option\n\t\t\tif (strcmp(*NextArg, \"--help\") == 0) { Options->WantHelp= true; break; }\n\t\t\tif (strcmp(*NextArg, \"--showcmds\") == 0) { Options->ShowCmds= true; break; }\n\t\t\tif (strcmp(*NextArg, \"--showconsts\") == 0) { Options->ShowConsts= true; break; }\n\t\t\tif (strcmp(*NextArg, \"--noevents\") == 0) { Options->NoEmitEvents= true; break; }\n\t\t\tif (strcmp(*NextArg, \"--manual-viewport\") == 0) { Options->ManualViewport= true; break; }\n\t\t\tif (strcmp(*NextArg, \"--manual-projection\") == 0) { Options->ManualProjection= true; break; }\n\t\t\tif (strcmp(*NextArg, \"--title\") == 0) {\n\t\t\t\tOptions->WndTitle= *++NextArg;\n\t\t\t\tif (!Options->WndTitle) {\n\t\t\t\t\tPrintMissingParamMessage(\"--title\", Options);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (strcmp(*NextArg, \"--version\") == 0) { Options->VersionOnly= true; break; }\n\t\t\tif (strcmp(*NextArg, \"--geometry\") == 0) {\n\t\t\t\ttmp= *++NextArg;\n\t\t\t\tif (!tmp || (n=sscanf(tmp, \"%dx%d%d%d\", &w, &h, &x, &y)) < 2) {\n\t\t\t\t\tPrintMissingParamMessage(\"--geometry\", Options);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tOptions->Width= w;\n\t\t\t\tOptions->Height= h;\n\t\t\t\tif (n > 2) Options->X= x;\n\t\t\t\tif (n > 3) Options->Y= y;\n\t\t\t\tbreak;\n\t\t\t}\n\t\tdefault:\n\t\t\tfprintf(stderr, \"Unrecognized argument: %s\\n\", *NextArg);\n\t\t\tOptions->NeedHelp= true;\n\t\t\treturn;\n\t\t}\n\t\tNextArg++;\n\t}\n}\n\n/*\n=head1 OPTIONS\n\n=over\n\n=item -t\n\nTerminate after a zero-length read (EOF)\n\n=item --manual-viewport\n\nDon't automatically reinitialize glViewport after the window has changed size.\nThis allows the application to control the viewport area.\n\n=item --manual-projection\n\nDon't automatically set up a projection matrix or rescale it after the window\nchanges size.\n\n=item -f FIFO\n\nCreate a named pipe at this path, and read from it.  This option is not available on Windows.\n\n=item --geometry WIDTHxHEIGHT+X+Y\n\nUsing Unix X11 notation, specify the window geometry.  Negative X and Y are not yet supported.\n\n=item --title TEXT\n\nSet the title of the window.\n\n=item --noevents\n\nDon't report user input activity on stdout.  (other messages and events will still be printed)\n\n=item --showcmds\n\nDump a list of all available commands on stdout.\n\n=item --showconsts\n\nDump a list of all symbolic constants on stdout.  These constants may be given to any command\nwhich takes an integer argument.\n\n=item -v\n\n=item --version\n\nPrint the version and exit.\n\n=item -h\n\nPrint a brief usage summary\n\n=back\n\n=cut */\nvoid PrintUsage(bool error) {\n\tfprintf(error? stderr : stdout,\n\t\"CmdlineGL %s\\n\"\n\t\"Usage:\\n\"\n\t\"  <command-source> | CmdlineGL [options] | <user-input-reader>\\n\"\n\t\"     Reads commands from stdin, and writes user input to stdout.\\n\"\n\t\"\\n\"\n\t\"Options:\\n\"\n\t\"  -t                  Terminate after a zero-length read (EOF).\\n\"\n\t\"  --manual-viewport   No automatic glViewport on window resize\\n\"\n\t\"  --manual-projection No default GL_PROJECTION matrix\\n\"\n\t#ifndef WIN32\n\t\"  -f FIFO             Create the named fifo (file path+name) and read from it.\\n\"\n\t#endif\n\t\"  --geometry WxH+X+Y  Set initial window geometry (defaults to 640x480+0+0)\\n\"\n\t\"  --title TEXT        Set the title of the window to \\\"text\\\".\\n\"\n\t\"  --noevents          Don't print any input event messages to stdout.\\n\"\n\t\"  --showcmds          List all the available commands in this version of CmdlineGL.\\n\"\n\t\"  --showconsts        List all the constants (GL_xxxx) that are available.\\n\"\n\t\"  -v --version        Print version and exit.\\n\"\n\t\"  -h                  Display this help message.\\n\"\n\t\"\\n\"\n\t\"Note: Each line of input is broken on space characters and treated as a\\n\"\n \t\"      command.  There is currently no escaping mechanism, although I'm not\\n\"\n \t\"      opposed to the idea.\\n\\n\",\n\tCGLVER_String\n\t);\n}\n\n/*=head1 COMMANDS\n\n=head2 Render Loop Commands\n\nThese commands control CmdlineGL itself, and assist with setting up a render loop.\n\n=item cglEcho ANY_TEXT\n\nRepeat a string of text on stdout (may be confused for user input events,\nbut maybe that's what you want)\n\n=cut */\nCOMMAND(cglEcho, \"b\") {\n\tprintf(\"%s\\n\", parsed->strings[0]);\n\tfflush(stdout);\n\treturn true;\n}\n\n/*=item cglExit\n\nCause CmdlineGL to terminate (with error code 0)\n\n=item cglQuit\n\nAlias for cglExit\n\n=cut */\nCOMMAND(cglExit, \"\") {\n\tShutdown= true;\n\treturn true;\n}\nCOMMAND(cglQuit, \"\") {\n\tShutdown= true;\n\treturn true;\n}\n\n/*=item cglGetTime\n\nReturn the number of milliseconds since start of the program.\n\n=item cglSleep DELAY_MS\n\nSleep for a number of milliseconds from when the command is received\n\n=item cglSync UNTIL_TIME_MS\n\nSleep until the specified time, measured as milliseconds from start of program.\n\n=cut */\nCOMMAND(cglGetTime, \"\") {\n\tlong t= SDL_GetTicks() - StartTime;\n\tprintf(\"t=%ld\\n\", t);\n\tfflush(stdout);\n\treturn true;\n}\n\nCOMMAND(cglSleep, \"i\") {\n\tfflush(stdout);\n\tfflush(stderr);\n\tSDL_Delay(parsed->ints[0]);\n\treturn true;\n}\n\nCOMMAND(cglSync, \"i\") {\n\tint target= parsed->ints[0];\n\tint t= SDL_GetTicks() - StartTime;\n\tif (target - t > 0) {\n\t\tDEBUGMSG((\"sleeping for %d\\n\", target - t));\n\t\tfflush(stdout);\n\t\tfflush(stderr);\n\t\tSDL_Delay(target - t);\n\t}\n\treturn true;\n}\n\n/*=item cglSwapBuffers\n\nSwap front and back buffer, showing the frame you were drawing and beginning\na new frame.  (you still need to call glClear yourself)\nIf a window resize is pending, it will be performed at this point.\n\n=cut */\nCOMMAND(cglSwapBuffers, \"\") {\n\tSDL_GL_SwapBuffers();\n\tFrameInProgress= false;\n\t// If we were waiting to resize the window, now is the time\n\tif (PendingResize) FinishResize();\n\treturn true;\n}\n\nvoid CheckInput() {\n\tint CmdCount;\n\tchar *Line;\n\n\terrno= 0;\n\tCmdCount= 0;\n\twhile ((CmdCount < MAX_COMMAND_BATCH || PointsInProgress) && (Line= ReadLine())) {\n\t\tif (*Line && *Line != '#') {\n\t\t\t//fprintf(stderr, \"Starting '%s'\\n\", Line);\n\t\t\tProcessCommand(Line);\n\t\t\t//fprintf(stderr, \"Ending '%s'\\n\", Line);\n\t\t\tCmdCount++;\n\t\t}\n\t}\n\tif (CmdCount < MAX_COMMAND_BATCH && errno != EAGAIN) {\n\t\tDEBUGMSG((\"Received EOF.\\n\"));\n\t\tif (Options.TerminateOnEOF)\n\t\t\tShutdown= 1;\n\t}\n}\n\nvoid CheckSDLEvents() {\n\tSDL_Event Event;\n\twhile (SDL_PollEvent(&Event))\n\t\tswitch (Event.type) {\n\t\t\tcase SDL_KEYDOWN:\n\t\t\tcase SDL_KEYUP:\n\t\t\t\tif (!Options.NoEmitEvents)\n\t\t\t\t\tEmitKey(&Event.key);\n\t\t\t\tbreak;\n\t\t\tcase SDL_MOUSEMOTION:\n\t\t\t\tif (!Options.NoEmitEvents)\n\t\t\t\t\tprintf(\"M @ %d %d %d %d\\n\", Event.motion.x, Event.motion.y,\n\t\t\t\t\t\tEvent.motion.xrel, Event.motion.yrel);\n\t\t\t\tbreak;\n\t\t\tcase SDL_MOUSEBUTTONDOWN:\n\t\t\tcase SDL_MOUSEBUTTONUP:\n\t\t\t\tif (!Options.NoEmitEvents)\n\t\t\t\t\tprintf(\"M %c %d %d %d\\n\", (Event.button.state == SDL_PRESSED)? '+':'-',\n\t\t\t\t\t\tEvent.button.button, Event.button.x, Event.button.y);\n\t\t\t\tbreak;\n\t\t\tcase SDL_VIDEORESIZE:\n\t\t\t\tResize_w= Event.resize.w;\n\t\t\t\tResize_h= Event.resize.h;\n\t\t\t\t// Can't resize if user is in the middle of rendering\n\t\t\t\tif (FrameInProgress)\n\t\t\t\t\tPendingResize= true;\n\t\t\t\telse\n\t\t\t\t\tFinishResize();\n\t\t\t\tbreak;\n\t\t\tcase SDL_ACTIVEEVENT:\n\t\t\t\tif (!Options.NoEmitEvents) {\n\t\t\t\t\tif (Event.active.state & SDL_APPMOUSEFOCUS)\n\t\t\t\t\t\tprintf(\"W MOUSEFOCUS %c\\n\", Event.active.gain? '+':'-');\n\t\t\t\t\tif (Event.active.state & SDL_APPINPUTFOCUS)\n\t\t\t\t\t\tprintf(\"W INPUTFOCUS %c\\n\", Event.active.gain? '+':'-');\n\t\t\t\t\tif (Event.active.state & SDL_APPACTIVE)\n\t\t\t\t\t\tprintf(\"W ACTIVE %c\\n\", Event.active.gain? '+':'-');\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase SDL_QUIT:\n\t\t\t\tif (!Options.NoEmitEvents)\n\t\t\t\t\tprintf(\"W QUIT\\n\");\n\t\t\t\tShutdown= true;\n\t\t\t\tbreak;\n\t\t}\n\tif (!Options.NoEmitEvents)\n\t\tfflush(stdout);\n}\n\n// This should only be called when FrameInProgress is false\n// Might get called from ParseGL.c, so args are stored in globals.\nvoid FinishResize() {\n\tassert(!FrameInProgress);\n\tMainWnd= SDL_SetVideoMode(Resize_w, Resize_h, Options.Bpp, DefaultSDLFlags);\n\tif (!Options.NoEmitEvents) {\n\t\tprintf(\"W RESIZE %d %d\\n\", Resize_w, Resize_h);\n\t\tfflush(stdout);\n\t}\n\tPendingResize= false;\n\tInitGL(Resize_w, Resize_h);\n}\n\nvoid InitGL(int w, int h) {\n\tGLfloat top, bottom, left, right;\n\tGLfloat dist= 20; // 20 units from near clipping plane to the origin\n\tassert(!FrameInProgress);\n\n\tif (!Options.ManualViewport)\n\t\t// Use the entire window\n\t\tglViewport(0, 0, w, h);\n\n\tif (!Options.ManualProjection) {\n\t\t// Recalculate the projection matrix\n\t\tglMatrixMode(GL_PROJECTION);\n\t\tglLoadIdentity();\n\n\t\tif (w<h) {\n\t\t\t// if the width is less than the height, make the viewable width\n\t\t\t// 20 world units wide, and calculate the viewable height assuming\n\t\t\t// an aspect ratio of \"1\".\n\t\t\tleft= -10;\n\t\t\tright= 10;\n\t\t\tbottom= -10.0 * ((GLfloat)h) / w;\n\t\t\ttop= 10.0 * ((GLfloat)h) / w;\n\t\t}\n\t\telse {\n\t\t\t// if the height is less than the width, make the viewable height\n\t\t\t// 20 world units tall, and calculate the viewable width assuming\n\t\t\t// an aspect ratio of \"1\".\n\t\t\tleft= -10.0 * ((GLfloat)w) / h;\n\t\t\tright= 10.0 * ((GLfloat)w) / h;\n\t\t\tbottom= -10;\n\t\t\ttop= 10;\n\t\t}\n\n\t\tglFrustum(left/dist, right/dist, bottom/dist, top/dist, 1, 1000);\n\t\tglTranslated(0, 0, -dist);\n\t\tglMatrixMode(GL_MODELVIEW);\n\t}\n}\n\nvoid encode_utf8(char *buffer, unsigned codepoint);\nvoid EmitKey(const SDL_KeyboardEvent *E) {\n\tchar kname[64], uni[5], *c;\n\tunsigned int codepoint= E->keysym.unicode;\n\tstrncpy(kname, SDL_GetKeyName(E->keysym.sym), sizeof(kname));\n\tkname[sizeof(kname)-1]= '\\0';\n\t// remove any whitespace in the key name\n\tfor (c= kname; *c; c++)\n\t\tif (*c <= ' ') *c= '_';\n\t// If unicode available, encode as utf8\n\tif (codepoint > (unsigned) ' ')\n\t\tencode_utf8(uni, codepoint);\n\telse\n\t\tuni[0]= 0;\n\tprintf(\"K %c %s %d %04x %s\\n\", (E->state == SDL_PRESSED)? '+':'-', kname,\n\t\tE->keysym.scancode, codepoint, uni);\n}\n\n// Yeah this exists elsewhere but I don't feel like depending on a lib for just this one function\nvoid encode_utf8(char *buffer, unsigned codepoint) {\n\tif (codepoint < 0x80)\n\t\t*buffer++= (char) codepoint;\n\telse if (codepoint < 0x800) {\n\t\t*buffer++= (char) 0xC0 | ((codepoint >> 6) & 0x1F);\n\t\t*buffer++= (char) 0x80 | ((codepoint     ) & 0x3F);\n\t}\n\telse if (codepoint < 0x10000) {\n\t\t*buffer++= (char) 0xE0 | ((codepoint >> 12) & 0x0F);\n\t\t*buffer++= (char) 0x80 | ((codepoint >>  6) & 0x3F);\n\t\t*buffer++= (char) 0x80 | ((codepoint      ) & 0x3F);\n\t}\n\telse if (codepoint < 0x110000) {\n\t\t*buffer++= (char) 0xF0 | ((codepoint >> 18) & 0x07);\n\t\t*buffer++= (char) 0x80 | ((codepoint >> 12) & 0x3F);\n\t\t*buffer++= (char) 0x80 | ((codepoint >>  6) & 0x3F);\n\t\t*buffer++= (char) 0x80 | ((codepoint      ) & 0x3F);\n\t}\n\t*buffer= 0;\n}\n"
  },
  {
    "path": "src/Server.h",
    "content": "#ifndef SERVER_H\n#define SERVER_H\n\n#include \"Global.h\"\n\nextern bool PendingResize;\nextern void FinishResize();\n\n#endif\n"
  },
  {
    "path": "src/SymbolHash.c",
    "content": "#include <config.h>\n#include \"Global.h\"\n#include \"SymbolHash.h\"\n\nconst char *SymbVarTypeName[]= { \"?\", \"Display List\", \"Quadric\", \"Texture\", \"Font\" };\nbool SymbVarTreeInit= false;\nRBTree SymbVarTree;\n\n/* ConstList dynamically generated variables */\nextern const int IntConstListCount;\nextern const IntConstListEntry IntConstList[];\nextern const int IntConstHashTableSize;\nextern const uint16_t IntConstHashTable[];\n\nvoid DumpConstList(FILE* DestStream) {\n\tint i;\n\tfor (i=1; i<=IntConstListCount; i++) /* 1-based list, since hashtable 0 isn't a valid item */\n\t\tif (IntConstList[i].Name)\n\t\t\tfprintf(DestStream, \"%s %d\\n\", IntConstList[i].Name, IntConstList[i].Value);\n}\n\n/* CmdList dynamically generated variables */\nextern const int CmdListCount;\nextern const CmdListEntry CmdList[];\nextern const int CmdHashTableSize;\nextern const uint16_t CmdHashTable[];\n\nvoid DumpCommandList(FILE* DestStream) {\n\tint i;\n\tfor (i=1; i<=CmdListCount; i++) /* 1-based list, since hashtable 0 isn't a valid item */\n\t\tif (CmdList[i].Name)\n\t\t\tfprintf(DestStream, \"%s\\n\", CmdList[i].Name);\n}\n\n/* The rest is related to the red/black tree that stored dynamic named objects */\n\nunsigned int CalcHash(const char* str) {\n\tunsigned int Result= 0;\n\twhile (*str)\n\t\tResult= ((Result<<1) + (Result ^ *str++));\n\treturn Result;\n}\n\nvoid InitSymbVarEntry(SymbVarEntry *Entry, const char* Name, int Type) {\n\tEntry->Hash= Type+CalcHash(Name);\n\tEntry->Type= Type;\n\tstrncpy(Entry->Name, Name, SYMB_VAR_MAX_LEN-1);\n\tEntry->Name[SYMB_VAR_MAX_LEN-1]= '\\0';\n\tRBTreeNode_Init(&(Entry->node));\n\tEntry->node.Object= Entry;\n}\n\nbool SymbVar_inorder_func(const void* ObjA, const void* ObjB) {\n\tSymbVarEntry *EntryA= (SymbVarEntry*) ObjA;\n\tSymbVarEntry *EntryB= (SymbVarEntry*) ObjB;\n\tif (EntryA->Hash == EntryB->Hash) {\n\t\tif (EntryA->Type == EntryB->Type)\n\t\t\treturn strcmp(EntryA->Name, EntryB->Name) <= 0;\n\t\telse\n\t\t\treturn EntryA->Type < EntryB->Type;\n\t}\n\telse\n\t\treturn (EntryA->Hash < EntryB->Hash);\n}\n\n/** Structure used to pass the key to the compare function */\ntypedef struct {\n\tint Hash;\n\tconst char *Name;\n\tint Type;\n} SymbVarSearchKey;\n\nint SymbVar_compare_func(const void* SearchKey, const void* Object) {\n\tSymbVarSearchKey *Key= (SymbVarSearchKey*) SearchKey;\n\tSymbVarEntry *Node= (SymbVarEntry*) Object;\n\tif (Key->Hash == Node->Hash) {\n\t\tif (Key->Type == Node->Type)\n\t\t\treturn strcmp(Key->Name, Node->Name);\n\t\telse\n\t\t\treturn Key->Type - Node->Type;\n\t}\n\telse\n\t\treturn Key->Hash - Node->Hash;\n}\n\nSymbVarEntry *GetSymbVar(const char *Name, int Type) {\n\tSymbVarSearchKey Key;\n\tRBTreeNode *Node;\n\n\tif (!SymbVarTreeInit) {\n\t\tRBTree_InitRootSentinel(&SymbVarTree.RootSentinel);\n\t\tSymbVarTreeInit= true;\n\t}\n\tKey.Hash= Type+CalcHash(Name);\n\tKey.Name= Name;\n\tKey.Type= Type;\n\tNode= RBTree_Find(&SymbVarTree.RootSentinel, &Key, SymbVar_compare_func);\n\tif (Node) return (SymbVarEntry*) Node->Object;\n\telse return NULL;\n}\n\nSymbVarEntry *CreateSymbVar(const char *Name, int Type) {\n\tSymbVarEntry *Entry;\n\tif (!SymbVarTreeInit) {\n\t\tRBTree_InitRootSentinel(&SymbVarTree.RootSentinel);\n\t\tSymbVarTreeInit= true;\n\t}\n\tEntry= (SymbVarEntry*) malloc(sizeof(SymbVarEntry));\n\tInitSymbVarEntry(Entry, Name, Type);\n\tRBTree_Add(&SymbVarTree.RootSentinel, &(Entry->node), SymbVar_inorder_func);\n\treturn Entry;\n}\n\nvoid DeleteSymbVar(SymbVarEntry *Entry) {\n\tRBTree_Prune(&Entry->node);\n\tfree(Entry);\n}\n\nvoid DumpVarList(FILE* DestStream) {\n\tRBTreeNode *Current= RBTree_GetLeftmost(SymbVarTree.RootSentinel.Left);\n\twhile (Current != &Sentinel) {\n\t\tfprintf(DestStream, \"%s %s\\n\",\n\t\t\tSymbVarTypeName[((SymbVarEntry*)Current->Object)->Type],\n\t\t\t((SymbVarEntry*)Current->Object)->Name\n\t\t);\n\t\tCurrent= RBTree_GetNext(Current);\n\t}\n}\n\n"
  },
  {
    "path": "src/SymbolHash.h",
    "content": "#ifndef SYMBOL_HASH_H\n#define SYMBOL_HASH_H\n\n#include \"ProcessInput.h\"\n\nstruct ParseParamsResult;\n\ntypedef struct {\n\tconst char* Name;\n\tconst char* ArgFormat;\n\tbool (*Handler)(struct ParseParamsResult *parsed);\n} CmdListEntry;\n\ntypedef struct {\n\tconst char* Name;\n\tint Value;\n} IntConstListEntry;\n\n#ifndef SYMB_VAR_MAX_LEN\n#define SYMB_VAR_MAX_LEN 32\n#endif\n#include \"Contained_RBTree.h\"\ntypedef struct SymbVarEntry_t {\n\tint Hash;\n\tchar Name[SYMB_VAR_MAX_LEN];\n\tunion {\n\t\tint Value;\n\t\tvoid *Data;\n\t};\n\tint Type;\n\tRBTreeNode node;\n} SymbVarEntry;\n\n#define NAMED_LIST 1\n#define NAMED_QUADRIC 2\n#define NAMED_TEXTURE 3\n#define NAMED_FONT 4\n\nextern const char *SymbVarTypeName[];\n\nextern const CmdListEntry *GetCmd(const char *Name);\nextern void DumpCommandList(FILE* DestStream);\n\nextern const IntConstListEntry *GetIntConst(const char *Name);\nextern void DumpConstList(FILE* DestStream);\n\nextern SymbVarEntry *CreateSymbVar(const char *Name, int Type);\nextern SymbVarEntry *GetSymbVar(const char *Name, int Type);\nextern void DeleteSymbVar(SymbVarEntry *Entry); // does not free contents of the variable!!\nextern void DumpVarList(FILE* DestStream);\n\n#endif\n\n"
  },
  {
    "path": "src/Version.h",
    "content": "#ifndef VERSION_H\n#define VERSION_H\n\nextern const int CGLVER_Major;\nextern const int CGLVER_Minor;\nextern const int CGLVER_Release;\nextern const int CGLVER_Build;\nextern const char* CGLVER_Host;\nextern const char* CGLVER_String;\n\n#endif\n"
  },
  {
    "path": "src/manual.head.pod",
    "content": "=head1 NAME\n\nCmdlineGL - Interpreter for subset of OpenGL 1.4 API\n\n=head1 SYNOPSIS\n\n  CmdlineGL [OPTIONS] <opengl_commands >user_events\n\n  # Play some recorded 3D graphics\n  bzcat graphics.txt.bz2 | CmdlineGL >/dev/null\n  \n  # Experiment from Bash\n  source CmdlineGL.lib\n  glClearColor '#00FF00'\n  glClear GL_COLOR_BUFFER_BIT\n  cglSwapBuffers\n\n=head1 DESCRIPTION\n\nCmdlineGL is an interpreter for parsing and executing OpenGL functions, which also simplifies\nthe OpenGL API in several ways to make it more user-friendly.  It comes with shell bindings for\nbash, allowing for experiments right from the terminal (if you have a graphical desktop).\nIt only covers the functions a beginner would need, and doesn't aspire to anything newer than\nthe 1.4 API.  It also provides some basic access to the GLU,\nL<SDL_image|https://github.com/libsdl-org/SDL_image> (loading image files), and\nL<FTGL|https://sourceforge.net/projects/ftgl/> (font rendering) libraries,\nfor the ability to make useful demos that the raw OpenGL API can't provide on its own.\n\n=head1 OPTIONS\n\n=head1 COMMANDS\n\n=head2 Parameter Parsing\n\nAll commands take parameters separated by whitespace, in much the same way as a shell would\nbreak its arguments.  There is also a quoting mechanism that may be used for any type of\nparameter.  If the parameter begins with C<'> or C<\">, then whitespace (other than newlines)\nwill be included in the parameter until the matching quote character.  Literal newline\ncharacters always end the command.  Within the string, C<\\n> will be converted to newline\ncharachers, and any other character preceeded by a backslash will be included as-is, allowing\nyou to escape the quote character and the backslash.\n\n=head3 Integers\n\nAll integer parameters of commands may be given as decimal, hexidecimal or symbolic C<GL_>\nconstants.  If an integer parameter does not begin with a digit, CmdlineGL will look it up in\nthe table of symbolic codes, and if it is not found, the command will fail and not execute.\n\n=head3 Floats\n\nAll floating point values may be specified as a normal decimal notation.  However, to make\nthings easier for Bash scripts, they may also contain a divisor, like \"34/100\".  To facilitate\nfixed-point math on lots of parameters, CmdlineGL supports a feature of a \"default divisor\" that\nwill be applied to EVERY floating point parameter of every command, unless the parameter\ncontains a divisor already.  See C<cglPushDivisor> below.\n\n=head3 Colors\n\nMany OpenGL commands take a color parameter, usually as 3 or 4 floating point numbers in the\nrange [0..1].  In each case, you may supply a single HTML-style hex code like '#RRGGBB' or\n'#RRGGBBAA' in their place.  The floating point values ARE affected by any implied divisor\nin effect (see above) but the HTML color codes are NOT.\n\n=head2 Default-Divisor Commands\n\n=cut"
  },
  {
    "path": "src/manual.tail.pod",
    "content": "=head1 EXAMPLE\n\nThe typical render loop, taking advantage of CmdlineGL's ability to\nsynchronize frames to a clock, looks like this:\n\n=over\n\n=item 1\n\nread output of CmdlineGL until \"t=\" event indicating current timestamp\n\n=item 2\n\nclear frame buffer\n\n=item 3\n\nrender OpenGL graphics\n\n=item 4\n\ncall glFlush and cglSwapBuffers to show the rendering\n\n=item 5\n\ncall cglSync telling it to delay until T + framerate_period\n\n=item 6\n\ncall cglGetTime, so that new timestamp will be available immediately after sleep\n\n=item 7\n\nrepeat\n\n=back\n\nThere are many examples in the C<./share/examples> directory that ships with this project,\nthough you may or may not have them installed.  Reproduced below, SpinText.sh is a minimal\nexample of something visually interesting.  It requires variables C<$font> (a path to a\n.ttf font file) and C<$text> (the text to render).\n\n    spin_rate=70  # Degree per second\n    R=0           # current rotation\n    T=0           # \"game-time\", in milliseconds\n    \n    # Initialize CmdlineGL for rendering only (no input or feedback)\n    source CmdlineGL.lib\n    CmdlineGL_Start ro\n    glEnable GL_NORMALIZE GL_DEPTH_TEST GL_CULL_FACE\n    glShadeModel GL_SMOOTH\n    \n    # Load font file and configure font rendering parameters\n    ftglCreateExtrudeFont font1 \"$font\"\n    ftglSetFontFaceSize   font1 72 72\n    ftglSetFontDepth      font1 20\n    \n    # Prepare the graphics in a display list.  Need to call once first since\n    # ftgl creates its own display lists, then again to capture those in the\n    # second display list.\n    ftglRenderFont font1 \"$text\" FTGL_ALIGN_CENTER FTGL_RENDER_ALL\n    glNewList mytext GL_COMPILE\n    glTranslate -$(( ${#text}/2 * 40 )) -36 10  # flaky guess at string mid\n    ftglRenderFont font1 \"$text\" FTGL_RENDER_ALL\n    glEndList\n    \n    # set up lighting (otherwise no change as it rotates)\n    glEnable GL_LIGHTING GL_LIGHT0\n    glLight GL_LIGHT0 GL_AMBIENT .8 .8 .8 0\n    glLight GL_LIGHT0 GL_DIFFUSE 1 .8 .8 0\n    glLight GL_LIGHT0 GL_SPECULAR .8 .8 .8 0\n    glLight GL_LIGHT0 GL_POSITION 10 10 10 1\n    \n    while true; do\n        glClear GL_COLOR_BUFFER_BIT GL_DEPTH_BUFFER_BIT\n        glLoadIdentity\n        glRotate $((R+=spin_rate))/60 0 1 0  # assuming 60fps\n        glScale 10/$((40 * ${#text} / 2))    # flaky guess at window width\n        glCallList mytext\n        glFlush\n        cglSwapBuffers\n        cglSync $((T+=16)) # blindly assume we can maintain 60fps\n    done\n\nMore advanced timing and handling of user input can be seen in ModelViewer.sh, usage of\nQuadrics for quick rendering of solids can be seen in Robot.sh, and direct manipulation\nof the modelview matrix as a coordinate system can be seen in FlightSim.sh\n\n=head1 BUGS\n\nPlease report bugs in the issue tracker at L<http://github.com/nrdvana/CmdlineGL>\n\n=head1 SEE ALSO\n\n=over 15\n\n=item Homepage\n\nL<http://nrdvana.net/cmdlinegl>\n\n=item GitHub Page\n\nL<http://github.com/nrdvana/CmdlineGL>\n\n=back\n\n=head1 AUTHOR\n\nMichael Conrad <mike@nrdvana.net>\n\n=cut\n"
  },
  {
    "path": "test/01-version.t",
    "content": "#! /usr/bin/env perl\nuse strict;\nuse warnings;\nuse Test::More;\n\npass;\ndone_testing;\n"
  }
]