blob: 3428b49e1667a8204d5ae1fb51292be83d436a51 [file] [log] [blame]
/*
* Mesa 3-D graphics library
* Version: 6.5.3
*
* Copyright (C) 2005-2007 Brian Paul All Rights Reserved.
*
* 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 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
* BRIAN PAUL 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 slang_compile_variable.c
* slang front-end compiler
* \author Michal Krol
*/
#include "main/imports.h"
#include "slang_compile.h"
#include "slang_mem.h"
typedef struct
{
const char *name;
slang_type_specifier_type type;
} type_specifier_type_name;
static const type_specifier_type_name type_specifier_type_names[] = {
{"void", SLANG_SPEC_VOID},
{"bool", SLANG_SPEC_BOOL},
{"bvec2", SLANG_SPEC_BVEC2},
{"bvec3", SLANG_SPEC_BVEC3},
{"bvec4", SLANG_SPEC_BVEC4},
{"int", SLANG_SPEC_INT},
{"ivec2", SLANG_SPEC_IVEC2},
{"ivec3", SLANG_SPEC_IVEC3},
{"ivec4", SLANG_SPEC_IVEC4},
{"float", SLANG_SPEC_FLOAT},
{"vec2", SLANG_SPEC_VEC2},
{"vec3", SLANG_SPEC_VEC3},
{"vec4", SLANG_SPEC_VEC4},
{"mat2", SLANG_SPEC_MAT2},
{"mat3", SLANG_SPEC_MAT3},
{"mat4", SLANG_SPEC_MAT4},
{"mat2x3", SLANG_SPEC_MAT23},
{"mat3x2", SLANG_SPEC_MAT32},
{"mat2x4", SLANG_SPEC_MAT24},
{"mat4x2", SLANG_SPEC_MAT42},
{"mat3x4", SLANG_SPEC_MAT34},
{"mat4x3", SLANG_SPEC_MAT43},
{"sampler1D", SLANG_SPEC_SAMPLER1D},
{"sampler2D", SLANG_SPEC_SAMPLER2D},
{"sampler3D", SLANG_SPEC_SAMPLER3D},
{"samplerCube", SLANG_SPEC_SAMPLERCUBE},
{"sampler1DShadow", SLANG_SPEC_SAMPLER1DSHADOW},
{"sampler2DShadow", SLANG_SPEC_SAMPLER2DSHADOW},
{"sampler2DRect", SLANG_SPEC_SAMPLER2DRECT},
{"sampler2DRectShadow", SLANG_SPEC_SAMPLER2DRECTSHADOW},
{NULL, SLANG_SPEC_VOID}
};
slang_type_specifier_type
slang_type_specifier_type_from_string(const char *name)
{
const type_specifier_type_name *p = type_specifier_type_names;
while (p->name != NULL) {
if (slang_string_compare(p->name, name) == 0)
break;
p++;
}
return p->type;
}
const char *
slang_type_specifier_type_to_string(slang_type_specifier_type type)
{
const type_specifier_type_name *p = type_specifier_type_names;
while (p->name != NULL) {
if (p->type == type)
break;
p++;
}
return p->name;
}
/* slang_fully_specified_type */
int
slang_fully_specified_type_construct(slang_fully_specified_type * type)
{
type->qualifier = SLANG_QUAL_NONE;
slang_type_specifier_ctr(&type->specifier);
return 1;
}
void
slang_fully_specified_type_destruct(slang_fully_specified_type * type)
{
slang_type_specifier_dtr(&type->specifier);
}
int
slang_fully_specified_type_copy(slang_fully_specified_type * x,
const slang_fully_specified_type * y)
{
slang_fully_specified_type z;
if (!slang_fully_specified_type_construct(&z))
return 0;
z.qualifier = y->qualifier;
if (!slang_type_specifier_copy(&z.specifier, &y->specifier)) {
slang_fully_specified_type_destruct(&z);
return 0;
}
slang_fully_specified_type_destruct(x);
*x = z;
return 1;
}
static slang_variable *
slang_variable_new(void)
{
slang_variable *v = (slang_variable *) _slang_alloc(sizeof(slang_variable));
if (v) {
if (!slang_variable_construct(v)) {
_slang_free(v);
v = NULL;
}
}
return v;
}
static void
slang_variable_delete(slang_variable * var)
{
slang_variable_destruct(var);
_slang_free(var);
}
/*
* slang_variable_scope
*/
slang_variable_scope *
_slang_variable_scope_new(slang_variable_scope *parent)
{
slang_variable_scope *s;
s = (slang_variable_scope *) _slang_alloc(sizeof(slang_variable_scope));
if (s)
s->outer_scope = parent;
return s;
}
GLvoid
_slang_variable_scope_ctr(slang_variable_scope * self)
{
self->variables = NULL;
self->num_variables = 0;
self->outer_scope = NULL;
}
void
slang_variable_scope_destruct(slang_variable_scope * scope)
{
unsigned int i;
if (!scope)
return;
for (i = 0; i < scope->num_variables; i++) {
if (scope->variables[i])
slang_variable_delete(scope->variables[i]);
}
_slang_free(scope->variables);
/* do not free scope->outer_scope */
}
int
slang_variable_scope_copy(slang_variable_scope * x,
const slang_variable_scope * y)
{
slang_variable_scope z;
unsigned int i;
_slang_variable_scope_ctr(&z);
z.variables = (slang_variable **)
_slang_alloc(y->num_variables * sizeof(slang_variable *));
if (z.variables == NULL) {
slang_variable_scope_destruct(&z);
return 0;
}
for (z.num_variables = 0; z.num_variables < y->num_variables;
z.num_variables++) {
z.variables[z.num_variables] = slang_variable_new();
if (!z.variables[z.num_variables]) {
slang_variable_scope_destruct(&z);
return 0;
}
}
for (i = 0; i < z.num_variables; i++) {
if (!slang_variable_copy(z.variables[i], y->variables[i])) {
slang_variable_scope_destruct(&z);
return 0;
}
}
z.outer_scope = y->outer_scope;
slang_variable_scope_destruct(x);
*x = z;
return 1;
}
/**
* Grow the variable list by one.
* \return pointer to space for the new variable (will be initialized)
*/
slang_variable *
slang_variable_scope_grow(slang_variable_scope *scope)
{
const int n = scope->num_variables;
scope->variables = (slang_variable **)
_slang_realloc(scope->variables,
n * sizeof(slang_variable *),
(n + 1) * sizeof(slang_variable *));
if (!scope->variables)
return NULL;
scope->num_variables++;
scope->variables[n] = slang_variable_new();
if (!scope->variables[n])
return NULL;
return scope->variables[n];
}
/* slang_variable */
int
slang_variable_construct(slang_variable * var)
{
if (!slang_fully_specified_type_construct(&var->type))
return 0;
var->a_name = SLANG_ATOM_NULL;
var->array_len = 0;
var->initializer = NULL;
var->address = ~0;
var->size = 0;
var->isTemp = GL_FALSE;
var->aux = NULL;
var->declared = 0;
return 1;
}
void
slang_variable_destruct(slang_variable * var)
{
slang_fully_specified_type_destruct(&var->type);
if (var->initializer != NULL) {
slang_operation_destruct(var->initializer);
_slang_free(var->initializer);
}
#if 0
if (var->aux) {
_mesa_free(var->aux);
}
#endif
}
int
slang_variable_copy(slang_variable * x, const slang_variable * y)
{
slang_variable z;
if (!slang_variable_construct(&z))
return 0;
if (!slang_fully_specified_type_copy(&z.type, &y->type)) {
slang_variable_destruct(&z);
return 0;
}
z.a_name = y->a_name;
z.array_len = y->array_len;
if (y->initializer != NULL) {
z.initializer
= (slang_operation *) _slang_alloc(sizeof(slang_operation));
if (z.initializer == NULL) {
slang_variable_destruct(&z);
return 0;
}
if (!slang_operation_construct(z.initializer)) {
_slang_free(z.initializer);
slang_variable_destruct(&z);
return 0;
}
if (!slang_operation_copy(z.initializer, y->initializer)) {
slang_variable_destruct(&z);
return 0;
}
}
z.address = y->address;
z.size = y->size;
slang_variable_destruct(x);
*x = z;
return 1;
}
/**
* Search for named variable in given scope.
* \param all if true, search parent scopes too.
*/
slang_variable *
_slang_locate_variable(const slang_variable_scope * scope,
const slang_atom a_name, GLboolean all)
{
while (scope) {
GLuint i;
for (i = 0; i < scope->num_variables; i++)
if (a_name == scope->variables[i]->a_name)
return scope->variables[i];
if (all)
scope = scope->outer_scope;
else
scope = NULL;
}
return NULL;
}