|
kusano |
7d535a |
package OpenGL::Spec;
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
# A very simple task further complicated by the fact that some people
|
|
kusano |
7d535a |
# can't read, others use legacy Operating Systems, and others don't give
|
|
kusano |
7d535a |
# a damn about using a halfway decent text editor.
|
|
kusano |
7d535a |
#
|
|
kusano |
7d535a |
# The code to parse the _template_ is so simple and straightforward...
|
|
kusano |
7d535a |
# yet the code to parse the real spec files is this mess.
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
my %typemap = (
|
|
kusano |
7d535a |
bitfield => "GLbitfield",
|
|
kusano |
7d535a |
boolean => "GLboolean",
|
|
kusano |
7d535a |
# fsck up in EXT_vertex_array
|
|
kusano |
7d535a |
Boolean => "GLboolean",
|
|
kusano |
7d535a |
byte => "GLbyte",
|
|
kusano |
7d535a |
clampd => "GLclampd",
|
|
kusano |
7d535a |
clampf => "GLclampf",
|
|
kusano |
7d535a |
double => "GLdouble",
|
|
kusano |
7d535a |
enum => "GLenum",
|
|
kusano |
7d535a |
# Intel fsck up
|
|
kusano |
7d535a |
Glenum => "GLenum",
|
|
kusano |
7d535a |
float => "GLfloat",
|
|
kusano |
7d535a |
half => "GLuint",
|
|
kusano |
7d535a |
int => "GLint",
|
|
kusano |
7d535a |
short => "GLshort",
|
|
kusano |
7d535a |
sizei => "GLsizei",
|
|
kusano |
7d535a |
ubyte => "GLubyte",
|
|
kusano |
7d535a |
uint => "GLuint",
|
|
kusano |
7d535a |
ushort => "GLushort",
|
|
kusano |
7d535a |
DMbuffer => "void *",
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
# ARB VBO introduces these
|
|
kusano |
7d535a |
sizeiptrARB => "GLsizeiptrARB",
|
|
kusano |
7d535a |
intptrARB => "GLintptrARB",
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
# ARB shader objects introduces these, charARB is at least 8 bits,
|
|
kusano |
7d535a |
# handleARB is at least 32 bits
|
|
kusano |
7d535a |
charARB => "GLcharARB",
|
|
kusano |
7d535a |
handleARB => "GLhandleARB",
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
# GLX 1.3 defines new types which might not be available at compile time
|
|
kusano |
7d535a |
#GLXFBConfig => "void*",
|
|
kusano |
7d535a |
#GLXFBConfigID => "XID",
|
|
kusano |
7d535a |
#GLXContextID => "XID",
|
|
kusano |
7d535a |
#GLXWindow => "XID",
|
|
kusano |
7d535a |
#GLXPbuffer => "XID",
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
# Weird stuff for some SGIX extension
|
|
kusano |
7d535a |
#GLXFBConfigSGIX => "void*",
|
|
kusano |
7d535a |
#GLXFBConfigIDSGIX => "XID",
|
|
kusano |
7d535a |
);
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
my %void_typemap = (
|
|
kusano |
7d535a |
void => "GLvoid",
|
|
kusano |
7d535a |
);
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
my $section_re = qr{^[A-Z]};
|
|
kusano |
7d535a |
my $function_re = qr{^(.+) ([a-z][a-z0-9_]*) \((.+)\)$}i;
|
|
kusano |
7d535a |
my $token_re = qr{^([A-Z0-9][A-Z0-9_]*):?\s+((?:0x)?[0-9A-F]+)(.*)$};
|
|
kusano |
7d535a |
my $prefix_re = qr{^(?:AGL | GLX | WGL)_}x;
|
|
kusano |
7d535a |
my $eofnc_re = qr{ \);?$ | ^$ }x;
|
|
kusano |
7d535a |
my $function_re = qr{^(.+) ([a-z][a-z0-9_]*) \((.+)\)$}i;
|
|
kusano |
7d535a |
my $prefix_re = qr{^(?:gl | agl | wgl | glX)}x;
|
|
kusano |
7d535a |
my $types_re = __compile_wordlist_cap(keys %typemap);
|
|
kusano |
7d535a |
my $voidtype_re = __compile_wordlist_cap(keys %void_typemap);
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
sub new($)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
my $class = shift;
|
|
kusano |
7d535a |
my $self = { section => {} };
|
|
kusano |
7d535a |
$self->{filename} = shift;
|
|
kusano |
7d535a |
local $/;
|
|
kusano |
7d535a |
open(my $fh, "<$self->{filename}") or die "Can't open $self->{filename}";
|
|
kusano |
7d535a |
my $content = <$fh>;
|
|
kusano |
7d535a |
my $section;
|
|
kusano |
7d535a |
my $s = $self->{section};
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
$content =~ s{[ \t]+$}{}mg;
|
|
kusano |
7d535a |
# Join lines that end with a word-character and ones that *begin*
|
|
kusano |
7d535a |
# with one
|
|
kusano |
7d535a |
$content =~ s{(\w)\n(\w)}{$1 $2}sg;
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
foreach (split /\n/, $content)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
if (/$section_re/)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
chomp;
|
|
kusano |
7d535a |
s/^Name String$/Name Strings/; # Fix common mistake
|
|
kusano |
7d535a |
$section = $_;
|
|
kusano |
7d535a |
$s->{$section} = "";
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
elsif (defined $section and exists $s->{$section})
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
s{^\s+}{}mg; # Remove leading whitespace
|
|
kusano |
7d535a |
$s->{$section} .= $_ . "\n";
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
$s->{$_} =~ s{(?:^\n+|\n+$)}{}s foreach keys %$s;
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
bless $self, $class;
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
sub sections()
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
my $self = shift;
|
|
kusano |
7d535a |
keys %{$self->{section}};
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
sub name()
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
my $self = shift;
|
|
kusano |
7d535a |
$self->{section}->{Name};
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
sub name_strings()
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
my $self = shift;
|
|
kusano |
7d535a |
split("\n", $self->{section}->{"Name Strings"});
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
sub tokens()
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
my $self = shift;
|
|
kusano |
7d535a |
my %tokens = ();
|
|
kusano |
7d535a |
foreach (split /\n/, $self->{section}->{"New Tokens"})
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
next unless /$token_re/;
|
|
kusano |
7d535a |
my ($name, $value) = ($1, $2);
|
|
kusano |
7d535a |
$name =~ s{^}{GL_} unless $name =~ /$prefix_re/;
|
|
kusano |
7d535a |
$tokens{$name} = $value;
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
return %tokens;
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
sub functions()
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
my $self = shift;
|
|
kusano |
7d535a |
my %functions = ();
|
|
kusano |
7d535a |
my @fnc = ();
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
foreach (split /\n/, $self->{section}->{"New Procedures and Functions"})
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
push @fnc, $_ unless ($_ eq "" or $_ eq "None");
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
next unless /$eofnc_re/;
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
if (__normalize_proto(@fnc) =~ /$function_re/)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
my ($return, $name, $parms) = ($1, $2, $3);
|
|
kusano |
7d535a |
if (!__ignore_function($name, $extname))
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
$name =~ s/^/gl/ unless $name =~ /$prefix_re/;
|
|
kusano |
7d535a |
if ($name =~ /^gl/ && $name !~ /^glX/)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
$return =~ s/$types_re/$typemap{$1}/g;
|
|
kusano |
7d535a |
$return =~ s/$voidtype_re/$void_typemap{$1}/g;
|
|
kusano |
7d535a |
$parms =~ s/$types_re/$typemap{$1}/g;
|
|
kusano |
7d535a |
$parms =~ s/$voidtype_re/$void_typemap{$1}/g;
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
$functions{$name} = {
|
|
kusano |
7d535a |
rtype => $return,
|
|
kusano |
7d535a |
parms => $parms,
|
|
kusano |
7d535a |
};
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
@fnc = ();
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
return %functions;
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
sub __normalize_proto
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
local $_ = join(" ", @_);
|
|
kusano |
7d535a |
s/\s+/ /g; # multiple whitespace -> single space
|
|
kusano |
7d535a |
s/\s*\(\s*/ \(/; # exactly one space before ( and none after
|
|
kusano |
7d535a |
s/\s*\)\s*/\)/; # no after before or after )
|
|
kusano |
7d535a |
s/\s*\*([a-zA-Z])/\* $1/; # "* identifier" XXX: g missing?
|
|
kusano |
7d535a |
s/\*wgl/\* wgl/; # "* wgl" XXX: why doesn't the
|
|
kusano |
7d535a |
s/\*glX/\* glX/; # "* glX" previous re catch this?
|
|
kusano |
7d535a |
s/\.\.\./void/; # ... -> void
|
|
kusano |
7d535a |
s/;$//; # remove ; at the end of the line
|
|
kusano |
7d535a |
return $_;
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
sub __ignore_function
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
return 0;
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
sub __compile_regex
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
my $regex = join('', @_);
|
|
kusano |
7d535a |
return qr/$regex/
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
sub __compile_wordlist_cap
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
__compile_regex('\b(', join('|', @_), ')\b');
|
|
kusano |
7d535a |
}
|