Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // readme.txt
- yo dawg.
- This is some minimal OpenGL header and loader generator.
- It does *not* include the default GL.h piece of shit.
- You have to include all typedefs and tokens you use by yourself.
- 1. Create C# command line app named Glue.
- 2. Copy Program.cs to the project.
- 3. Compile that shit.
- 4. Check example.cmd and example.txt below for usage.
- And fuck nope, it isn't really tested.
- Cheers, E1.
- // Program.cs
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Text;
- namespace Glue
- {
- /// <summary>
- /// List of strings.
- /// </summary>
- class StringList : LinkedList<String>
- {
- /// <summary>
- /// Creates a new list.
- /// </summary>
- public StringList()
- : base()
- {
- }
- /// <summary>
- /// Creates a new list.
- /// </summary>
- /// <param name="tokens">Token array.</param>
- public StringList(String[] tokens)
- : base(tokens)
- {
- }
- /// <summary>
- /// Pops the first element.
- /// </summary>
- /// <returns>First element.</returns>
- public String PopFirst()
- {
- var result = First.Value;
- RemoveFirst();
- return result;
- }
- /// <summary>
- /// Pops the last element.
- /// </summary>
- /// <returns>Last element.</returns>
- public String PopLast()
- {
- var result = Last.Value;
- RemoveLast();
- return result;
- }
- }
- /// <summary>
- /// Generator base entry.
- /// </summary>
- /// <typeparam name="N">Type of the name.</typeparam>
- /// <typeparam name="D">Type of the data.</typeparam>
- class Entry<N, D>
- {
- /// <summary>
- /// Entry name.
- /// </summary>
- public N Name;
- /// <summary>
- /// Entry data.
- /// </summary>
- public D Data;
- /// <summary>
- /// Creates a new entry.
- /// </summary>
- /// <param name="name">Entry name.</param>
- /// <param name="data">Entry data.</param>
- public Entry(N name, D data)
- {
- Name = name;
- Data = data;
- }
- }
- /// <summary>
- /// Named generator entry.
- /// </summary>
- class Named : Entry<String, StringList>
- {
- /// <summary>
- /// Joined typename cache.
- /// </summary>
- private String joined;
- /// <summary>
- /// Creates a new named entry.
- /// </summary>
- /// <param name="name">Entry name.</param>
- /// <param name="data">Entry data.</param>
- public Named(String name, StringList data)
- : base(name, data)
- {
- }
- /// <summary>
- /// Joins the data into a typename.
- /// </summary>
- /// <returns>Typename.</returns>
- public String Join()
- {
- if (joined == null)
- {
- StringBuilder builder = new StringBuilder();
- foreach (var token in Data)
- {
- if (token.Equals("*") || builder.Length == 0)
- builder.Append(token);
- else
- builder.Append(" ").Append(token);
- }
- joined = builder.ToString();
- }
- return joined;
- }
- }
- /// <summary>
- /// Generator function entry.
- /// </summary>
- class Function : Entry<Named, List<Named>>
- {
- /// <summary>
- /// Entry point array index.
- /// </summary>
- public int Index;
- /// <summary>
- /// Creates a new function entry.
- /// </summary>
- /// <param name="name">Function name.</param>
- /// <param name="data">Function data.</param>
- /// <param name="index">Entry point array index.</param>
- public Function(Named name, List<Named> data, int index)
- : base(name, data)
- {
- Index = index;
- }
- /// <summary>
- /// Test void return.
- /// </summary>
- /// <returns>True on success.</returns>
- public bool IsVoid()
- {
- var data = Name.Data;
- return data.Count == 1 && (data.First.Value.Equals("void") || data.First.Value.Equals("GLvoid"));
- }
- }
- /// <summary>
- /// OpenGL extension loader generator.
- /// </summary>
- class Generator
- {
- /// <summary>
- /// Current file while parsing.
- /// </summary>
- private String file;
- /// <summary>
- /// Line number while parsing.
- /// </summary>
- private int current;
- /// <summary>
- /// Dynamic linkage for functions.
- /// </summary>
- private bool dynamic;
- /// <summary>
- /// Current entry point array index.
- /// </summary>
- private int index;
- /// <summary>
- /// OpenGL constant tokens.
- /// </summary>
- private List<Named> constants = new List<Named>();
- /// <summary>
- /// OpenGL type definitions.
- /// </summary>
- private List<String> types = new List<String>();
- /// <summary>
- /// OpenGL function definitions.
- /// </summary>
- private List<Function> functions = new List<Function>();
- /// <summary>
- /// Adds a new file to the generator.
- /// </summary>
- /// <param name="file">Extension file name.</param>
- public void Add(String file)
- {
- // Reset parser state.
- this.file = file; current = 0; dynamic = false;
- // Parse template file.
- using (var reader = new StreamReader(file))
- {
- while (true)
- {
- current++;
- String line = reader.ReadLine();
- if (line == null)
- break;
- int index = line.IndexOf("//");
- if (index != -1)
- line = line.Substring(0, index);
- line = line.Trim();
- if (line.Length == 0)
- continue;
- if (StartsWith(line, "#pragma"))
- {
- var tokens = Split(line, null);
- if (tokens.Count != 2)
- Panic("invalid #pragma");
- tokens.RemoveFirst();
- var action = tokens.PopFirst();
- if (action.Equals("dynamic"))
- dynamic = true;
- else if (action.Equals("static"))
- dynamic = false;
- else
- Panic("invalid pragma directive");
- continue;
- }
- if (StartsWith(line, "#define"))
- {
- ParseConstant(line);
- continue;
- }
- if (line.EndsWith(";"))
- line = line.Substring(0, line.Length - 1).Trim();
- if (line.Length == 0)
- continue;
- if (StartsWith(line, "typedef"))
- {
- line = line.Substring(7, line.Length - 7).Trim();
- if (line.Length == 0)
- Panic("invalid typedef");
- types.Add(line);
- continue;
- }
- line = line.Replace("*", " * ").Trim();
- if (line.Length == 0)
- continue;
- ParseFunction(line);
- }
- }
- }
- /// <summary>
- /// Writes the header file.
- /// </summary>
- /// <param name="writer">Destination stream.</param>
- public void WriteHeader(StreamWriter writer)
- {
- writer.WriteLine("#pragma once");
- writer.WriteLine();
- writer.WriteLine("#include <stddef.h>");
- writer.WriteLine("#include <stdint.h>");
- writer.WriteLine();
- writer.WriteLine("#ifndef GLAPI");
- writer.WriteLine("#define GLAPI extern \"C\" __declspec(dllimport)");
- writer.WriteLine("#endif");
- writer.WriteLine();
- writer.WriteLine("#ifndef GLAPIENTRY");
- writer.WriteLine("#define GLAPIENTRY __stdcall");
- writer.WriteLine("#endif");
- writer.WriteLine();
- writer.WriteLine("#pragma comment (lib, \"OPENGL32\")");
- writer.WriteLine();
- if (index > 0)
- {
- writer.WriteLine("// Load function pointers.");
- writer.WriteLine("extern void LoadGL();");
- writer.WriteLine();
- }
- // Emit types.
- if (types.Count > 0)
- {
- foreach (var type in types)
- writer.WriteLine("typedef " + type + ";");
- writer.WriteLine();
- }
- // Emit constants.
- if (constants.Count > 0)
- {
- foreach (var constant in constants)
- writer.WriteLine("#define " + Pad(constant.Name, 60) + " " + constant.Join());
- writer.WriteLine();
- }
- // Direct (static) imports.
- int direct = 0;
- foreach (var function in functions)
- {
- if (function.Index == -1)
- direct++;
- }
- // Emit direct imports.
- if (direct > 0)
- {
- foreach (var function in functions)
- {
- if (function.Index != -1)
- continue;
- var name = function.Name;
- var data = function.Data;
- writer.Write("GLAPI " + name.Join() + " GLAPIENTRY " + name.Name + " (");
- for (int i = 0, n = data.Count; i < n; i++)
- {
- if (i > 0)
- writer.Write(", ");
- writer.Write(data[i].Join() + " " + data[i].Name);
- }
- writer.WriteLine(");");
- }
- writer.WriteLine();
- }
- // Emit dynamic imports.
- if (index > 0)
- {
- foreach (var function in functions)
- {
- if (function.Index == -1)
- continue;
- writer.WriteLine("#define " + Pad("IDX" + function.Name.Name.ToUpper() + "PROC", 60) + " " + function.Index);
- }
- writer.WriteLine();
- writer.WriteLine("// OpenGL function pointers.");
- writer.WriteLine("extern void* PFNGL[" + index + "];");
- writer.WriteLine();
- int count = 0;
- foreach (var function in functions)
- {
- if (function.Index == -1)
- continue;
- var name = function.Name;
- var data = function.Data;
- writer.Write("inline " + name.Join() + " " + name.Name + " (");
- for (int i = 0, n = data.Count; i < n; i++)
- {
- if (i > 0)
- writer.Write(", ");
- writer.Write(data[i].Join() + " " + data[i].Name);
- }
- writer.WriteLine(") {");
- writer.Write(" ");
- if (!function.IsVoid())
- writer.Write("return ");
- writer.Write("((" + name.Join() + " (GLAPIENTRY *)(");
- for (int i = 0, n = data.Count; i < n; i++)
- {
- if (i > 0)
- writer.Write(", ");
- writer.Write(data[i].Join());
- }
- writer.Write(")) PFNGL[" + function.Index + "]) (");
- for (int i = 0, n = data.Count; i < n; i++)
- {
- if (i > 0)
- writer.Write(", ");
- writer.Write(data[i].Name);
- }
- writer.WriteLine(");");
- writer.WriteLine("}");
- // Be a Newline-Nazi!
- if (++count < index)
- writer.WriteLine();
- }
- }
- Console.WriteLine(types.Count + " types.");
- Console.WriteLine(constants.Count + " constants.");
- Console.WriteLine(functions.Count + " functions (" + (functions.Count - index) + " static, " + index + " dynamic).");
- }
- /// <summary>
- /// Writes the source file.
- /// </summary>
- /// <param name="writer">Destination stream.</param>
- public void WriteSource(StreamWriter writer)
- {
- if (index == 0)
- {
- writer.WriteLine("// There may be dragons.");
- writer.WriteLine("// Nothing to generate.");
- return;
- }
- writer.WriteLine("#include <Windows.h>");
- writer.WriteLine();
- writer.WriteLine("// Function pointers.");
- writer.WriteLine("void* PFNGL[" + index + "];");
- writer.WriteLine();
- writer.WriteLine("// Function names.");
- writer.WriteLine("static const char* names[" + index + "] = {");
- foreach (var function in functions)
- {
- if (function.Index == -1)
- continue;
- writer.WriteLine(" \"" + function.Name.Name + "\",");
- }
- writer.WriteLine("};");
- writer.WriteLine();
- writer.WriteLine("// Load function pointers.");
- writer.WriteLine("void LoadGL() {");
- writer.WriteLine(" for (int i = 0; i < " + index + "; i++) {");
- writer.WriteLine(" PFNGL[i] = wglGetProcAddress(names[i]);");
- writer.WriteLine(" }");
- writer.WriteLine("}");
- }
- /// <summary>
- /// Parses a single constant.
- /// </summary>
- /// <param name="line">Current line.</param>
- private void ParseConstant(String line)
- {
- var tokens = Split(line, null);
- if (tokens.Count < 3)
- Panic("invalid #define");
- tokens.RemoveFirst();
- constants.Add(new Named(tokens.PopFirst(), tokens));
- }
- /// <summary>
- /// Parses a named parameter.
- /// </summary>
- /// <param name="line">Current line.</param>
- /// <returns>Named parmeter.</returns>
- private Named ParseNamed(String line)
- {
- var tokens = Split(line, null);
- if (tokens.Count < 2)
- Panic("invalid type and name");
- return new Named(tokens.PopLast(), tokens);
- }
- /// <summary>
- /// Parses a function entry point.
- /// </summary>
- /// <param name="line">Current line.</param>
- private void ParseFunction(String line)
- {
- int lp = line.IndexOf("(");
- int rp = line.IndexOf(")");
- if (lp == -1 || rp == -1 || rp < lp)
- Panic("invalid function prototype");
- var name = ParseNamed(line.Substring(0, lp));
- var data = new List<Named>();
- var guard = false;
- foreach (var token in Split(line.Substring(lp + 1, rp - lp - 1), ","))
- {
- if (token.Equals("void") || token.Equals("GLvoid"))
- {
- if (data.Count > 0)
- Panic("invalid usage of void or GLvoid");
- guard = true;
- }
- else
- {
- if (guard)
- Panic("additional parameters after void or GLvoid");
- data.Add(ParseNamed(token));
- }
- }
- functions.Add(new Function(name, data, dynamic ? index++ : -1));
- }
- /// <summary>
- /// Throws an annotated error.
- /// </summary>
- /// <param name="msg">Error message.</param>
- private void Panic(String msg)
- {
- throw new ApplicationException(file + " [" + current + "] " + msg);
- }
- /// <summary>
- /// Splits a string into components.
- /// </summary>
- /// <param name="line">Current line.</param>
- /// <param name="delimiters">Optional delimiters.</param>
- /// <returns></returns>
- private static StringList Split(String line, String delimiters)
- {
- var tokens = line.Split(delimiters == null ? null : delimiters.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
- var result = new StringList();
- foreach (var token in tokens)
- result.AddLast(token.Trim());
- return result;
- }
- /// <summary>
- /// String prefix test.
- /// </summary>
- /// <param name="line">Current line.</param>
- /// <param name="prefix">Prefix value.</param>
- /// <returns>True on success.</returns>
- private static bool StartsWith(String line, String prefix)
- {
- if (line.StartsWith(prefix))
- return line.Length == prefix.Length || Char.IsWhiteSpace(line[prefix.Length]);
- return false;
- }
- /// <summary>
- /// Pad string to length.
- /// </summary>
- /// <param name="what">String to pad.</param>
- /// <param name="count">Result count.</param>
- /// <returns>Padded string.</returns>
- private static String Pad(String what, int count)
- {
- StringBuilder builder = new StringBuilder(what);
- for (int i = 0, n = count - what.Length; i < n; i++)
- builder.Append(" ");
- return builder.ToString();
- }
- }
- class Program
- {
- static void Main(string[] args)
- {
- if (args.Length == 0)
- {
- Console.WriteLine("Usage: Glue [template] [name]");
- Console.WriteLine();
- Console.WriteLine("Parses the [template] and outputs [name].hpp and [name].cpp OpenGL function loader.");
- Console.WriteLine("Use #pragma static|dynamic to toggle desired linkage.");
- Console.WriteLine("Initial state when parsing a template is static.");
- Console.WriteLine();
- Console.WriteLine("This is intended for 64K intros, so have fun!");
- Console.WriteLine("Hakuna Matata, EvilOne");
- Environment.Exit(0);
- }
- if (args.Length < 2)
- {
- Console.Error.WriteLine("invalid command line arguments");
- Environment.Exit(1);
- }
- try
- {
- Generator generator = new Generator();
- for (int i = 0; i < args.Length - 1; i++)
- generator.Add(args[i]);
- using (StreamWriter writer = new StreamWriter(args[args.Length - 1] + ".hpp"))
- generator.WriteHeader(writer);
- using (StreamWriter writer = new StreamWriter(args[args.Length - 1] + ".cpp"))
- generator.WriteSource(writer);
- Environment.Exit(0);
- }
- catch (Exception e)
- {
- Console.Error.WriteLine(e.Message);
- Environment.Exit(1);
- }
- }
- }
- }
- // example.cmd
- @echo off
- Glue
- echo.
- Glue example.txt example
- echo.
- pause
- // example.txt
- typedef unsigned int GLenum;
- typedef unsigned char GLboolean;
- typedef unsigned int GLbitfield;
- typedef signed char GLbyte;
- typedef short GLshort;
- typedef int GLint;
- typedef int GLsizei;
- typedef unsigned char GLubyte;
- typedef unsigned short GLushort;
- typedef unsigned int GLuint;
- typedef float GLfloat;
- typedef float GLclampf;
- typedef double GLdouble;
- typedef double GLclampd;
- typedef void GLvoid;
- typedef char GLchar;
- typedef ptrdiff_t GLintptr;
- typedef ptrdiff_t GLsizeiptr;
- #define GL_FRAGMENT_SHADER 0x8B30
- #define GL_VERTEX_SHADER 0x8B31
- #define GL_GEOMETRY_SHADER 0x8DD9
- #pragma static
- void glTexImage1D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
- void glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
- #pragma dynamic
- void glCompileShader (GLuint shader);
- GLuint glCreateProgram (void);
- GLuint glCreateShader (GLenum type);
- void glDeleteProgram (GLuint program);
- void glDeleteShader (GLuint shader);
- void glDetachShader (GLuint program, GLuint shader);
- void glGetProgramiv (GLuint program, GLenum pname, GLint *params);
- void glGetProgramInfoLog (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
- void glGetShaderiv (GLuint shader, GLenum pname, GLint *params);
- void glGetShaderInfoLog (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
- void glLinkProgram (GLuint program);
- void glShaderSource (GLuint shader, GLsizei count, const GLchar* const *string, const GLint *length);
- void glUseProgram (GLuint program);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement