Commit a87ac255 authored by Ian Romanick's avatar Ian Romanick

Initial commit. lol

parents
((c-mode . ((c-basic-offset . 3))))
CSRCS = symbol_table.c hash_table.c glsl_types.c
CCSRCS = glsl_parser.tab.cc glsl_lexer.cc glsl_parser_extras.cc
# ast_to_hir.cc ir.cc hir_field_selection.cc
OBJS = $(CSRCS:.c=.o) $(CCSRCS:.cc=.o)
CC = gcc
CXX = g++
WARN = -Wall -Wextra -Wunsafe-loop-optimizations -Wstack-protector \
-Wunreachable-code
CPPFLAGS = -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE
CFLAGS = -O0 -ggdb3 -fstack-protector $(CPPFLAGS) $(WARN) -std=c89 -ansi -pedantic
CXXFLAGS = -O0 -ggdb3 -fstack-protector $(CPPFLAGS) $(WARN)
LDLAGS = -ggdb3
glsl: $(OBJS)
$(CXX) $(LDLAGS) $(OBJS) -o glsl
glsl_parser.tab.cc glsl_parser.tab.h: glsl_parser.y
bison --report-file=glsl_parser.output -v -d \
--output=glsl_parser.tab.cc \
--name-prefix=_mesa_glsl_ $< && \
mv glsl_parser.tab.hh glsl_parser.tab.h
glsl_lexer.cc: glsl_lexer.l
flex --outfile="glsl_lexer.cc" $<
glsl_parser_tab.o: glsl_parser.tab.cc
glsl_types.o: glsl_types.c glsl_types.h builtin_types.h
glsl_lexer.o: glsl_lexer.cc glsl_parser.tab.h glsl_parser_extras.h ast.h
glsl_parser.o: glsl_parser_extras.h ast.h
ast_to_hir.o: ast_to_hir.cc symbol_table.h glsl_parser_extras.h ast.h glsl_types.h ir.h
builtin_types.h: builtin_types.sh
./builtin_types.sh > builtin_types.h
clean:
rm -f $(OBJS) glsl
rm -f glsl_lexer.cc glsl_parser.tab.{cc,h,hh} glsl_parser.output
rm -f builtin_types.h
rm -f *~
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
%{
/*
* Copyright © 2008, 2009 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "ast.h"
#include "glsl_parser_extras.h"
#include "glsl_parser.tab.h"
#include "symbol_table.h"
#define YY_USER_ACTION \
do { \
yylloc->source = 0; \
yylloc->first_column = yycolumn + 1; \
yylloc->first_line = yylineno + 1; \
yycolumn += yyleng; \
} while(0);
%}
%option bison-bridge bison-locations reentrant noyywrap
%option never-interactive
%option prefix="_mesa_glsl_"
%option extra-type="struct _mesa_glsl_parse_state *"
%option stack
%x PP COMMENT
%%
"/*" { yy_push_state(COMMENT, yyscanner); }
<COMMENT>[^*\n]*
<COMMENT>[^*\n]*\n { yylineno++; yycolumn = 0; }
<COMMENT>"*"+[^*/\n]*
<COMMENT>"*"+[^*/\n]*\n { yylineno++; yycolumn = 0; }
<COMMENT>"*"+"/" { yy_pop_state(yyscanner); }
\/\/.*\n { yylineno++; yycolumn = 0; }
[ \r\t]+ ;
/* Preprocessor tokens. */
^[ \t]*#[ \t]*$ ;
^[ \t]*#[ \t]*version { BEGIN PP; return VERSION; }
^[ \t]*#[ \t]*extension { BEGIN PP; return EXTENSION; }
^[ \t]*#[ \t]*line { BEGIN PP; return LINE; }
^[ \t]*#[ \t]*pragma { BEGIN PP; return PRAGMA; }
<PP>: return COLON;
<PP>[_a-zA-Z][_a-zA-Z0-9]* {
yylval->identifier = strdup(yytext);
return IDENTIFIER;
}
<PP>[1-9][0-9]* {
yylval->n = strtol(yytext, NULL, 10);
return INTCONSTANT;
}
<PP>\n { BEGIN 0; yylineno++; yycolumn = 0; return EOL; }
\n { yylineno++; yycolumn = 0; }
attribute return ATTRIBUTE;
const return CONST;
bool return BOOL;
float return FLOAT;
int return INT;
break return BREAK;
continue return CONTINUE;
do return DO;
while return WHILE;
else return ELSE;
for return FOR;
if return IF;
discard return DISCARD;
return return RETURN;
bvec2 return BVEC2;
bvec3 return BVEC3;
bvec4 return BVEC4;
ivec2 return IVEC2;
ivec3 return IVEC3;
ivec4 return IVEC4;
vec2 return VEC2;
vec3 return VEC3;
vec4 return VEC4;
mat2 return MAT2;
mat3 return MAT3;
mat4 return MAT4;
mat2x2 return MAT2X2;
mat2x3 return MAT2X3;
mat2x4 return MAT2X4;
mat3x2 return MAT3X2;
mat3x3 return MAT3X3;
mat3x4 return MAT3X4;
mat4x2 return MAT4X2;
mat4x3 return MAT4X3;
mat4x4 return MAT4X4;
in return IN;
out return OUT;
inout return INOUT;
uniform return UNIFORM;
varying return VARYING;
centroid return CENTROID;
invariant return INVARIANT;
sampler1D return SAMPLER1D;
sampler2D return SAMPLER2D;
sampler3D return SAMPLER3D;
samplerCube return SAMPLERCUBE;
sampler1DShadow return SAMPLER1DSHADOW;
sampler2DShadow return SAMPLER2DSHADOW;
struct return STRUCT;
void return VOID;
\+\+ return INC_OP;
-- return DEC_OP;
\<= return LE_OP;
>= return GE_OP;
== return EQ_OP;
!= return NE_OP;
&& return AND_OP;
\|\| return OR_OP;
"^^" return XOR_OP;
\*= return MUL_ASSIGN;
\/= return DIV_ASSIGN;
\+= return ADD_ASSIGN;
\%= return MOD_ASSIGN;
\<\<= return LEFT_ASSIGN;
>>= return RIGHT_ASSIGN;
&= return AND_ASSIGN;
^= return XOR_ASSIGN;
\|= return OR_ASSIGN;
-= return SUB_ASSIGN;
[1-9][0-9]* {
yylval->n = strtol(yytext, NULL, 10);
return INTCONSTANT;
}
0[xX][0-9a-fA-F]+ {
yylval->n = strtol(yytext + 2, NULL, 16);
return INTCONSTANT;
}
0[0-7]* {
yylval->n = strtol(yytext + 2, NULL, 8);
return INTCONSTANT;
}
[0-9]+\.[0-9]+([eE][+-]?[0-9]+)?[fF]? {
yylval->real = strtod(yytext, NULL);
return FLOATCONSTANT;
}
\.[0-9]+([eE][+-]?[0-9]+)?[fF]? {
yylval->real = strtod(yytext, NULL);
return FLOATCONSTANT;
}
[0-9]+\.([eE][+-]?[0-9]+)?[fF]? {
yylval->real = strtod(yytext, NULL);
return FLOATCONSTANT;
}
[0-9]+[eE][+-]?[0-9]+[fF]? {
yylval->real = strtod(yytext, NULL);
return FLOATCONSTANT;
}
true {
yylval->n = 1;
return BOOLCONSTANT;
}
false {
yylval->n = 0;
return BOOLCONSTANT;
}
/* Reserved words in GLSL 1.10. */
asm return ASM;
class return CLASS;
union return UNION;
enum return ENUM;
typedef return TYPEDEF;
template return TEMPLATE;
this return THIS;
packed return PACKED;
goto return GOTO;
switch return SWITCH;
default return DEFAULT;
inline return INLINE;
noinline return NOINLINE;
volatile return VOLATILE;
public return PUBLIC;
static return STATIC;
extern return EXTERN;
external return EXTERNAL;
interface return INTERFACE;
long return LONG;
short return SHORT;
double return DOUBLE;
half return HALF;
fixed return FIXED;
unsigned return UNSIGNED;
input return INPUT;
output return OUTPUT;
hvec2 return HVEC2;
hvec3 return HVEC3;
hvec4 return HVEC4;
dvec2 return DVEC2;
dvec3 return DVEC3;
dvec4 return DVEC4;
fvec2 return FVEC2;
fvec3 return FVEC3;
fvec4 return FVEC4;
sampler2DRect return SAMPLER2DRECT;
sampler3DRect return SAMPLER3DRECT;
sampler2DRectShadow return SAMPLER2DRECTSHADOW;
sizeof return SIZEOF;
cast return CAST;
namespace return NAMESPACE;
using return USING;
/* Additional reserved words in GLSL 1.20. */
lowp return LOWP;
mediump return MEDIUMP;
highp return HIGHP;
precision return PRECISION;
[_a-zA-Z][_a-zA-Z0-9]* {
yylval->identifier = strdup(yytext);
if (_mesa_symbol_table_find_symbol(yyextra->symbols,
0,
yylval->identifier))
return TYPE_NAME;
else
return IDENTIFIER;
}
. { return yytext[0]; }
%%
void
_mesa_glsl_lexer_ctor(struct _mesa_glsl_parse_state *state,
const char *string, size_t len)
{
yylex_init_extra(state, & state->scanner);
yy_scan_bytes(string, len, state->scanner);
}
void
_mesa_glsl_lexer_dtor(struct _mesa_glsl_parse_state *state)
{
yylex_destroy(state->scanner);
}
This diff is collapsed.
This diff is collapsed.
/*
* Copyright © 2010 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#pragma once
#ifndef GLSL_PARSER_EXTRAS_H
#define GLSL_PARSER_EXTRAS_H
#include "main/simple_list.h"
enum _mesa_glsl_parser_targets {
vertex_shader,
geometry_shader,
fragment_shader
};
struct _mesa_glsl_parse_state {
void *scanner;
struct simple_node translation_unit;
struct _mesa_symbol_table *symbols;
unsigned language_version;
enum _mesa_glsl_parser_targets target;
};
typedef struct YYLTYPE {
int first_line;
int first_column;
int last_line;
int last_column;
unsigned source;
} YYLTYPE;
# define YYLTYPE_IS_DECLARED 1
# define YYLTYPE_IS_TRIVIAL 1
extern void _mesa_glsl_error(YYLTYPE *locp, void *state, const char *fmt, ...);
extern void _mesa_glsl_lexer_ctor(struct _mesa_glsl_parse_state *state,
const char *string, size_t len);
extern void _mesa_glsl_lexer_dtor(struct _mesa_glsl_parse_state *state);
union YYSTYPE;
extern int _mesa_glsl_lex(union YYSTYPE *yylval, YYLTYPE *yylloc,
void *scanner);
extern int _mesa_glsl_parse(struct _mesa_glsl_parse_state *);
#endif /* GLSL_PARSER_EXTRAS_H */
/*
* Copyright © 2009 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include <stdlib.h>
#include "symbol_table.h"
#include "glsl_parser_extras.h"
#include "glsl_types.h"
#include "builtin_types.h"
struct glsl_type *
_mesa_glsl_array_type_ctor(struct glsl_type *base, unsigned length,
const char *name)
{
struct glsl_type *type = calloc(1, sizeof(*type));
type->base_type = GLSL_TYPE_ARRAY;
type->name = name;
type->length = length;
type->fields.array = base;
return type;
}
static void
add_types_to_symbol_table(struct _mesa_symbol_table *symtab,
const struct glsl_type *types,
unsigned num_types)
{
unsigned i;
for (i = 0; i < num_types; i++) {
_mesa_symbol_table_add_symbol(symtab, 0, types[i].name,
(void *) & types[i]);
}
}
static void
generate_110_types(struct _mesa_symbol_table *symtab)
{
add_types_to_symbol_table(symtab, builtin_core_types,
Elements(builtin_core_types));
add_types_to_symbol_table(symtab, builtin_structure_types,
Elements(builtin_structure_types));
add_types_to_symbol_table(symtab, builtin_110_deprecated_structure_types,
Elements(builtin_110_deprecated_structure_types));
}
static void
generate_120_types(struct _mesa_symbol_table *symtab)
{
generate_110_types(symtab);
add_types_to_symbol_table(symtab, builtin_120_types,
Elements(builtin_120_types));
}
static void
generate_130_types(struct _mesa_symbol_table *symtab)
{
generate_120_types(symtab);
add_types_to_symbol_table(symtab, builtin_130_types,
Elements(builtin_130_types));
}
void
_mesa_glsl_initialize_types(struct _mesa_glsl_parse_state *state)
{
switch (state->language_version) {
case 110:
generate_110_types(state->symbols);
break;
case 120:
generate_120_types(state->symbols);
break;
case 130:
generate_130_types(state->symbols);
break;
default:
/* error */
break;
}
}
const struct glsl_type *
_mesa_glsl_get_vector_type(unsigned base_type, unsigned vector_length)
{
switch (base_type) {
case GLSL_TYPE_UINT:
switch (vector_length) {
case 1:
case 2:
case 3:
case 4:
return glsl_uint_type + (vector_length - 1);
default:
return glsl_error_type;
}
case GLSL_TYPE_INT:
switch (vector_length) {
case 1:
case 2:
case 3:
case 4:
return glsl_int_type + (vector_length - 1);
default:
return glsl_error_type;
}
case GLSL_TYPE_FLOAT:
switch (vector_length) {
case 1:
case 2:
case 3:
case 4:
return glsl_float_type + (vector_length - 1);
default:
return glsl_error_type;
}
case GLSL_TYPE_BOOL:
switch (vector_length) {
case 1:
case 2:
case 3:
case 4:
return glsl_bool_type + (vector_length - 1);
default:
return glsl_error_type;
}
default:
return glsl_error_type;
}
}
/*
* Copyright © 2009 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#pragma once
#ifndef GLSL_TYPES_H
#define GLSL_TYPES_H
#define GLSL_TYPE_UINT 0
#define GLSL_TYPE_INT 1
#define GLSL_TYPE_FLOAT 2
#define GLSL_TYPE_BOOL 3
#define GLSL_TYPE_SAMPLER 4
#define GLSL_TYPE_STRUCT 5
#define GLSL_TYPE_ARRAY 6
#define GLSL_TYPE_FUNCTION 7
#define GLSL_TYPE_VOID 8
#define GLSL_TYPE_ERROR 9
#define is_numeric_base_type(b) \
(((b) >= GLSL_TYPE_UINT) && ((b) <= GLSL_TYPE_FLOAT))
#define is_integer_base_type(b) \
(((b) == GLSL_TYPE_UINT) || ((b) == GLSL_TYPE_INT))
#define is_error_type(t) ((t)->base_type == GLSL_TYPE_ERROR)
#define GLSL_SAMPLER_DIM_1D 0
#define GLSL_SAMPLER_DIM_2D 1
#define GLSL_SAMPLER_DIM_3D 2
#define GLSL_SAMPLER_DIM_CUBE 3
#define GLSL_SAMPLER_DIM_RECT 4
#define GLSL_SAMPLER_DIM_BUF 5
struct glsl_type {
unsigned base_type:4;
unsigned sampler_dimensionality:3;
unsigned sampler_shadow:1;
unsigned sampler_array:1;
unsigned sampler_type:2; /**< Type of data returned using this sampler.
* only \c GLSL_TYPE_FLOAT, \c GLSL_TYPE_INT,
* and \c GLSL_TYPE_UINT are valid.
*/
unsigned vector_elements:3; /**< 0, 2, 3, or 4 vector elements. */
unsigned matrix_rows:3; /**< 0, 2, 3, or 4 matrix rows. */
/**
* Name of the data type
*
* This may be \c NULL for anonymous structures, for arrays, or for
* function types.
*/
const char *name;
/**
* For \c GLSL_TYPE_ARRAY, this is the length of the array. For
* \c GLSL_TYPE_STRUCT, it is the number of elements in the structure and
* the number of values pointed to by \c fields.structure (below).
*
* For \c GLSL_TYPE_FUNCTION, it is the number of parameters to the
* function. The return value from a function is implicitly the first
* parameter. The types of the parameters are stored in
* \c fields.parameters (below).
*/
unsigned length;
/**
* Subtype of composite data types.
*/
union {
const struct glsl_type *array; /**< Type of array elements. */
const struct glsl_type *parameters; /**< Parameters to function. */
const struct glsl_struct_field *structure;/**< List of struct fields. */
} fields;
};
#define is_glsl_type_scalar(t) \
(((t)->vector_elements == 0) \
&& ((t)->base_type >= GLSL_TYPE_UINT) \
&& ((t)->base_type <= GLSL_TYPE_BOOL))
#define is_glsl_type_vector(t) \
(((t)->vector_elements > 0) \
&& ((t)->matrix_rows == 0) \
&& ((t)->base_type >= GLSL_TYPE_UINT) \
&& ((t)->base_type <= GLSL_TYPE_BOOL))
#define is_glsl_type_matrix(t) \
(((t)->matrix_rows > 0) \
&& ((t)->base_type == GLSL_TYPE_FLOAT)) /* GLSL only has float matrices. */
struct glsl_struct_field {
const struct glsl_type *type;
const char *name;
};
struct _mesa_glsl_parse_state;
#ifdef __cplusplus
extern "C" {
#endif
extern void
_mesa_glsl_initialize_types(struct _mesa_glsl_parse_state *state);
extern const struct glsl_type *
_mesa_glsl_get_vector_type(unsigned base_type, unsigned vector_length);
extern const struct glsl_type *const glsl_error_type;
extern const struct glsl_type *const glsl_int_type;
extern const struct glsl_type *const glsl_uint_type;
extern const struct glsl_type *const glsl_float_type;
extern const struct glsl_type *const glsl_bool_type;
#ifdef __cplusplus
}
#endif
#endif /* GLSL_TYPES_H */
/*
* Copyright © 2008 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
/**
* \file hash_table.c
* \brief Implementation of a generic, opaque hash table data type.
*
* \author Ian Romanick <ian.d.romanick@intel.com>
*/
#include "main/imports.h"
#include "main/simple_list.h"
#include "hash_table.h"
struct node {
struct node *next;
struct node *prev;
};
struct hash_table {
hash_func_t hash;
hash_compare_func_t compare;
unsigned num_buckets;
struct node buckets[1];
};
struct hash_node {
struct node link;
const void *key;
void *data;
};
struct hash_table *
hash_table_ctor(unsigned num_buckets, hash_func_t hash,
hash_compare_func_t compare)
{
struct hash_table *ht;
unsigned i;
if (num_buckets < 16) {
num_buckets = 16;
}
ht = _mesa_malloc(sizeof(*ht) + ((num_buckets - 1)
* sizeof(ht->buckets[0])));
if (ht != NULL) {
ht->hash = hash;
ht->compare = compare;
ht->num_buckets = num_buckets;
for (i = 0; i < num_buckets; i++) {
make_empty_list(& ht->buckets[i]);
}
}
return ht;
}