ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

slang_compile.c
Go to the documentation of this file.
00001 /*
00002  * Mesa 3-D graphics library
00003  *
00004  * Copyright (C) 2005-2006  Brian Paul   All Rights Reserved.
00005  * Copyright (C) 2008 VMware, Inc.  All Rights Reserved.
00006  *
00007  * Permission is hereby granted, free of charge, to any person obtaining a
00008  * copy of this software and associated documentation files (the "Software"),
00009  * to deal in the Software without restriction, including without limitation
00010  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00011  * and/or sell copies of the Software, and to permit persons to whom the
00012  * Software is furnished to do so, subject to the following conditions:
00013  *
00014  * The above copyright notice and this permission notice shall be included
00015  * in all copies or substantial portions of the Software.
00016  *
00017  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00018  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00019  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00020  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
00021  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00022  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00023  */
00024 
00031 #include "main/imports.h"
00032 #include "main/context.h"
00033 #include "shader/program.h"
00034 #include "shader/programopt.h"
00035 #include "shader/prog_print.h"
00036 #include "shader/prog_parameter.h"
00037 #include "shader/grammar/grammar_mesa.h"
00038 #include "slang_codegen.h"
00039 #include "slang_compile.h"
00040 #include "slang_preprocess.h"
00041 #include "slang_storage.h"
00042 #include "slang_emit.h"
00043 #include "slang_log.h"
00044 #include "slang_mem.h"
00045 #include "slang_vartable.h"
00046 #include "slang_simplify.h"
00047 
00048 #include "slang_print.h"
00049 
00050 /*
00051  * This is a straightforward implementation of the slang front-end
00052  * compiler.  Lots of error-checking functionality is missing but
00053  * every well-formed shader source should compile successfully and
00054  * execute as expected. However, some semantically ill-formed shaders
00055  * may be accepted resulting in undefined behaviour.
00056  */
00057 
00058 
00060 #define TYPE_SPECIFIER_COUNT 32
00061 
00062 
00066 static GLboolean
00067 legal_identifier(slang_atom name)
00068 {
00069    /* "gl_" is a reserved prefix */
00070    if (_mesa_strncmp((char *) name, "gl_", 3) == 0) {
00071       return GL_FALSE;
00072    }
00073    return GL_TRUE;
00074 }
00075 
00076 
00077 /*
00078  * slang_code_unit
00079  */
00080 
00081 GLvoid
00082 _slang_code_unit_ctr(slang_code_unit * self,
00083                      struct slang_code_object_ * object)
00084 {
00085    _slang_variable_scope_ctr(&self->vars);
00086    _slang_function_scope_ctr(&self->funs);
00087    _slang_struct_scope_ctr(&self->structs);
00088    self->object = object;
00089 }
00090 
00091 GLvoid
00092 _slang_code_unit_dtr(slang_code_unit * self)
00093 {
00094    slang_variable_scope_destruct(&self->vars);
00095    slang_function_scope_destruct(&self->funs);
00096    slang_struct_scope_destruct(&self->structs);
00097 }
00098 
00099 /*
00100  * slang_code_object
00101  */
00102 
00103 GLvoid
00104 _slang_code_object_ctr(slang_code_object * self)
00105 {
00106    GLuint i;
00107 
00108    for (i = 0; i < SLANG_BUILTIN_TOTAL; i++)
00109       _slang_code_unit_ctr(&self->builtin[i], self);
00110    _slang_code_unit_ctr(&self->unit, self);
00111    slang_atom_pool_construct(&self->atompool);
00112 }
00113 
00114 GLvoid
00115 _slang_code_object_dtr(slang_code_object * self)
00116 {
00117    GLuint i;
00118 
00119    for (i = 0; i < SLANG_BUILTIN_TOTAL; i++)
00120       _slang_code_unit_dtr(&self->builtin[i]);
00121    _slang_code_unit_dtr(&self->unit);
00122    slang_atom_pool_destruct(&self->atompool);
00123 }
00124 
00125 
00126 /* slang_parse_ctx */
00127 
00128 typedef struct slang_parse_ctx_
00129 {
00130    const byte *I;
00131    slang_info_log *L;
00132    int parsing_builtin;
00133    GLboolean global_scope;   
00134    slang_atom_pool *atoms;
00135    slang_unit_type type;     
00136    GLuint version;           
00137 } slang_parse_ctx;
00138 
00139 /* slang_output_ctx */
00140 
00141 typedef struct slang_output_ctx_
00142 {
00143    slang_variable_scope *vars;
00144    slang_function_scope *funs;
00145    slang_struct_scope *structs;
00146    struct gl_program *program;
00147    struct gl_sl_pragmas *pragmas;
00148    slang_var_table *vartable;
00149    GLuint default_precision[TYPE_SPECIFIER_COUNT];
00150    GLboolean allow_precision;
00151    GLboolean allow_invariant;
00152    GLboolean allow_centroid;
00153    GLboolean allow_array_types;  /* float[] syntax */
00154 } slang_output_ctx;
00155 
00156 /* _slang_compile() */
00157 
00158 
00159 /* Debugging aid, print file/line where parsing error is detected */
00160 #define RETURN0 \
00161    do { \
00162       if (0) \
00163          printf("slang error at %s:%d\n", __FILE__, __LINE__); \
00164       return 0; \
00165    } while (0)
00166 
00167 
00168 static void
00169 parse_identifier_str(slang_parse_ctx * C, char **id)
00170 {
00171    *id = (char *) C->I;
00172    C->I += _mesa_strlen(*id) + 1;
00173 }
00174 
00175 static slang_atom
00176 parse_identifier(slang_parse_ctx * C)
00177 {
00178    const char *id;
00179 
00180    id = (const char *) C->I;
00181    C->I += _mesa_strlen(id) + 1;
00182    return slang_atom_pool_atom(C->atoms, id);
00183 }
00184 
00185 static int
00186 parse_number(slang_parse_ctx * C, int *number)
00187 {
00188    const int radix = (int) (*C->I++);
00189    *number = 0;
00190    while (*C->I != '\0') {
00191       int digit;
00192       if (*C->I >= '0' && *C->I <= '9')
00193          digit = (int) (*C->I - '0');
00194       else if (*C->I >= 'A' && *C->I <= 'Z')
00195          digit = (int) (*C->I - 'A') + 10;
00196       else
00197          digit = (int) (*C->I - 'a') + 10;
00198       *number = *number * radix + digit;
00199       C->I++;
00200    }
00201    C->I++;
00202    if (*number > 65535)
00203       slang_info_log_warning(C->L, "%d: literal integer overflow.", *number);
00204    return 1;
00205 }
00206 
00207 static int
00208 parse_float(slang_parse_ctx * C, float *number)
00209 {
00210    char *integral = NULL;
00211    char *fractional = NULL;
00212    char *exponent = NULL;
00213    char *whole = NULL;
00214 
00215    parse_identifier_str(C, &integral);
00216    parse_identifier_str(C, &fractional);
00217    parse_identifier_str(C, &exponent);
00218 
00219    whole = (char *) _slang_alloc((_mesa_strlen(integral) +
00220                                   _mesa_strlen(fractional) +
00221                                   _mesa_strlen(exponent) + 3) * sizeof(char));
00222    if (whole == NULL) {
00223       slang_info_log_memory(C->L);
00224       RETURN0;
00225    }
00226 
00227    slang_string_copy(whole, integral);
00228    slang_string_concat(whole, ".");
00229    slang_string_concat(whole, fractional);
00230    slang_string_concat(whole, "E");
00231    slang_string_concat(whole, exponent);
00232 
00233    *number = (float) (_mesa_strtod(whole, (char **) NULL));
00234 
00235    _slang_free(whole);
00236 
00237    return 1;
00238 }
00239 
00240 /* revision number - increment after each change affecting emitted output */
00241 #define REVISION 5
00242 
00243 static int
00244 check_revision(slang_parse_ctx * C)
00245 {
00246    if (*C->I != REVISION) {
00247       slang_info_log_error(C->L, "Internal compiler error.");
00248       RETURN0;
00249    }
00250    C->I++;
00251    return 1;
00252 }
00253 
00254 static int parse_statement(slang_parse_ctx *, slang_output_ctx *,
00255                            slang_operation *);
00256 static int parse_expression(slang_parse_ctx *, slang_output_ctx *,
00257                             slang_operation *);
00258 static int parse_type_specifier(slang_parse_ctx *, slang_output_ctx *,
00259                                 slang_type_specifier *);
00260 static int
00261 parse_type_array_size(slang_parse_ctx *C,
00262                       slang_output_ctx *O,
00263                       GLint *array_len);
00264 
00265 static GLboolean
00266 parse_array_len(slang_parse_ctx * C, slang_output_ctx * O, GLuint * len)
00267 {
00268    slang_operation array_size;
00269    slang_name_space space;
00270    GLboolean result;
00271 
00272    if (!slang_operation_construct(&array_size))
00273       return GL_FALSE;
00274    if (!parse_expression(C, O, &array_size)) {
00275       slang_operation_destruct(&array_size);
00276       return GL_FALSE;
00277    }
00278 
00279    space.funcs = O->funs;
00280    space.structs = O->structs;
00281    space.vars = O->vars;
00282 
00283    /* evaluate compile-time expression which is array size */
00284    _slang_simplify(&array_size, &space, C->atoms);
00285 
00286    if (array_size.type == SLANG_OPER_LITERAL_INT) {
00287       result = GL_TRUE;
00288       *len = (GLint) array_size.literal[0];
00289    } else if (array_size.type == SLANG_OPER_IDENTIFIER) {
00290       slang_variable *var = _slang_variable_locate(array_size.locals, array_size.a_id, GL_TRUE);
00291       if (!var) {
00292          slang_info_log_error(C->L, "undefined variable '%s'",
00293                               (char *) array_size.a_id);
00294          result = GL_FALSE;
00295       } else if (var->type.qualifier == SLANG_QUAL_CONST &&
00296                  var->type.specifier.type == SLANG_SPEC_INT) {
00297          if (var->initializer &&
00298              var->initializer->type == SLANG_OPER_LITERAL_INT) {
00299             *len = (GLint) var->initializer->literal[0];
00300             result = GL_TRUE;
00301          } else {
00302             slang_info_log_error(C->L, "unable to parse array size declaration");
00303             result = GL_FALSE;
00304          }
00305       } else {
00306          slang_info_log_error(C->L, "unable to parse array size declaration");
00307          result = GL_FALSE;
00308       }
00309    } else {
00310       result = GL_FALSE;
00311    }
00312 
00313    slang_operation_destruct(&array_size);
00314    return result;
00315 }
00316 
00317 static GLboolean
00318 calculate_var_size(slang_parse_ctx * C, slang_output_ctx * O,
00319                    slang_variable * var)
00320 {
00321    slang_storage_aggregate agg;
00322 
00323    if (!slang_storage_aggregate_construct(&agg))
00324       return GL_FALSE;
00325    if (!_slang_aggregate_variable(&agg, &var->type.specifier, var->array_len,
00326                                   O->funs, O->structs, O->vars, C->atoms)) {
00327       slang_storage_aggregate_destruct(&agg);
00328       return GL_FALSE;
00329    }
00330    var->size = _slang_sizeof_aggregate(&agg);
00331    slang_storage_aggregate_destruct(&agg);
00332    return GL_TRUE;
00333 }
00334 
00335 static void
00336 promote_type_to_array(slang_parse_ctx *C,
00337                       slang_fully_specified_type *type,
00338                       GLint array_len)
00339 {
00340    slang_type_specifier *baseType =
00341       slang_type_specifier_new(type->specifier.type, NULL, NULL);
00342 
00343    type->specifier.type = SLANG_SPEC_ARRAY;
00344    type->specifier._array = baseType;
00345    type->array_len = array_len;
00346 }
00347 
00348 
00349 static GLboolean
00350 convert_to_array(slang_parse_ctx * C, slang_variable * var,
00351                  const slang_type_specifier * sp)
00352 {
00353    /* sized array - mark it as array, copy the specifier to the array element
00354     * and parse the expression */
00355    var->type.specifier.type = SLANG_SPEC_ARRAY;
00356    var->type.specifier._array = (slang_type_specifier *)
00357       _slang_alloc(sizeof(slang_type_specifier));
00358    if (var->type.specifier._array == NULL) {
00359       slang_info_log_memory(C->L);
00360       return GL_FALSE;
00361    }
00362    slang_type_specifier_ctr(var->type.specifier._array);
00363    return slang_type_specifier_copy(var->type.specifier._array, sp);
00364 }
00365 
00366 /* structure field */
00367 #define FIELD_NONE 0
00368 #define FIELD_NEXT 1
00369 #define FIELD_ARRAY 2
00370 
00371 static GLboolean
00372 parse_struct_field_var(slang_parse_ctx * C, slang_output_ctx * O,
00373                        slang_variable * var, slang_atom a_name,
00374                        const slang_type_specifier * sp,
00375                        GLuint array_len)
00376 {
00377    var->a_name = a_name;
00378    if (var->a_name == SLANG_ATOM_NULL)
00379       return GL_FALSE;
00380 
00381    switch (*C->I++) {
00382    case FIELD_NONE:
00383       if (array_len != -1) {
00384          if (!convert_to_array(C, var, sp))
00385             return GL_FALSE;
00386          var->array_len = array_len;
00387       }
00388       else {
00389          if (!slang_type_specifier_copy(&var->type.specifier, sp))
00390             return GL_FALSE;
00391       }
00392       break;
00393    case FIELD_ARRAY:
00394       if (array_len != -1)
00395          return GL_FALSE;
00396       if (!convert_to_array(C, var, sp))
00397          return GL_FALSE;
00398       if (!parse_array_len(C, O, &var->array_len))
00399          return GL_FALSE;
00400       break;
00401    default:
00402       return GL_FALSE;
00403    }
00404 
00405    return calculate_var_size(C, O, var);
00406 }
00407 
00408 static int
00409 parse_struct_field(slang_parse_ctx * C, slang_output_ctx * O,
00410                    slang_struct * st, slang_type_specifier * sp)
00411 {
00412    slang_output_ctx o = *O;
00413    GLint array_len;
00414 
00415    o.structs = st->structs;
00416    if (!parse_type_specifier(C, &o, sp))
00417       RETURN0;
00418    if (!parse_type_array_size(C, &o, &array_len))
00419       RETURN0;
00420 
00421    do {
00422       slang_atom a_name;
00423       slang_variable *var = slang_variable_scope_grow(st->fields);
00424       if (!var) {
00425          slang_info_log_memory(C->L);
00426          RETURN0;
00427       }
00428       a_name = parse_identifier(C);
00429       if (_slang_variable_locate(st->fields, a_name, GL_FALSE)) {
00430          slang_info_log_error(C->L, "duplicate field '%s'", (char *) a_name);
00431          RETURN0;
00432       }
00433 
00434       if (!parse_struct_field_var(C, &o, var, a_name, sp, array_len))
00435          RETURN0;
00436    }
00437    while (*C->I++ != FIELD_NONE);
00438 
00439    return 1;
00440 }
00441 
00442 static int
00443 parse_struct(slang_parse_ctx * C, slang_output_ctx * O, slang_struct ** st)
00444 {
00445    slang_atom a_name;
00446    const char *name;
00447 
00448    /* parse struct name (if any) and make sure it is unique in current scope */
00449    a_name = parse_identifier(C);
00450    if (a_name == SLANG_ATOM_NULL)
00451       RETURN0;
00452 
00453    name = slang_atom_pool_id(C->atoms, a_name);
00454    if (name[0] != '\0'
00455        && slang_struct_scope_find(O->structs, a_name, 0) != NULL) {
00456       slang_info_log_error(C->L, "%s: duplicate type name.", name);
00457       RETURN0;
00458    }
00459 
00460    /* set-up a new struct */
00461    *st = (slang_struct *) _slang_alloc(sizeof(slang_struct));
00462    if (*st == NULL) {
00463       slang_info_log_memory(C->L);
00464       RETURN0;
00465    }
00466    if (!slang_struct_construct(*st)) {
00467       _slang_free(*st);
00468       *st = NULL;
00469       slang_info_log_memory(C->L);
00470       RETURN0;
00471    }
00472    (**st).a_name = a_name;
00473    (**st).structs->outer_scope = O->structs;
00474 
00475    /* parse individual struct fields */
00476    do {
00477       slang_type_specifier sp;
00478 
00479       slang_type_specifier_ctr(&sp);
00480       if (!parse_struct_field(C, O, *st, &sp)) {
00481          slang_type_specifier_dtr(&sp);
00482          RETURN0;
00483       }
00484       slang_type_specifier_dtr(&sp);
00485    }
00486    while (*C->I++ != FIELD_NONE);
00487 
00488    /* if named struct, copy it to current scope */
00489    if (name[0] != '\0') {
00490       slang_struct *s;
00491 
00492       O->structs->structs =
00493          (slang_struct *) _slang_realloc(O->structs->structs,
00494                                          O->structs->num_structs
00495                                          * sizeof(slang_struct),
00496                                          (O->structs->num_structs + 1)
00497                                          * sizeof(slang_struct));
00498       if (O->structs->structs == NULL) {
00499          slang_info_log_memory(C->L);
00500          RETURN0;
00501       }
00502       s = &O->structs->structs[O->structs->num_structs];
00503       if (!slang_struct_construct(s))
00504          RETURN0;
00505       O->structs->num_structs++;
00506       if (!slang_struct_copy(s, *st))
00507          RETURN0;
00508    }
00509 
00510    return 1;
00511 }
00512 
00513 
00514 /* invariant qualifer */
00515 #define TYPE_VARIANT    90
00516 #define TYPE_INVARIANT  91
00517 
00518 static int
00519 parse_type_variant(slang_parse_ctx * C, slang_type_variant *variant)
00520 {
00521    GLuint invariant = *C->I++;
00522    switch (invariant) {
00523    case TYPE_VARIANT:
00524       *variant = SLANG_VARIANT;
00525       return 1;
00526    case TYPE_INVARIANT:
00527       *variant = SLANG_INVARIANT;
00528       return 1;
00529    default:
00530       RETURN0;
00531    }
00532 }
00533 
00534 
00535 /* centroid qualifer */
00536 #define TYPE_CENTER    95
00537 #define TYPE_CENTROID  96
00538 
00539 static int
00540 parse_type_centroid(slang_parse_ctx * C, slang_type_centroid *centroid)
00541 {
00542    GLuint c = *C->I++;
00543    switch (c) {
00544    case TYPE_CENTER:
00545       *centroid = SLANG_CENTER;
00546       return 1;
00547    case TYPE_CENTROID:
00548       *centroid = SLANG_CENTROID;
00549       return 1;
00550    default:
00551       RETURN0;
00552    }
00553 }
00554 
00555 
00556 /* type qualifier */
00557 #define TYPE_QUALIFIER_NONE 0
00558 #define TYPE_QUALIFIER_CONST 1
00559 #define TYPE_QUALIFIER_ATTRIBUTE 2
00560 #define TYPE_QUALIFIER_VARYING 3
00561 #define TYPE_QUALIFIER_UNIFORM 4
00562 #define TYPE_QUALIFIER_FIXEDOUTPUT 5
00563 #define TYPE_QUALIFIER_FIXEDINPUT 6
00564 
00565 static int
00566 parse_type_qualifier(slang_parse_ctx * C, slang_type_qualifier * qual)
00567 {
00568    GLuint qualifier = *C->I++;
00569    switch (qualifier) {
00570    case TYPE_QUALIFIER_NONE:
00571       *qual = SLANG_QUAL_NONE;
00572       break;
00573    case TYPE_QUALIFIER_CONST:
00574       *qual = SLANG_QUAL_CONST;
00575       break;
00576    case TYPE_QUALIFIER_ATTRIBUTE:
00577       *qual = SLANG_QUAL_ATTRIBUTE;
00578       break;
00579    case TYPE_QUALIFIER_VARYING:
00580       *qual = SLANG_QUAL_VARYING;
00581       break;
00582    case TYPE_QUALIFIER_UNIFORM:
00583       *qual = SLANG_QUAL_UNIFORM;
00584       break;
00585    case TYPE_QUALIFIER_FIXEDOUTPUT:
00586       *qual = SLANG_QUAL_FIXEDOUTPUT;
00587       break;
00588    case TYPE_QUALIFIER_FIXEDINPUT:
00589       *qual = SLANG_QUAL_FIXEDINPUT;
00590       break;
00591    default:
00592       RETURN0;
00593    }
00594    return 1;
00595 }
00596 
00597 /* type specifier */
00598 #define TYPE_SPECIFIER_VOID 0
00599 #define TYPE_SPECIFIER_BOOL 1
00600 #define TYPE_SPECIFIER_BVEC2 2
00601 #define TYPE_SPECIFIER_BVEC3 3
00602 #define TYPE_SPECIFIER_BVEC4 4
00603 #define TYPE_SPECIFIER_INT 5
00604 #define TYPE_SPECIFIER_IVEC2 6
00605 #define TYPE_SPECIFIER_IVEC3 7
00606 #define TYPE_SPECIFIER_IVEC4 8
00607 #define TYPE_SPECIFIER_FLOAT 9
00608 #define TYPE_SPECIFIER_VEC2 10
00609 #define TYPE_SPECIFIER_VEC3 11
00610 #define TYPE_SPECIFIER_VEC4 12
00611 #define TYPE_SPECIFIER_MAT2 13
00612 #define TYPE_SPECIFIER_MAT3 14
00613 #define TYPE_SPECIFIER_MAT4 15
00614 #define TYPE_SPECIFIER_SAMPLER1D 16
00615 #define TYPE_SPECIFIER_SAMPLER2D 17
00616 #define TYPE_SPECIFIER_SAMPLER3D 18
00617 #define TYPE_SPECIFIER_SAMPLERCUBE 19
00618 #define TYPE_SPECIFIER_SAMPLER1DSHADOW 20
00619 #define TYPE_SPECIFIER_SAMPLER2DSHADOW 21
00620 #define TYPE_SPECIFIER_SAMPLER2DRECT 22
00621 #define TYPE_SPECIFIER_SAMPLER2DRECTSHADOW 23
00622 #define TYPE_SPECIFIER_STRUCT 24
00623 #define TYPE_SPECIFIER_TYPENAME 25
00624 #define TYPE_SPECIFIER_MAT23 26
00625 #define TYPE_SPECIFIER_MAT32 27
00626 #define TYPE_SPECIFIER_MAT24 28
00627 #define TYPE_SPECIFIER_MAT42 29
00628 #define TYPE_SPECIFIER_MAT34 30
00629 #define TYPE_SPECIFIER_MAT43 31
00630 #define TYPE_SPECIFIER_COUNT 32
00631 
00632 static int
00633 parse_type_specifier(slang_parse_ctx * C, slang_output_ctx * O,
00634                      slang_type_specifier * spec)
00635 {
00636    switch (*C->I++) {
00637    case TYPE_SPECIFIER_VOID:
00638       spec->type = SLANG_SPEC_VOID;
00639       break;
00640    case TYPE_SPECIFIER_BOOL:
00641       spec->type = SLANG_SPEC_BOOL;
00642       break;
00643    case TYPE_SPECIFIER_BVEC2:
00644       spec->type = SLANG_SPEC_BVEC2;
00645       break;
00646    case TYPE_SPECIFIER_BVEC3:
00647       spec->type = SLANG_SPEC_BVEC3;
00648       break;
00649    case TYPE_SPECIFIER_BVEC4:
00650       spec->type = SLANG_SPEC_BVEC4;
00651       break;
00652    case TYPE_SPECIFIER_INT:
00653       spec->type = SLANG_SPEC_INT;
00654       break;
00655    case TYPE_SPECIFIER_IVEC2:
00656       spec->type = SLANG_SPEC_IVEC2;
00657       break;
00658    case TYPE_SPECIFIER_IVEC3:
00659       spec->type = SLANG_SPEC_IVEC3;
00660       break;
00661    case TYPE_SPECIFIER_IVEC4:
00662       spec->type = SLANG_SPEC_IVEC4;
00663       break;
00664    case TYPE_SPECIFIER_FLOAT:
00665       spec->type = SLANG_SPEC_FLOAT;
00666       break;
00667    case TYPE_SPECIFIER_VEC2:
00668       spec->type = SLANG_SPEC_VEC2;
00669       break;
00670    case TYPE_SPECIFIER_VEC3:
00671       spec->type = SLANG_SPEC_VEC3;
00672       break;
00673    case TYPE_SPECIFIER_VEC4:
00674       spec->type = SLANG_SPEC_VEC4;
00675       break;
00676    case TYPE_SPECIFIER_MAT2:
00677       spec->type = SLANG_SPEC_MAT2;
00678       break;
00679    case TYPE_SPECIFIER_MAT3:
00680       spec->type = SLANG_SPEC_MAT3;
00681       break;
00682    case TYPE_SPECIFIER_MAT4:
00683       spec->type = SLANG_SPEC_MAT4;
00684       break;
00685    case TYPE_SPECIFIER_MAT23:
00686       spec->type = SLANG_SPEC_MAT23;
00687       break;
00688    case TYPE_SPECIFIER_MAT32:
00689       spec->type = SLANG_SPEC_MAT32;
00690       break;
00691    case TYPE_SPECIFIER_MAT24:
00692       spec->type = SLANG_SPEC_MAT24;
00693       break;
00694    case TYPE_SPECIFIER_MAT42:
00695       spec->type = SLANG_SPEC_MAT42;
00696       break;
00697    case TYPE_SPECIFIER_MAT34:
00698       spec->type = SLANG_SPEC_MAT34;
00699       break;
00700    case TYPE_SPECIFIER_MAT43:
00701       spec->type = SLANG_SPEC_MAT43;
00702       break;
00703    case TYPE_SPECIFIER_SAMPLER1D:
00704       spec->type = SLANG_SPEC_SAMPLER1D;
00705       break;
00706    case TYPE_SPECIFIER_SAMPLER2D:
00707       spec->type = SLANG_SPEC_SAMPLER2D;
00708       break;
00709    case TYPE_SPECIFIER_SAMPLER3D:
00710       spec->type = SLANG_SPEC_SAMPLER3D;
00711       break;
00712    case TYPE_SPECIFIER_SAMPLERCUBE:
00713       spec->type = SLANG_SPEC_SAMPLERCUBE;
00714       break;
00715    case TYPE_SPECIFIER_SAMPLER2DRECT:
00716       spec->type = SLANG_SPEC_SAMPLER2DRECT;
00717       break;
00718    case TYPE_SPECIFIER_SAMPLER1DSHADOW:
00719       spec->type = SLANG_SPEC_SAMPLER1DSHADOW;
00720       break;
00721    case TYPE_SPECIFIER_SAMPLER2DSHADOW:
00722       spec->type = SLANG_SPEC_SAMPLER2DSHADOW;
00723       break;
00724    case TYPE_SPECIFIER_SAMPLER2DRECTSHADOW:
00725       spec->type = SLANG_SPEC_SAMPLER2DRECTSHADOW;
00726       break;
00727    case TYPE_SPECIFIER_STRUCT:
00728       spec->type = SLANG_SPEC_STRUCT;
00729       if (!parse_struct(C, O, &spec->_struct))
00730          RETURN0;
00731       break;
00732    case TYPE_SPECIFIER_TYPENAME:
00733       spec->type = SLANG_SPEC_STRUCT;
00734       {
00735          slang_atom a_name;
00736          slang_struct *stru;
00737 
00738          a_name = parse_identifier(C);
00739          if (a_name == NULL)
00740             RETURN0;
00741 
00742          stru = slang_struct_scope_find(O->structs, a_name, 1);
00743          if (stru == NULL) {
00744             slang_info_log_error(C->L, "undeclared type name '%s'",
00745                                  slang_atom_pool_id(C->atoms, a_name));
00746             RETURN0;
00747          }
00748 
00749          spec->_struct = (slang_struct *) _slang_alloc(sizeof(slang_struct));
00750          if (spec->_struct == NULL) {
00751             slang_info_log_memory(C->L);
00752             RETURN0;
00753          }
00754          if (!slang_struct_construct(spec->_struct)) {
00755             _slang_free(spec->_struct);
00756             spec->_struct = NULL;
00757             RETURN0;
00758          }
00759          if (!slang_struct_copy(spec->_struct, stru))
00760             RETURN0;
00761       }
00762       break;
00763    default:
00764       RETURN0;
00765    }
00766    return 1;
00767 }
00768 
00769 #define TYPE_SPECIFIER_NONARRAY 0
00770 #define TYPE_SPECIFIER_ARRAY    1
00771 
00772 static int
00773 parse_type_array_size(slang_parse_ctx *C,
00774                       slang_output_ctx *O,
00775                       GLint *array_len)
00776 {
00777    GLuint size;
00778 
00779    switch (*C->I++) {
00780    case TYPE_SPECIFIER_NONARRAY:
00781       *array_len = -1; /* -1 = not an array */
00782       break;
00783    case TYPE_SPECIFIER_ARRAY:
00784       if (!parse_array_len(C, O, &size))
00785          RETURN0;
00786       *array_len = (GLint) size;
00787       break;
00788    default:
00789       assert(0);
00790       RETURN0;
00791    }
00792    return 1;
00793 }
00794 
00795 #define PRECISION_DEFAULT 0
00796 #define PRECISION_LOW     1
00797 #define PRECISION_MEDIUM  2
00798 #define PRECISION_HIGH    3
00799 
00800 static int
00801 parse_type_precision(slang_parse_ctx *C,
00802                      slang_type_precision *precision)
00803 {
00804    GLint prec = *C->I++;
00805    switch (prec) {
00806    case PRECISION_DEFAULT:
00807       *precision = SLANG_PREC_DEFAULT;
00808       return 1;
00809    case PRECISION_LOW:
00810       *precision = SLANG_PREC_LOW;
00811       return 1;
00812    case PRECISION_MEDIUM:
00813       *precision = SLANG_PREC_MEDIUM;
00814       return 1;
00815    case PRECISION_HIGH:
00816       *precision = SLANG_PREC_HIGH;
00817       return 1;
00818    default:
00819       RETURN0;
00820    }
00821 }
00822 
00823 static int
00824 parse_fully_specified_type(slang_parse_ctx * C, slang_output_ctx * O,
00825                            slang_fully_specified_type * type)
00826 {
00827    if (!parse_type_variant(C, &type->variant))
00828       RETURN0;
00829   
00830    if (!parse_type_centroid(C, &type->centroid))
00831       RETURN0;
00832 
00833    if (!parse_type_qualifier(C, &type->qualifier))
00834       RETURN0;
00835 
00836    if (!parse_type_precision(C, &type->precision))
00837       RETURN0;
00838 
00839    if (!parse_type_specifier(C, O, &type->specifier))
00840       RETURN0;
00841 
00842    if (!parse_type_array_size(C, O, &type->array_len))
00843       RETURN0;
00844 
00845    if (!O->allow_invariant && type->variant == SLANG_INVARIANT) {
00846       slang_info_log_error(C->L,
00847          "'invariant' keyword not allowed (perhaps set #version 120)");
00848       RETURN0;
00849    }
00850 
00851    if (!O->allow_centroid && type->centroid == SLANG_CENTROID) {
00852       slang_info_log_error(C->L,
00853          "'centroid' keyword not allowed (perhaps set #version 120)");
00854       RETURN0;
00855    }
00856    else if (type->centroid == SLANG_CENTROID &&
00857             type->qualifier != SLANG_QUAL_VARYING) {
00858       slang_info_log_error(C->L,
00859          "'centroid' keyword only allowed for varying vars");
00860       RETURN0;
00861    }
00862 
00863 
00864    /* need this?
00865    if (type->qualifier != SLANG_QUAL_VARYING &&
00866        type->variant == SLANG_INVARIANT) {
00867       slang_info_log_error(C->L,
00868                            "invariant qualifer only allowed for varying vars");
00869       RETURN0;
00870    }
00871    */
00872 
00873    if (O->allow_precision) {
00874       if (type->precision == SLANG_PREC_DEFAULT) {
00875          assert(type->specifier.type < TYPE_SPECIFIER_COUNT);
00876          /* use the default precision for this datatype */
00877          type->precision = O->default_precision[type->specifier.type];
00878       }
00879    }
00880    else {
00881       /* only default is allowed */
00882       if (type->precision != SLANG_PREC_DEFAULT) {
00883          slang_info_log_error(C->L, "precision qualifiers not allowed");
00884          RETURN0;
00885       }
00886    }
00887 
00888    if (!O->allow_array_types && type->array_len >= 0) {
00889       slang_info_log_error(C->L, "first-class array types not allowed");
00890       RETURN0;
00891    }
00892 
00893    if (type->array_len >= 0) {
00894       /* convert type to array type (ex: convert "int" to "array of int" */
00895       promote_type_to_array(C, type, type->array_len);
00896    }
00897 
00898    return 1;
00899 }
00900 
00901 /* operation */
00902 #define OP_END 0
00903 #define OP_BLOCK_BEGIN_NO_NEW_SCOPE 1
00904 #define OP_BLOCK_BEGIN_NEW_SCOPE 2
00905 #define OP_DECLARE 3
00906 #define OP_ASM 4
00907 #define OP_BREAK 5
00908 #define OP_CONTINUE 6
00909 #define OP_DISCARD 7
00910 #define OP_RETURN 8
00911 #define OP_EXPRESSION 9
00912 #define OP_IF 10
00913 #define OP_WHILE 11
00914 #define OP_DO 12
00915 #define OP_FOR 13
00916 #define OP_PUSH_VOID 14
00917 #define OP_PUSH_BOOL 15
00918 #define OP_PUSH_INT 16
00919 #define OP_PUSH_FLOAT 17
00920 #define OP_PUSH_IDENTIFIER 18
00921 #define OP_SEQUENCE 19
00922 #define OP_ASSIGN 20
00923 #define OP_ADDASSIGN 21
00924 #define OP_SUBASSIGN 22
00925 #define OP_MULASSIGN 23
00926 #define OP_DIVASSIGN 24
00927 /*#define OP_MODASSIGN 25*/
00928 /*#define OP_LSHASSIGN 26*/
00929 /*#define OP_RSHASSIGN 27*/
00930 /*#define OP_ORASSIGN 28*/
00931 /*#define OP_XORASSIGN 29*/
00932 /*#define OP_ANDASSIGN 30*/
00933 #define OP_SELECT 31
00934 #define OP_LOGICALOR 32
00935 #define OP_LOGICALXOR 33
00936 #define OP_LOGICALAND 34
00937 /*#define OP_BITOR 35*/
00938 /*#define OP_BITXOR 36*/
00939 /*#define OP_BITAND 37*/
00940 #define OP_EQUAL 38
00941 #define OP_NOTEQUAL 39
00942 #define OP_LESS 40
00943 #define OP_GREATER 41
00944 #define OP_LESSEQUAL 42
00945 #define OP_GREATEREQUAL 43
00946 /*#define OP_LSHIFT 44*/
00947 /*#define OP_RSHIFT 45*/
00948 #define OP_ADD 46
00949 #define OP_SUBTRACT 47
00950 #define OP_MULTIPLY 48
00951 #define OP_DIVIDE 49
00952 /*#define OP_MODULUS 50*/
00953 #define OP_PREINCREMENT 51
00954 #define OP_PREDECREMENT 52
00955 #define OP_PLUS 53
00956 #define OP_MINUS 54
00957 /*#define OP_COMPLEMENT 55*/
00958 #define OP_NOT 56
00959 #define OP_SUBSCRIPT 57
00960 #define OP_CALL 58
00961 #define OP_FIELD 59
00962 #define OP_POSTINCREMENT 60
00963 #define OP_POSTDECREMENT 61
00964 #define OP_PRECISION 62
00965 #define OP_METHOD 63
00966 
00967 
00980 static int
00981 parse_child_operation(slang_parse_ctx * C, slang_output_ctx * O,
00982                       slang_operation * oper, GLboolean statement)
00983 {
00984    slang_operation *ch;
00985 
00986    /* grow child array */
00987    ch = slang_operation_grow(&oper->num_children, &oper->children);
00988    if (statement)
00989       return parse_statement(C, O, ch);
00990    return parse_expression(C, O, ch);
00991 }
00992 
00993 static int parse_declaration(slang_parse_ctx * C, slang_output_ctx * O);
00994 
00995 static int
00996 parse_statement(slang_parse_ctx * C, slang_output_ctx * O,
00997                 slang_operation * oper)
00998 {
00999    int op;
01000 
01001    oper->locals->outer_scope = O->vars;
01002 
01003    op = *C->I++;
01004    switch (op) {
01005    case OP_BLOCK_BEGIN_NO_NEW_SCOPE:
01006       /* parse child statements, do not create new variable scope */
01007       oper->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE;
01008       while (*C->I != OP_END)
01009          if (!parse_child_operation(C, O, oper, GL_TRUE))
01010             RETURN0;
01011       C->I++;
01012       break;
01013    case OP_BLOCK_BEGIN_NEW_SCOPE:
01014       /* parse child statements, create new variable scope */
01015       {
01016          slang_output_ctx o = *O;
01017 
01018          oper->type = SLANG_OPER_BLOCK_NEW_SCOPE;
01019          o.vars = oper->locals;
01020          while (*C->I != OP_END)
01021             if (!parse_child_operation(C, &o, oper, GL_TRUE))
01022                RETURN0;
01023          C->I++;
01024       }
01025       break;
01026    case OP_DECLARE:
01027       /* local variable declaration, individual declarators are stored as
01028        * children identifiers
01029        */
01030       oper->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE;
01031       {
01032          const unsigned int first_var = O->vars->num_variables;
01033 
01034          /* parse the declaration, note that there can be zero or more
01035           * than one declarators
01036           */
01037          if (!parse_declaration(C, O))
01038             RETURN0;
01039          if (first_var < O->vars->num_variables) {
01040             const unsigned int num_vars = O->vars->num_variables - first_var;
01041             unsigned int i;
01042             assert(oper->num_children == 0);
01043             oper->num_children = num_vars;
01044             oper->children = slang_operation_new(num_vars);
01045             if (oper->children == NULL) {
01046                slang_info_log_memory(C->L);
01047                RETURN0;
01048             }
01049             for (i = first_var; i < O->vars->num_variables; i++) {
01050                slang_operation *o = &oper->children[i - first_var];
01051                slang_variable *var = O->vars->variables[i];
01052                o->type = SLANG_OPER_VARIABLE_DECL;
01053                o->locals->outer_scope = O->vars;
01054                o->a_id = var->a_name;
01055 
01056                /* new/someday...
01057                calculate_var_size(C, O, var);
01058                */
01059 
01060                if (!legal_identifier(o->a_id)) {
01061                   slang_info_log_error(C->L, "illegal variable name '%s'",
01062                                        (char *) o->a_id);
01063                   RETURN0;
01064                }
01065             }
01066          }
01067       }
01068       break;
01069    case OP_ASM:
01070       /* the __asm statement, parse the mnemonic and all its arguments
01071        * as expressions
01072        */
01073       oper->type = SLANG_OPER_ASM;
01074       oper->a_id = parse_identifier(C);
01075       if (oper->a_id == SLANG_ATOM_NULL)
01076          RETURN0;
01077       while (*C->I != OP_END) {
01078          if (!parse_child_operation(C, O, oper, GL_FALSE))
01079             RETURN0;
01080       }
01081       C->I++;
01082       break;
01083    case OP_BREAK:
01084       oper->type = SLANG_OPER_BREAK;
01085       break;
01086    case OP_CONTINUE:
01087       oper->type = SLANG_OPER_CONTINUE;
01088       break;
01089    case OP_DISCARD:
01090       oper->type = SLANG_OPER_DISCARD;
01091       break;
01092    case OP_RETURN:
01093       oper->type = SLANG_OPER_RETURN;
01094       if (!parse_child_operation(C, O, oper, GL_FALSE))
01095          RETURN0;
01096       break;
01097    case OP_EXPRESSION:
01098       oper->type = SLANG_OPER_EXPRESSION;
01099       if (!parse_child_operation(C, O, oper, GL_FALSE))
01100          RETURN0;
01101       break;
01102    case OP_IF:
01103       oper->type = SLANG_OPER_IF;
01104       if (!parse_child_operation(C, O, oper, GL_FALSE))
01105          RETURN0;
01106       if (!parse_child_operation(C, O, oper, GL_TRUE))
01107          RETURN0;
01108       if (!parse_child_operation(C, O, oper, GL_TRUE))
01109          RETURN0;
01110       break;
01111    case OP_WHILE:
01112       {
01113          slang_output_ctx o = *O;
01114 
01115          oper->type = SLANG_OPER_WHILE;
01116          o.vars = oper->locals;
01117          if (!parse_child_operation(C, &o, oper, GL_TRUE))
01118             RETURN0;
01119          if (!parse_child_operation(C, &o, oper, GL_TRUE))
01120             RETURN0;
01121       }
01122       break;
01123    case OP_DO:
01124       oper->type = SLANG_OPER_DO;
01125       if (!parse_child_operation(C, O, oper, GL_TRUE))
01126          RETURN0;
01127       if (!parse_child_operation(C, O, oper, GL_FALSE))
01128          RETURN0;
01129       break;
01130    case OP_FOR:
01131       {
01132          slang_output_ctx o = *O;
01133 
01134          oper->type = SLANG_OPER_FOR;
01135          o.vars = oper->locals;
01136          if (!parse_child_operation(C, &o, oper, GL_TRUE))
01137             RETURN0;
01138          if (!parse_child_operation(C, &o, oper, GL_TRUE))
01139             RETURN0;
01140          if (!parse_child_operation(C, &o, oper, GL_FALSE))
01141             RETURN0;
01142          if (!parse_child_operation(C, &o, oper, GL_TRUE))
01143             RETURN0;
01144       }
01145       break;
01146    case OP_PRECISION:
01147       {
01148          /* set default precision for a type in this scope */
01149          /* ignored at this time */
01150          int prec_qual = *C->I++;
01151          int datatype = *C->I++;
01152          (void) prec_qual;
01153          (void) datatype;
01154       }
01155       break;
01156    default:
01157       /*printf("Unexpected operation %d\n", op);*/
01158       RETURN0;
01159    }
01160    return 1;
01161 }
01162 
01163 static int
01164 handle_nary_expression(slang_parse_ctx * C, slang_operation * op,
01165                        slang_operation ** ops, unsigned int *total_ops,
01166                        unsigned int n)
01167 {
01168    unsigned int i;
01169 
01170    op->children = slang_operation_new(n);
01171    if (op->children == NULL) {
01172       slang_info_log_memory(C->L);
01173       RETURN0;
01174    }
01175    op->num_children = n;
01176 
01177    for (i = 0; i < n; i++) {
01178       slang_operation_destruct(&op->children[i]);
01179       op->children[i] = (*ops)[*total_ops - (n + 1 - i)];
01180    }
01181 
01182    (*ops)[*total_ops - (n + 1)] = (*ops)[*total_ops - 1];
01183    *total_ops -= n;
01184 
01185    *ops = (slang_operation *)
01186       _slang_realloc(*ops,
01187                      (*total_ops + n) * sizeof(slang_operation),
01188                      *total_ops * sizeof(slang_operation));
01189    if (*ops == NULL) {
01190       slang_info_log_memory(C->L);
01191       RETURN0;
01192    }
01193    return 1;
01194 }
01195 
01196 static int
01197 is_constructor_name(const char *name, slang_atom a_name,
01198                     slang_struct_scope * structs)
01199 {
01200    if (slang_type_specifier_type_from_string(name) != SLANG_SPEC_VOID)
01201       return 1;
01202    return slang_struct_scope_find(structs, a_name, 1) != NULL;
01203 }
01204 
01205 #define FUNCTION_CALL_NONARRAY 0
01206 #define FUNCTION_CALL_ARRAY    1
01207 
01208 static int
01209 parse_expression(slang_parse_ctx * C, slang_output_ctx * O,
01210                  slang_operation * oper)
01211 {
01212    slang_operation *ops = NULL;
01213    unsigned int num_ops = 0;
01214    int number;
01215 
01216    while (*C->I != OP_END) {
01217       slang_operation *op;
01218       const unsigned int op_code = *C->I++;
01219 
01220       /* allocate default operation, becomes a no-op if not used  */
01221       ops = (slang_operation *)
01222          _slang_realloc(ops,
01223                         num_ops * sizeof(slang_operation),
01224                         (num_ops + 1) * sizeof(slang_operation));
01225       if (ops == NULL) {
01226          slang_info_log_memory(C->L);
01227          RETURN0;
01228       }
01229       op = &ops[num_ops];
01230       if (!slang_operation_construct(op)) {
01231          slang_info_log_memory(C->L);
01232          RETURN0;
01233       }
01234       num_ops++;
01235       op->locals->outer_scope = O->vars;
01236 
01237       switch (op_code) {
01238       case OP_PUSH_VOID:
01239          op->type = SLANG_OPER_VOID;
01240          break;
01241       case OP_PUSH_BOOL:
01242          op->type = SLANG_OPER_LITERAL_BOOL;
01243          if (!parse_number(C, &number))
01244             RETURN0;
01245          op->literal[0] =
01246          op->literal[1] =
01247          op->literal[2] =
01248          op->literal[3] = (GLfloat) number;
01249          op->literal_size = 1;
01250          break;
01251       case OP_PUSH_INT:
01252          op->type = SLANG_OPER_LITERAL_INT;
01253          if (!parse_number(C, &number))
01254             RETURN0;
01255          op->literal[0] =
01256          op->literal[1] =
01257          op->literal[2] =
01258          op->literal[3] = (GLfloat) number;
01259          op->literal_size = 1;
01260          break;
01261       case OP_PUSH_FLOAT:
01262          op->type = SLANG_OPER_LITERAL_FLOAT;
01263          if (!parse_float(C, &op->literal[0]))
01264             RETURN0;
01265          op->literal[1] =
01266          op->literal[2] =
01267          op->literal[3] = op->literal[0];
01268          op->literal_size = 1;
01269          break;
01270       case OP_PUSH_IDENTIFIER:
01271          op->type = SLANG_OPER_IDENTIFIER;
01272          op->a_id = parse_identifier(C);
01273          if (op->a_id == SLANG_ATOM_NULL)
01274             RETURN0;
01275          break;
01276       case OP_SEQUENCE:
01277          op->type = SLANG_OPER_SEQUENCE;
01278          if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
01279             RETURN0;
01280          break;
01281       case OP_ASSIGN:
01282          op->type = SLANG_OPER_ASSIGN;
01283          if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
01284             RETURN0;
01285          break;
01286       case OP_ADDASSIGN:
01287          op->type = SLANG_OPER_ADDASSIGN;
01288          if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
01289             RETURN0;
01290          break;
01291       case OP_SUBASSIGN:
01292          op->type = SLANG_OPER_SUBASSIGN;
01293          if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
01294             RETURN0;
01295          break;
01296       case OP_MULASSIGN:
01297          op->type = SLANG_OPER_MULASSIGN;
01298          if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
01299             RETURN0;
01300          break;
01301       case OP_DIVASSIGN:
01302          op->type = SLANG_OPER_DIVASSIGN;
01303          if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
01304             RETURN0;
01305          break;
01306          /*case OP_MODASSIGN: */
01307          /*case OP_LSHASSIGN: */
01308          /*case OP_RSHASSIGN: */
01309          /*case OP_ORASSIGN: */
01310          /*case OP_XORASSIGN: */
01311          /*case OP_ANDASSIGN: */
01312       case OP_SELECT:
01313          op->type = SLANG_OPER_SELECT;
01314          if (!handle_nary_expression(C, op, &ops, &num_ops, 3))
01315             RETURN0;
01316          break;
01317       case OP_LOGICALOR:
01318          op->type = SLANG_OPER_LOGICALOR;
01319          if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
01320             RETURN0;
01321          break;
01322       case OP_LOGICALXOR:
01323          op->type = SLANG_OPER_LOGICALXOR;
01324          if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
01325             RETURN0;
01326          break;
01327       case OP_LOGICALAND:
01328          op->type = SLANG_OPER_LOGICALAND;
01329          if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
01330             RETURN0;
01331          break;
01332          /*case OP_BITOR: */
01333          /*case OP_BITXOR: */
01334          /*case OP_BITAND: */
01335       case OP_EQUAL:
01336          op->type = SLANG_OPER_EQUAL;
01337          if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
01338             RETURN0;
01339          break;
01340       case OP_NOTEQUAL:
01341          op->type = SLANG_OPER_NOTEQUAL;
01342          if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
01343             RETURN0;
01344          break;
01345       case OP_LESS:
01346          op->type = SLANG_OPER_LESS;
01347          if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
01348             RETURN0;
01349          break;
01350       case OP_GREATER:
01351          op->type = SLANG_OPER_GREATER;
01352          if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
01353             RETURN0;
01354          break;
01355       case OP_LESSEQUAL:
01356          op->type = SLANG_OPER_LESSEQUAL;
01357          if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
01358             RETURN0;
01359          break;
01360       case OP_GREATEREQUAL:
01361          op->type = SLANG_OPER_GREATEREQUAL;
01362          if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
01363             RETURN0;
01364          break;
01365          /*case OP_LSHIFT: */
01366          /*case OP_RSHIFT: */
01367       case OP_ADD:
01368          op->type = SLANG_OPER_ADD;
01369          if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
01370             RETURN0;
01371          break;
01372       case OP_SUBTRACT:
01373          op->type = SLANG_OPER_SUBTRACT;
01374          if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
01375             RETURN0;
01376          break;
01377       case OP_MULTIPLY:
01378          op->type = SLANG_OPER_MULTIPLY;
01379          if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
01380             RETURN0;
01381          break;
01382       case OP_DIVIDE:
01383          op->type = SLANG_OPER_DIVIDE;
01384          if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
01385             RETURN0;
01386          break;
01387          /*case OP_MODULUS: */
01388       case OP_PREINCREMENT:
01389          op->type = SLANG_OPER_PREINCREMENT;
01390          if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
01391             RETURN0;
01392          break;
01393       case OP_PREDECREMENT:
01394          op->type = SLANG_OPER_PREDECREMENT;
01395          if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
01396             RETURN0;
01397          break;
01398       case OP_PLUS:
01399          op->type = SLANG_OPER_PLUS;
01400          if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
01401             RETURN0;
01402          break;
01403       case OP_MINUS:
01404          op->type = SLANG_OPER_MINUS;
01405          if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
01406             RETURN0;
01407          break;
01408       case OP_NOT:
01409          op->type = SLANG_OPER_NOT;
01410          if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
01411             RETURN0;
01412          break;
01413          /*case OP_COMPLEMENT: */
01414       case OP_SUBSCRIPT:
01415          op->type = SLANG_OPER_SUBSCRIPT;
01416          if (!handle_nary_expression(C, op, &ops, &num_ops, 2))
01417             RETURN0;
01418          break;
01419       case OP_METHOD:
01420          op->type = SLANG_OPER_METHOD;
01421          op->a_obj = parse_identifier(C);
01422          if (op->a_obj == SLANG_ATOM_NULL)
01423             RETURN0;
01424 
01425          op->a_id = parse_identifier(C);
01426          if (op->a_id == SLANG_ATOM_NULL)
01427             RETURN0;
01428 
01429          assert(*C->I == OP_END);
01430          C->I++;
01431 
01432          while (*C->I != OP_END)
01433             if (!parse_child_operation(C, O, op, GL_FALSE))
01434                RETURN0;
01435          C->I++;
01436 #if 0
01437          /* don't lookup the method (not yet anyway) */
01438          if (!C->parsing_builtin
01439              && !slang_function_scope_find_by_name(O->funs, op->a_id, 1)) {
01440             const char *id;
01441 
01442             id = slang_atom_pool_id(C->atoms, op->a_id);
01443             if (!is_constructor_name(id, op->a_id, O->structs)) {
01444                slang_info_log_error(C->L, "%s: undeclared function name.", id);
01445                RETURN0;
01446             }
01447          }
01448 #endif
01449          break;
01450       case OP_CALL:
01451          {
01452             GLboolean array_constructor = GL_FALSE;
01453             GLint array_constructor_size = 0;
01454 
01455             op->type = SLANG_OPER_CALL;
01456             op->a_id = parse_identifier(C);
01457             if (op->a_id == SLANG_ATOM_NULL)
01458                RETURN0;
01459             switch (*C->I++) {
01460             case FUNCTION_CALL_NONARRAY:
01461                /* Nothing to do. */
01462                break;
01463             case FUNCTION_CALL_ARRAY:
01464                /* Calling an array constructor. For example:
01465                 *   float[3](1.1, 2.2, 3.3);
01466                 */
01467                if (!O->allow_array_types) {
01468                   slang_info_log_error(C->L,
01469                                        "array constructors not allowed "
01470                                        "in this GLSL version");
01471                   RETURN0;
01472                }
01473                else {
01474                   /* parse the array constructor size */
01475                   slang_operation array_size;
01476                   array_constructor = GL_TRUE;
01477                   slang_operation_construct(&array_size);
01478                   if (!parse_expression(C, O, &array_size)) {
01479                      slang_operation_destruct(&array_size);
01480                      return GL_FALSE;
01481                   }
01482                   if (array_size.type != SLANG_OPER_LITERAL_INT) {
01483                      slang_info_log_error(C->L,
01484                         "constructor array size is not an integer");
01485                      slang_operation_destruct(&array_size);
01486                      RETURN0;
01487                   }
01488                   array_constructor_size = (int) array_size.literal[0];
01489                   op->array_constructor = GL_TRUE;
01490                   slang_operation_destruct(&array_size);
01491                }
01492                break;
01493             default:
01494                assert(0);
01495                RETURN0;
01496             }
01497             while (*C->I != OP_END)
01498                if (!parse_child_operation(C, O, op, GL_FALSE))
01499                   RETURN0;
01500             C->I++;
01501 
01502             if (array_constructor &&
01503                 array_constructor_size != op->num_children) {
01504                slang_info_log_error(C->L, "number of parameters to array"
01505                                     " constructor does not match array size");
01506                RETURN0;
01507             }
01508 
01509             if (!C->parsing_builtin
01510                 && !slang_function_scope_find_by_name(O->funs, op->a_id, 1)) {
01511                const char *id;
01512 
01513                id = slang_atom_pool_id(C->atoms, op->a_id);
01514                if (!is_constructor_name(id, op->a_id, O->structs)) {
01515                   slang_info_log_error(C->L, "%s: undeclared function name.", id);
01516                   RETURN0;
01517                }
01518             }
01519          }
01520          break;
01521       case OP_FIELD:
01522          op->type = SLANG_OPER_FIELD;
01523          op->a_id = parse_identifier(C);
01524          if (op->a_id == SLANG_ATOM_NULL)
01525             RETURN0;
01526          if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
01527             RETURN0;
01528          break;
01529       case OP_POSTINCREMENT:
01530          op->type = SLANG_OPER_POSTINCREMENT;
01531          if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
01532             RETURN0;
01533          break;
01534       case OP_POSTDECREMENT:
01535          op->type = SLANG_OPER_POSTDECREMENT;
01536          if (!handle_nary_expression(C, op, &ops, &num_ops, 1))
01537             RETURN0;
01538          break;
01539       default:
01540          RETURN0;
01541       }
01542    }
01543    C->I++;
01544 
01545    slang_operation_destruct(oper);
01546    *oper = *ops; /* struct copy */
01547    _slang_free(ops);
01548 
01549    return 1;
01550 }
01551 
01552 /* parameter qualifier */
01553 #define PARAM_QUALIFIER_IN 0
01554 #define PARAM_QUALIFIER_OUT 1
01555 #define PARAM_QUALIFIER_INOUT 2
01556 
01557 /* function parameter array presence */
01558 #define PARAMETER_ARRAY_NOT_PRESENT 0
01559 #define PARAMETER_ARRAY_PRESENT 1
01560 
01561 static int
01562 parse_parameter_declaration(slang_parse_ctx * C, slang_output_ctx * O,
01563                             slang_variable * param)
01564 {
01565    int param_qual, precision_qual;
01566 
01567    /* parse and validate the parameter's type qualifiers (there can be
01568     * two at most) because not all combinations are valid
01569     */
01570    if (!parse_type_qualifier(C, &param->type.qualifier))
01571       RETURN0;
01572 
01573    param_qual = *C->I++;
01574    switch (param_qual) {
01575    case PARAM_QUALIFIER_IN:
01576       if (param->type.qualifier != SLANG_QUAL_CONST
01577           && param->type.qualifier != SLANG_QUAL_NONE) {
01578          slang_info_log_error(C->L, "Invalid type qualifier.");
01579          RETURN0;
01580       }
01581       break;
01582    case PARAM_QUALIFIER_OUT:
01583       if (param->type.qualifier == SLANG_QUAL_NONE)
01584          param->type.qualifier = SLANG_QUAL_OUT;
01585       else {
01586          slang_info_log_error(C->L, "Invalid type qualifier.");
01587          RETURN0;
01588       }
01589       break;
01590    case PARAM_QUALIFIER_INOUT:
01591       if (param->type.qualifier == SLANG_QUAL_NONE)
01592          param->type.qualifier = SLANG_QUAL_INOUT;
01593       else {
01594          slang_info_log_error(C->L, "Invalid type qualifier.");
01595          RETURN0;
01596       }
01597       break;
01598    default:
01599       RETURN0;
01600    }
01601 
01602    /* parse precision qualifier (lowp, mediump, highp */
01603    precision_qual = *C->I++;
01604    /* ignored at this time */
01605    (void) precision_qual;
01606 
01607    /* parse parameter's type specifier and name */
01608    if (!parse_type_specifier(C, O, &param->type.specifier))
01609       RETURN0;
01610    if (!parse_type_array_size(C, O, &param->type.array_len))
01611       RETURN0;
01612    param->a_name = parse_identifier(C);
01613    if (param->a_name == SLANG_ATOM_NULL)
01614       RETURN0;
01615 
01616    /* first-class array
01617     */
01618    if (param->type.array_len >= 0) {
01619       slang_type_specifier p;
01620 
01621       slang_type_specifier_ctr(&p);
01622       if (!slang_type_specifier_copy(&p, &param->type.specifier)) {
01623          slang_type_specifier_dtr(&p);
01624          RETURN0;
01625       }
01626       if (!convert_to_array(C, param, &p)) {
01627          slang_type_specifier_dtr(&p);
01628          RETURN0;
01629       }
01630       slang_type_specifier_dtr(&p);
01631       param->array_len = param->type.array_len;
01632    }
01633 
01634    /* if the parameter is an array, parse its size (the size must be
01635     * explicitly defined
01636     */
01637    if (*C->I++ == PARAMETER_ARRAY_PRESENT) {
01638       slang_type_specifier p;
01639 
01640       if (param->type.array_len >= 0) {
01641          slang_info_log_error(C->L, "multi-dimensional arrays not allowed");
01642          RETURN0;
01643       }
01644       slang_type_specifier_ctr(&p);
01645       if (!slang_type_specifier_copy(&p, &param->type.specifier)) {
01646          slang_type_specifier_dtr(&p);
01647          RETURN0;
01648       }
01649       if (!convert_to_array(C, param, &p)) {
01650          slang_type_specifier_dtr(&p);
01651          RETURN0;
01652       }
01653       slang_type_specifier_dtr(&p);
01654       if (!parse_array_len(C, O, &param->array_len))
01655          RETURN0;
01656    }
01657 
01658 #if 0
01659    /* calculate the parameter size */
01660    if (!calculate_var_size(C, O, param))
01661       RETURN0;
01662 #endif
01663    /* TODO: allocate the local address here? */
01664    return 1;
01665 }
01666 
01667 /* function type */
01668 #define FUNCTION_ORDINARY 0
01669 #define FUNCTION_CONSTRUCTOR 1
01670 #define FUNCTION_OPERATOR 2
01671 
01672 /* function parameter */
01673 #define PARAMETER_NONE 0
01674 #define PARAMETER_NEXT 1
01675 
01676 /* operator type */
01677 #define OPERATOR_ADDASSIGN 1
01678 #define OPERATOR_SUBASSIGN 2
01679 #define OPERATOR_MULASSIGN 3
01680 #define OPERATOR_DIVASSIGN 4
01681 /*#define OPERATOR_MODASSIGN 5*/
01682 /*#define OPERATOR_LSHASSIGN 6*/
01683 /*#define OPERATOR_RSHASSIGN 7*/
01684 /*#define OPERATOR_ANDASSIGN 8*/
01685 /*#define OPERATOR_XORASSIGN 9*/
01686 /*#define OPERATOR_ORASSIGN 10*/
01687 #define OPERATOR_LOGICALXOR 11
01688 /*#define OPERATOR_BITOR 12*/
01689 /*#define OPERATOR_BITXOR 13*/
01690 /*#define OPERATOR_BITAND 14*/
01691 #define OPERATOR_LESS 15
01692 #define OPERATOR_GREATER 16
01693 #define OPERATOR_LESSEQUAL 17
01694 #define OPERATOR_GREATEREQUAL 18
01695 /*#define OPERATOR_LSHIFT 19*/
01696 /*#define OPERATOR_RSHIFT 20*/
01697 #define OPERATOR_MULTIPLY 21
01698 #define OPERATOR_DIVIDE 22
01699 /*#define OPERATOR_MODULUS 23*/
01700 #define OPERATOR_INCREMENT 24
01701 #define OPERATOR_DECREMENT 25
01702 #define OPERATOR_PLUS 26
01703 #define OPERATOR_MINUS 27
01704 /*#define OPERATOR_COMPLEMENT 28*/
01705 #define OPERATOR_NOT 29
01706 
01707 static const struct
01708 {
01709    unsigned int o_code;
01710    const char *o_name;
01711 } operator_names[] = {
01712    {OPERATOR_INCREMENT, "++"},
01713    {OPERATOR_ADDASSIGN, "+="},
01714    {OPERATOR_PLUS, "+"},
01715    {OPERATOR_DECREMENT, "--"},
01716    {OPERATOR_SUBASSIGN, "-="},
01717    {OPERATOR_MINUS, "-"},
01718    {OPERATOR_NOT, "!"},
01719    {OPERATOR_MULASSIGN, "*="},
01720    {OPERATOR_MULTIPLY, "*"},
01721    {OPERATOR_DIVASSIGN, "/="},
01722    {OPERATOR_DIVIDE, "/"},
01723    {OPERATOR_LESSEQUAL, "<="},
01724    /*{ OPERATOR_LSHASSIGN, "<<=" }, */
01725    /*{ OPERATOR_LSHIFT, "<<" }, */
01726    {OPERATOR_LESS, "<"},
01727    {OPERATOR_GREATEREQUAL, ">="},
01728    /*{ OPERATOR_RSHASSIGN, ">>=" }, */
01729    /*{ OPERATOR_RSHIFT, ">>" }, */
01730    {OPERATOR_GREATER, ">"},
01731    /*{ OPERATOR_MODASSIGN, "%=" }, */
01732    /*{ OPERATOR_MODULUS, "%" }, */
01733    /*{ OPERATOR_ANDASSIGN, "&=" }, */
01734    /*{ OPERATOR_BITAND, "&" }, */
01735    /*{ OPERATOR_ORASSIGN, "|=" }, */
01736    /*{ OPERATOR_BITOR, "|" }, */
01737    /*{ OPERATOR_COMPLEMENT, "~" }, */
01738    /*{ OPERATOR_XORASSIGN, "^=" }, */
01739    {OPERATOR_LOGICALXOR, "^^"},
01740    /*{ OPERATOR_BITXOR, "^" } */
01741 };
01742 
01743 static slang_atom
01744 parse_operator_name(slang_parse_ctx * C)
01745 {
01746    unsigned int i;
01747 
01748    for (i = 0; i < sizeof(operator_names) / sizeof(*operator_names); i++) {
01749       if (operator_names[i].o_code == (unsigned int) (*C->I)) {
01750          slang_atom atom =
01751             slang_atom_pool_atom(C->atoms, operator_names[i].o_name);
01752          if (atom == SLANG_ATOM_NULL) {
01753             slang_info_log_memory(C->L);
01754             RETURN0;
01755          }
01756          C->I++;
01757          return atom;
01758       }
01759    }
01760    RETURN0;
01761 }
01762 
01763 
01764 static int
01765 parse_function_prototype(slang_parse_ctx * C, slang_output_ctx * O,
01766                          slang_function * func)
01767 {
01768    GLuint functype;
01769    /* parse function type and name */
01770    if (!parse_fully_specified_type(C, O, &func->header.type))
01771       RETURN0;
01772 
01773    functype = *C->I++;
01774    switch (functype) {
01775    case FUNCTION_ORDINARY:
01776       func->kind = SLANG_FUNC_ORDINARY;
01777       func->header.a_name = parse_identifier(C);
01778       if (func->header.a_name == SLANG_ATOM_NULL)
01779          RETURN0;
01780       break;
01781    case FUNCTION_CONSTRUCTOR:
01782       func->kind = SLANG_FUNC_CONSTRUCTOR;
01783       if (func->header.type.specifier.type == SLANG_SPEC_STRUCT)
01784          RETURN0;
01785       func->header.a_name =
01786          slang_atom_pool_atom(C->atoms,
01787                               slang_type_specifier_type_to_string
01788                               (func->header.type.specifier.type));
01789       if (func->header.a_name == SLANG_ATOM_NULL) {
01790          slang_info_log_memory(C->L);
01791          RETURN0;
01792       }
01793       break;
01794    case FUNCTION_OPERATOR:
01795       func->kind = SLANG_FUNC_OPERATOR;
01796       func->header.a_name = parse_operator_name(C);
01797       if (func->header.a_name == SLANG_ATOM_NULL)
01798          RETURN0;
01799       break;
01800    default:
01801       RETURN0;
01802    }
01803 
01804    if (!legal_identifier(func->header.a_name)) {
01805       slang_info_log_error(C->L, "illegal function name '%s'",
01806                            (char *) func->header.a_name);
01807       RETURN0;
01808    }
01809 
01810    /* parse function parameters */
01811    while (*C->I++ == PARAMETER_NEXT) {
01812       slang_variable *p = slang_variable_scope_grow(func->parameters);
01813       if (!p) {
01814          slang_info_log_memory(C->L);
01815          RETURN0;
01816       }
01817       if (!parse_parameter_declaration(C, O, p))
01818          RETURN0;
01819    }
01820 
01821    /* if the function returns a value, append a hidden __retVal 'out'
01822     * parameter that corresponds to the return value.
01823     */
01824    if (_slang_function_has_return_value(func)) {
01825       slang_variable *p = slang_variable_scope_grow(func->parameters);
01826       slang_atom a_retVal = slang_atom_pool_atom(C->atoms, "__retVal");
01827       assert(a_retVal);
01828       p->a_name = a_retVal;
01829       p->type = func->header.type;
01830       p->type.qualifier = SLANG_QUAL_OUT;
01831    }
01832 
01833    /* function formal parameters and local variables share the same
01834     * scope, so save the information about param count in a seperate
01835     * place also link the scope to the global variable scope so when a
01836     * given identifier is not found here, the search process continues
01837     * in the global space
01838     */
01839    func->param_count = func->parameters->num_variables;
01840    func->parameters->outer_scope = O->vars;
01841 
01842    return 1;
01843 }
01844 
01845 static int
01846 parse_function_definition(slang_parse_ctx * C, slang_output_ctx * O,
01847                           slang_function * func)
01848 {
01849    slang_output_ctx o = *O;
01850 
01851    if (!parse_function_prototype(C, O, func))
01852       RETURN0;
01853 
01854    /* create function's body operation */
01855    func->body = (slang_operation *) _slang_alloc(sizeof(slang_operation));
01856    if (func->body == NULL) {
01857       slang_info_log_memory(C->L);
01858       RETURN0;
01859    }
01860    if (!slang_operation_construct(func->body)) {
01861       _slang_free(func->body);
01862       func->body = NULL;
01863       slang_info_log_memory(C->L);
01864       RETURN0;
01865    }
01866 
01867    /* to parse the body the parse context is modified in order to
01868     * capture parsed variables into function's local variable scope
01869     */
01870    C->global_scope = GL_FALSE;
01871    o.vars = func->parameters;
01872    if (!parse_statement(C, &o, func->body))
01873       RETURN0;
01874 
01875    C->global_scope = GL_TRUE;
01876    return 1;
01877 }
01878 
01879 static GLboolean
01880 initialize_global(slang_assemble_ctx * A, slang_variable * var)
01881 {
01882    slang_operation op_id, op_assign;
01883    GLboolean result;
01884 
01885    /* construct the left side of assignment */
01886    if (!slang_operation_construct(&op_id))
01887       return GL_FALSE;
01888    op_id.type = SLANG_OPER_IDENTIFIER;
01889    op_id.a_id = var->a_name;
01890 
01891    /* put the variable into operation's scope */
01892    op_id.locals->variables =
01893       (slang_variable **) _slang_alloc(sizeof(slang_variable *));
01894    if (op_id.locals->variables == NULL) {
01895       slang_operation_destruct(&op_id);
01896       return GL_FALSE;
01897    }
01898    op_id.locals->num_variables = 1;
01899    op_id.locals->variables[0] = var;
01900 
01901    /* construct the assignment expression */
01902    if (!slang_operation_construct(&op_assign)) {
01903       op_id.locals->num_variables = 0;
01904       slang_operation_destruct(&op_id);
01905       return GL_FALSE;
01906    }
01907    op_assign.type = SLANG_OPER_ASSIGN;
01908    op_assign.children =
01909       (slang_operation *) _slang_alloc(2 * sizeof(slang_operation));
01910    if (op_assign.children == NULL) {
01911       slang_operation_destruct(&op_assign);
01912       op_id.locals->num_variables = 0;
01913       slang_operation_destruct(&op_id);
01914       return GL_FALSE;
01915    }
01916    op_assign.num_children = 2;
01917    op_assign.children[0] = op_id;
01918    op_assign.children[1] = *var->initializer;
01919 
01920    result = 1;
01921 
01922    /* carefully destroy the operations */
01923    op_assign.num_children = 0;
01924    _slang_free(op_assign.children);
01925    op_assign.children = NULL;
01926    slang_operation_destruct(&op_assign);
01927    op_id.locals->num_variables = 0;
01928    slang_operation_destruct(&op_id);
01929 
01930    if (!result)
01931       return GL_FALSE;
01932 
01933    return GL_TRUE;
01934 }
01935 
01936 /* init declarator list */
01937 #define DECLARATOR_NONE 0
01938 #define DECLARATOR_NEXT 1
01939 
01940 /* variable declaration */
01941 #define VARIABLE_NONE 0
01942 #define VARIABLE_IDENTIFIER 1
01943 #define VARIABLE_INITIALIZER 2
01944 #define VARIABLE_ARRAY_EXPLICIT 3
01945 #define VARIABLE_ARRAY_UNKNOWN 4
01946 
01947 
01951 static int
01952 parse_init_declarator(slang_parse_ctx * C, slang_output_ctx * O,
01953                       const slang_fully_specified_type * type)
01954 {
01955    slang_variable *var;
01956    slang_atom a_name;
01957 
01958    /* empty init declatator (without name, e.g. "float ;") */
01959    if (*C->I++ == VARIABLE_NONE)
01960       return 1;
01961 
01962    a_name = parse_identifier(C);
01963 
01964    /* check if name is already in this scope */
01965    if (_slang_variable_locate(O->vars, a_name, GL_FALSE)) {
01966       slang_info_log_error(C->L,
01967                    "declaration of '%s' conflicts with previous declaration",
01968                    (char *) a_name);
01969       RETURN0;
01970    }
01971 
01972    /* make room for the new variable and initialize it */
01973    var = slang_variable_scope_grow(O->vars);
01974    if (!var) {
01975       slang_info_log_memory(C->L);
01976       RETURN0;
01977    }
01978 
01979    /* copy the declarator type qualifier/etc info, parse the identifier */
01980    var->type.qualifier = type->qualifier;
01981    var->type.centroid = type->centroid;
01982    var->type.precision = type->precision;
01983    var->type.variant = type->variant;
01984    var->type.array_len = type->array_len;
01985    var->a_name = a_name;
01986    if (var->a_name == SLANG_ATOM_NULL)
01987       RETURN0;
01988 
01989    switch (*C->I++) {
01990    case VARIABLE_NONE:
01991       /* simple variable declarator - just copy the specifier */
01992       if (!slang_type_specifier_copy(&var->type.specifier, &type->specifier))
01993          RETURN0;
01994       break;
01995    case VARIABLE_INITIALIZER:
01996       /* initialized variable - copy the specifier and parse the expression */
01997       if (0 && type->array_len >= 0) {
01998          /* The type was something like "float[4]" */
01999          convert_to_array(C, var, &type->specifier);
02000          var->array_len = type->array_len;
02001       }
02002       else {
02003          if (!slang_type_specifier_copy(&var->type.specifier, &type->specifier))
02004             RETURN0;
02005       }
02006       var->initializer =
02007          (slang_operation *) _slang_alloc(sizeof(slang_operation));
02008       if (var->initializer == NULL) {
02009          slang_info_log_memory(C->L);
02010          RETURN0;
02011       }
02012       if (!slang_operation_construct(var->initializer)) {
02013          _slang_free(var->initializer);
02014          var->initializer = NULL;
02015          slang_info_log_memory(C->L);
02016          RETURN0;
02017       }
02018       if (!parse_expression(C, O, var->initializer))
02019          RETURN0;
02020       break;
02021    case VARIABLE_ARRAY_UNKNOWN:
02022       /* unsized array - mark it as array and copy the specifier to
02023        * the array element
02024        */
02025       if (type->array_len >= 0) {
02026          slang_info_log_error(C->L, "multi-dimensional arrays not allowed");
02027          RETURN0;
02028       }
02029       if (!convert_to_array(C, var, &type->specifier))
02030          return GL_FALSE;
02031       break;
02032    case VARIABLE_ARRAY_EXPLICIT:
02033       if (type->array_len >= 0) {
02034          /* the user is trying to do something like: float[2] x[3]; */
02035          slang_info_log_error(C->L, "multi-dimensional arrays not allowed");
02036          RETURN0;
02037       }
02038       if (!convert_to_array(C, var, &type->specifier))
02039          return GL_FALSE;
02040       if (!parse_array_len(C, O, &var->array_len))
02041          return GL_FALSE;
02042       break;
02043    default:
02044       RETURN0;
02045    }
02046 
02047    /* allocate global address space for a variable with a known size */
02048    if (C->global_scope
02049        && !(var->type.specifier.type == SLANG_SPEC_ARRAY
02050             && var->array_len == 0)) {
02051       if (!calculate_var_size(C, O, var))
02052          return GL_FALSE;
02053    }
02054 
02055    /* emit code for global var decl */
02056    if (C->global_scope) {
02057       slang_assemble_ctx A;
02058       A.atoms = C->atoms;
02059       A.space.funcs = O->funs;
02060       A.space.structs = O->structs;
02061       A.space.vars = O->vars;
02062       A.program = O->program;
02063       A.pragmas = O->pragmas;
02064       A.vartable = O->vartable;
02065       A.log = C->L;
02066       A.curFuncEndLabel = NULL;
02067       if (!_slang_codegen_global_variable(&A, var, C->type))
02068          RETURN0;
02069    }
02070 
02071    /* initialize global variable */
02072    if (C->global_scope) {
02073       if (var->initializer != NULL) {
02074          slang_assemble_ctx A;
02075 
02076          A.atoms = C->atoms;
02077          A.space.funcs = O->funs;
02078          A.space.structs = O->structs;
02079          A.space.vars = O->vars;
02080          if (!initialize_global(&A, var))
02081             RETURN0;
02082       }
02083    }
02084    return 1;
02085 }
02086 
02091 static int
02092 parse_init_declarator_list(slang_parse_ctx * C, slang_output_ctx * O)
02093 {
02094    slang_fully_specified_type type;
02095 
02096    /* parse the fully specified type, common to all declarators */
02097    if (!slang_fully_specified_type_construct(&type))
02098       RETURN0;
02099    if (!parse_fully_specified_type(C, O, &type)) {
02100       slang_fully_specified_type_destruct(&type);
02101       RETURN0;
02102    }
02103 
02104    /* parse declarators, pass-in the parsed type */
02105    do {
02106       if (!parse_init_declarator(C, O, &type)) {
02107          slang_fully_specified_type_destruct(&type);
02108          RETURN0;
02109       }
02110    }
02111    while (*C->I++ == DECLARATOR_NEXT);
02112 
02113    slang_fully_specified_type_destruct(&type);
02114    return 1;
02115 }
02116 
02117 
02126 static GLboolean
02127 parse_function(slang_parse_ctx * C, slang_output_ctx * O, int definition,
02128                slang_function ** parsed_func_ret)
02129 {
02130    slang_function parsed_func, *found_func;
02131 
02132    /* parse function definition/declaration */
02133    if (!slang_function_construct(&parsed_func))
02134       return GL_FALSE;
02135    if (definition) {
02136       if (!parse_function_definition(C, O, &parsed_func)) {
02137          slang_function_destruct(&parsed_func);
02138          return GL_FALSE;
02139       }
02140    }
02141    else {
02142       if (!parse_function_prototype(C, O, &parsed_func)) {
02143          slang_function_destruct(&parsed_func);
02144          return GL_FALSE;
02145       }
02146    }
02147 
02148    /* find a function with a prototype matching the parsed one - only
02149     * the current scope is being searched to allow built-in function
02150     * overriding
02151     */
02152    found_func = slang_function_scope_find(O->funs, &parsed_func, 0);
02153    if (found_func == NULL) {
02154       /* New function, add it to the function list */
02155       O->funs->functions =
02156          (slang_function *) _slang_realloc(O->funs->functions,
02157                                            O->funs->num_functions
02158                                            * sizeof(slang_function),
02159                                            (O->funs->num_functions + 1)
02160                                            * sizeof(slang_function));
02161       if (O->funs->functions == NULL) {
02162          slang_info_log_memory(C->L);
02163          slang_function_destruct(&parsed_func);
02164          return GL_FALSE;
02165       }
02166       O->funs->functions[O->funs->num_functions] = parsed_func;
02167       O->funs->num_functions++;
02168 
02169       /* return the newly parsed function */
02170       *parsed_func_ret = &O->funs->functions[O->funs->num_functions - 1];
02171    }
02172    else {
02173       /* previously defined or declared */
02174       /* TODO: check function return type qualifiers and specifiers */
02175       if (definition) {
02176          if (found_func->body != NULL) {
02177             slang_info_log_error(C->L, "%s: function already has a body.",
02178                                  slang_atom_pool_id(C->atoms,
02179                                                     parsed_func.header.
02180                                                     a_name));
02181             slang_function_destruct(&parsed_func);
02182             return GL_FALSE;
02183          }
02184 
02185          /* destroy the existing function declaration and replace it
02186           * with the new one
02187           */
02188          slang_function_destruct(found_func);
02189          *found_func = parsed_func;
02190       }
02191       else {
02192          /* another declaration of the same function prototype - ignore it */
02193          slang_function_destruct(&parsed_func);
02194       }
02195 
02196       /* return the found function */
02197       *parsed_func_ret = found_func;
02198    }
02199 
02200    return GL_TRUE;
02201 }
02202 
02203 /* declaration */
02204 #define DECLARATION_FUNCTION_PROTOTYPE 1
02205 #define DECLARATION_INIT_DECLARATOR_LIST 2
02206 
02207 static int
02208 parse_declaration(slang_parse_ctx * C, slang_output_ctx * O)
02209 {
02210    switch (*C->I++) {
02211    case DECLARATION_INIT_DECLARATOR_LIST:
02212       if (!parse_init_declarator_list(C, O))
02213          RETURN0;
02214       break;
02215    case DECLARATION_FUNCTION_PROTOTYPE:
02216       {
02217          slang_function *dummy_func;
02218 
02219          if (!parse_function(C, O, 0, &dummy_func))
02220             RETURN0;
02221       }
02222       break;
02223    default:
02224       RETURN0;
02225    }
02226    return 1;
02227 }
02228 
02229 static int
02230 parse_default_precision(slang_parse_ctx * C, slang_output_ctx * O)
02231 {
02232    int precision, type;
02233 
02234    if (!O->allow_precision) {
02235       slang_info_log_error(C->L, "syntax error at \"precision\"");
02236       RETURN0;
02237    }
02238 
02239    precision = *C->I++;
02240    switch (precision) {
02241    case PRECISION_LOW:
02242    case PRECISION_MEDIUM:
02243    case PRECISION_HIGH:
02244       /* OK */
02245       break;
02246    default:
02247       _mesa_problem(NULL, "unexpected precision %d at %s:%d\n",
02248                     precision, __FILE__, __LINE__);
02249       RETURN0;
02250    }
02251 
02252    type = *C->I++;
02253    switch (type) {
02254    case TYPE_SPECIFIER_FLOAT:
02255    case TYPE_SPECIFIER_INT:
02256    case TYPE_SPECIFIER_SAMPLER1D:
02257    case TYPE_SPECIFIER_SAMPLER2D:
02258    case TYPE_SPECIFIER_SAMPLER3D:
02259    case TYPE_SPECIFIER_SAMPLERCUBE:
02260    case TYPE_SPECIFIER_SAMPLER1DSHADOW:
02261    case TYPE_SPECIFIER_SAMPLER2DSHADOW:
02262    case TYPE_SPECIFIER_SAMPLER2DRECT:
02263    case TYPE_SPECIFIER_SAMPLER2DRECTSHADOW:
02264       /* OK */
02265       break;
02266    default:
02267       _mesa_problem(NULL, "unexpected type %d at %s:%d\n",
02268                     type, __FILE__, __LINE__);
02269       RETURN0;
02270    }
02271 
02272    assert(type < TYPE_SPECIFIER_COUNT);
02273    O->default_precision[type] = precision;
02274 
02275    return 1;
02276 }
02277 
02278 
02283 static void
02284 init_default_precision(slang_output_ctx *O, slang_unit_type type)
02285 {
02286    GLuint i;
02287    for (i = 0; i < TYPE_SPECIFIER_COUNT; i++) {
02288 #if FEATURE_es2_glsl
02289       O->default_precision[i] = PRECISION_LOW;
02290 #else
02291       O->default_precision[i] = PRECISION_HIGH;
02292 #endif
02293    }
02294 
02295    if (type == SLANG_UNIT_VERTEX_SHADER) {
02296       O->default_precision[TYPE_SPECIFIER_FLOAT] = PRECISION_HIGH;
02297       O->default_precision[TYPE_SPECIFIER_INT] = PRECISION_HIGH;
02298    }
02299    else {
02300       O->default_precision[TYPE_SPECIFIER_INT] = PRECISION_MEDIUM;
02301    }
02302 }
02303 
02304 
02305 static int
02306 parse_invariant(slang_parse_ctx * C, slang_output_ctx * O)
02307 {
02308    if (O->allow_invariant) {
02309       slang_atom *a = parse_identifier(C);
02310       /* XXX not doing anything with this var yet */
02311       /*printf("ID: %s\n", (char*) a);*/
02312       return a ? 1 : 0;
02313    }
02314    else {
02315       slang_info_log_error(C->L, "syntax error at \"invariant\"");
02316       RETURN0;
02317    }
02318 }
02319       
02320 
02321 /* external declaration or default precision specifier */
02322 #define EXTERNAL_NULL 0
02323 #define EXTERNAL_FUNCTION_DEFINITION 1
02324 #define EXTERNAL_DECLARATION 2
02325 #define DEFAULT_PRECISION 3
02326 #define INVARIANT_STMT 4
02327 
02328 
02329 static GLboolean
02330 parse_code_unit(slang_parse_ctx * C, slang_code_unit * unit,
02331                 struct gl_shader *shader)
02332 {
02333    GET_CURRENT_CONTEXT(ctx);
02334    slang_output_ctx o;
02335    GLboolean success;
02336    GLuint maxRegs;
02337    slang_function *mainFunc = NULL;
02338 
02339    if (unit->type == SLANG_UNIT_FRAGMENT_BUILTIN ||
02340        unit->type == SLANG_UNIT_FRAGMENT_SHADER) {
02341       maxRegs = ctx->Const.FragmentProgram.MaxTemps;
02342    }
02343    else {
02344       assert(unit->type == SLANG_UNIT_VERTEX_BUILTIN ||
02345              unit->type == SLANG_UNIT_VERTEX_SHADER);
02346       maxRegs = ctx->Const.VertexProgram.MaxTemps;
02347    }
02348 
02349    /* setup output context */
02350    o.funs = &unit->funs;
02351    o.structs = &unit->structs;
02352    o.vars = &unit->vars;
02353    o.program = shader ? shader->Program : NULL;
02354    o.pragmas = shader ? &shader->Pragmas : NULL;
02355    o.vartable = _slang_new_var_table(maxRegs);
02356    _slang_push_var_table(o.vartable);
02357 
02358    /* allow 'invariant' keyword? */
02359 #if FEATURE_es2_glsl
02360    o.allow_invariant = GL_TRUE;
02361 #else
02362    o.allow_invariant = (C->version >= 120) ? GL_TRUE : GL_FALSE;
02363 #endif
02364 
02365    /* allow 'centroid' keyword? */
02366    o.allow_centroid = (C->version >= 120) ? GL_TRUE : GL_FALSE;
02367 
02368    /* allow 'lowp/mediump/highp' keywords? */
02369 #if FEATURE_es2_glsl
02370    o.allow_precision = GL_TRUE;
02371 #else
02372    o.allow_precision = (C->version >= 120) ? GL_TRUE : GL_FALSE;
02373 #endif
02374    init_default_precision(&o, unit->type);
02375 
02376    /* allow 'float[]' keyword? */
02377    o.allow_array_types = (C->version >= 120) ? GL_TRUE : GL_FALSE;
02378 
02379    /* parse individual functions and declarations */
02380    while (*C->I != EXTERNAL_NULL) {
02381       switch (*C->I++) {
02382       case EXTERNAL_FUNCTION_DEFINITION:
02383          {
02384             slang_function *func;
02385             success = parse_function(C, &o, 1, &func);
02386             if (success &&
02387                 _mesa_strcmp((char *) func->header.a_name, "main") == 0) {
02388                /* found main() */
02389                mainFunc = func;
02390             }
02391          }
02392          break;
02393       case EXTERNAL_DECLARATION:
02394          success = parse_declaration(C, &o);
02395          break;
02396       case DEFAULT_PRECISION:
02397          success = parse_default_precision(C, &o);
02398          break;
02399       case INVARIANT_STMT:
02400          success = parse_invariant(C, &o);
02401          break;
02402       default:
02403          success = GL_FALSE;
02404       }
02405 
02406       if (!success) {
02407          /* xxx free codegen */
02408          _slang_pop_var_table(o.vartable);
02409          return GL_FALSE;
02410       }
02411    }
02412    C->I++;
02413 
02414    if (mainFunc) {
02415       /* assemble (generate code) for main() */
02416       slang_assemble_ctx A;
02417 
02418       A.atoms = C->atoms;
02419       A.space.funcs = o.funs;
02420       A.space.structs = o.structs;
02421       A.space.vars = o.vars;
02422       A.program = o.program;
02423       A.pragmas = &shader->Pragmas;
02424       A.vartable = o.vartable;
02425       A.log = C->L;
02426 
02427       /* main() takes no parameters */
02428       if (mainFunc->param_count > 0) {
02429          slang_info_log_error(A.log, "main() takes no arguments");
02430          return GL_FALSE;
02431       }
02432 
02433       _slang_codegen_function(&A, mainFunc);
02434 
02435       shader->Main = GL_TRUE; /* this shader defines main() */
02436    }
02437 
02438    _slang_pop_var_table(o.vartable);
02439    _slang_delete_var_table(o.vartable);
02440 
02441    return GL_TRUE;
02442 }
02443 
02444 static GLboolean
02445 compile_binary(const byte * prod, slang_code_unit * unit,
02446                GLuint version,
02447                slang_unit_type type, slang_info_log * infolog,
02448                slang_code_unit * builtin, slang_code_unit * downlink,
02449                struct gl_shader *shader)
02450 {
02451    slang_parse_ctx C;
02452 
02453    unit->type = type;
02454 
02455    /* setup parse context */
02456    C.I = prod;
02457    C.L = infolog;
02458    C.parsing_builtin = (builtin == NULL);
02459    C.global_scope = GL_TRUE;
02460    C.atoms = &unit->object->atompool;
02461    C.type = type;
02462    C.version = version;
02463 
02464    if (!check_revision(&C))
02465       return GL_FALSE;
02466 
02467    if (downlink != NULL) {
02468       unit->vars.outer_scope = &downlink->vars;
02469       unit->funs.outer_scope = &downlink->funs;
02470       unit->structs.outer_scope = &downlink->structs;
02471    }
02472 
02473    /* parse translation unit */
02474    return parse_code_unit(&C, unit, shader);
02475 }
02476 
02477 static GLboolean
02478 compile_with_grammar(grammar id, const char *source, slang_code_unit * unit,
02479                      slang_unit_type type, slang_info_log * infolog,
02480                      slang_code_unit * builtin,
02481                      struct gl_shader *shader,
02482                      const struct gl_extensions *extensions,
02483                      struct gl_sl_pragmas *pragmas)
02484 {
02485    byte *prod;
02486    GLuint size, start, version;
02487    slang_string preprocessed;
02488    GLuint maxVersion;
02489 
02490 #if FEATURE_ARB_shading_language_120
02491    maxVersion = 120;
02492 #elif FEATURE_es2_glsl
02493    maxVersion = 100;
02494 #else
02495    maxVersion = 110;
02496 #endif
02497 
02498    /* First retrieve the version number. */
02499    if (!_slang_preprocess_version(source, &version, &start, infolog))
02500       return GL_FALSE;
02501 
02502    if (version > maxVersion) {
02503       slang_info_log_error(infolog,
02504                            "language version %.2f is not supported.",
02505                            version * 0.01);
02506       return GL_FALSE;
02507    }
02508 
02509    /* Now preprocess the source string. */
02510    slang_string_init(&preprocessed);
02511    if (!_slang_preprocess_directives(&preprocessed, &source[start],
02512                                      infolog, extensions, pragmas)) {
02513       slang_string_free(&preprocessed);
02514       slang_info_log_error(infolog, "failed to preprocess the source.");
02515       return GL_FALSE;
02516    }
02517 
02518    /* Finally check the syntax and generate its binary representation. */
02519    if (!grammar_fast_check(id,
02520                            (const byte *) (slang_string_cstr(&preprocessed)),
02521                            &prod, &size, 65536)) {
02522       char buf[1024];
02523       GLint pos;
02524 
02525       slang_string_free(&preprocessed);
02526       grammar_get_last_error((byte *) (buf), sizeof(buf), &pos);
02527       slang_info_log_error(infolog, buf);
02528       /* syntax error (possibly in library code) */
02529 #if 0
02530       {
02531          int line, col;
02532          char *s;
02533          s = (char *) _mesa_find_line_column((const GLubyte *) source,
02534                                              (const GLubyte *) source + pos,
02535                                              &line, &col);
02536          printf("Error on line %d, col %d: %s\n", line, col, s);
02537       }
02538 #endif
02539       return GL_FALSE;
02540    }
02541    slang_string_free(&preprocessed);
02542 
02543    /* Syntax is okay - translate it to internal representation. */
02544    if (!compile_binary(prod, unit, version, type, infolog, builtin,
02545                        &builtin[SLANG_BUILTIN_TOTAL - 1],
02546                        shader)) {
02547       grammar_alloc_free(prod);
02548       return GL_FALSE;
02549    }
02550    grammar_alloc_free(prod);
02551    return GL_TRUE;
02552 }
02553 
02554 LONGSTRING static const char *slang_shader_syn =
02555 #include "library/slang_shader_syn.h"
02556    ;
02557 
02558 static const byte slang_core_gc[] = {
02559 #include "library/slang_core_gc.h"
02560 };
02561 
02562 static const byte slang_120_core_gc[] = {
02563 #include "library/slang_120_core_gc.h"
02564 };
02565 
02566 static const byte slang_120_fragment_gc[] = {
02567 #include "library/slang_builtin_120_fragment_gc.h"
02568 };
02569 
02570 static const byte slang_common_builtin_gc[] = {
02571 #include "library/slang_common_builtin_gc.h"
02572 };
02573 
02574 static const byte slang_fragment_builtin_gc[] = {
02575 #include "library/slang_fragment_builtin_gc.h"
02576 };
02577 
02578 static const byte slang_vertex_builtin_gc[] = {
02579 #include "library/slang_vertex_builtin_gc.h"
02580 };
02581 
02582 static GLboolean
02583 compile_object(grammar * id, const char *source, slang_code_object * object,
02584                slang_unit_type type, slang_info_log * infolog,
02585                struct gl_shader *shader,
02586                const struct gl_extensions *extensions,
02587                struct gl_sl_pragmas *pragmas)
02588 {
02589    slang_code_unit *builtins = NULL;
02590    GLuint base_version = 110;
02591 
02592    /* load GLSL grammar */
02593    *id = grammar_load_from_text((const byte *) (slang_shader_syn));
02594    if (*id == 0) {
02595       byte buf[1024];
02596       int pos;
02597 
02598       grammar_get_last_error(buf, 1024, &pos);
02599       slang_info_log_error(infolog, (const char *) (buf));
02600       return GL_FALSE;
02601    }
02602 
02603    /* set shader type - the syntax is slightly different for different shaders */
02604    if (type == SLANG_UNIT_FRAGMENT_SHADER
02605        || type == SLANG_UNIT_FRAGMENT_BUILTIN)
02606       grammar_set_reg8(*id, (const byte *) "shader_type", 1);
02607    else
02608       grammar_set_reg8(*id, (const byte *) "shader_type", 2);
02609 
02610    /* enable language extensions */
02611    grammar_set_reg8(*id, (const byte *) "parsing_builtin", 1);
02612 
02613    /* if parsing user-specified shader, load built-in library */
02614    if (type == SLANG_UNIT_FRAGMENT_SHADER || type == SLANG_UNIT_VERTEX_SHADER) {
02615       /* compile core functionality first */
02616       if (!compile_binary(slang_core_gc,
02617                           &object->builtin[SLANG_BUILTIN_CORE],
02618                           base_version,
02619                           SLANG_UNIT_FRAGMENT_BUILTIN, infolog,
02620                           NULL, NULL, NULL))
02621          return GL_FALSE;
02622 
02623 #if FEATURE_ARB_shading_language_120
02624       if (!compile_binary(slang_120_core_gc,
02625                           &object->builtin[SLANG_BUILTIN_120_CORE],
02626                           120,
02627                           SLANG_UNIT_FRAGMENT_BUILTIN, infolog,
02628                           NULL, &object->builtin[SLANG_BUILTIN_CORE], NULL))
02629          return GL_FALSE;
02630 #endif
02631 
02632       /* compile common functions and variables, link to core */
02633       if (!compile_binary(slang_common_builtin_gc,
02634                           &object->builtin[SLANG_BUILTIN_COMMON],
02635 #if FEATURE_ARB_shading_language_120
02636                           120,
02637 #else
02638                           base_version,
02639 #endif
02640                           SLANG_UNIT_FRAGMENT_BUILTIN, infolog, NULL,
02641 #if FEATURE_ARB_shading_language_120
02642                           &object->builtin[SLANG_BUILTIN_120_CORE],
02643 #else
02644                           &object->builtin[SLANG_BUILTIN_CORE],
02645 #endif
02646                           NULL))
02647          return GL_FALSE;
02648 
02649       /* compile target-specific functions and variables, link to common */
02650       if (type == SLANG_UNIT_FRAGMENT_SHADER) {
02651          if (!compile_binary(slang_fragment_builtin_gc,
02652                              &object->builtin[SLANG_BUILTIN_TARGET],
02653                              base_version,
02654                              SLANG_UNIT_FRAGMENT_BUILTIN, infolog, NULL,
02655                              &object->builtin[SLANG_BUILTIN_COMMON], NULL))
02656             return GL_FALSE;
02657 #if FEATURE_ARB_shading_language_120
02658          if (!compile_binary(slang_120_fragment_gc,
02659                              &object->builtin[SLANG_BUILTIN_TARGET],
02660                              120,
02661                              SLANG_UNIT_FRAGMENT_BUILTIN, infolog, NULL,
02662                              &object->builtin[SLANG_BUILTIN_COMMON], NULL))
02663             return GL_FALSE;
02664 #endif
02665       }
02666       else if (type == SLANG_UNIT_VERTEX_SHADER) {
02667          if (!compile_binary(slang_vertex_builtin_gc,
02668                              &object->builtin[SLANG_BUILTIN_TARGET],
02669                              base_version,
02670                              SLANG_UNIT_VERTEX_BUILTIN, infolog, NULL,
02671                              &object->builtin[SLANG_BUILTIN_COMMON], NULL))
02672             return GL_FALSE;
02673       }
02674 
02675       /* disable language extensions */
02676 #if NEW_SLANG /* allow-built-ins */
02677       grammar_set_reg8(*id, (const byte *) "parsing_builtin", 1);
02678 #else
02679       grammar_set_reg8(*id, (const byte *) "parsing_builtin", 0);
02680 #endif
02681       builtins = object->builtin;
02682    }
02683 
02684    /* compile the actual shader - pass-in built-in library for external shader */
02685    return compile_with_grammar(*id, source, &object->unit, type, infolog,
02686                                builtins, shader, extensions, pragmas);
02687 }
02688 
02689 
02690 static GLboolean
02691 compile_shader(GLcontext *ctx, slang_code_object * object,
02692                slang_unit_type type, slang_info_log * infolog,
02693                struct gl_shader *shader)
02694 {
02695    GLboolean success;
02696    grammar id = 0;
02697 
02698 #if 0 /* for debug */
02699    _mesa_printf("********* COMPILE SHADER ***********\n");
02700    _mesa_printf("%s\n", shader->Source);
02701    _mesa_printf("************************************\n");
02702 #endif
02703 
02704    assert(shader->Program);
02705 
02706    _slang_code_object_dtr(object);
02707    _slang_code_object_ctr(object);
02708 
02709    success = compile_object(&id, shader->Source, object, type, infolog, shader,
02710                             &ctx->Extensions, &shader->Pragmas);
02711    if (id != 0)
02712       grammar_destroy(id);
02713    if (!success)
02714       return GL_FALSE;
02715 
02716    return GL_TRUE;
02717 }
02718 
02719 
02720 
02721 GLboolean
02722 _slang_compile(GLcontext *ctx, struct gl_shader *shader)
02723 {
02724    GLboolean success;
02725    slang_info_log info_log;
02726    slang_code_object obj;
02727    slang_unit_type type;
02728 
02729    if (shader->Type == GL_VERTEX_SHADER) {
02730       type = SLANG_UNIT_VERTEX_SHADER;
02731    }
02732    else {
02733       assert(shader->Type == GL_FRAGMENT_SHADER);
02734       type = SLANG_UNIT_FRAGMENT_SHADER;
02735    }
02736 
02737    if (!shader->Source)
02738       return GL_FALSE;
02739 
02740    ctx->Shader.MemPool = _slang_new_mempool(1024*1024);
02741 
02742    shader->Main = GL_FALSE;
02743 
02744    if (!shader->Program) {
02745       GLenum progTarget;
02746       if (shader->Type == GL_VERTEX_SHADER)
02747          progTarget = GL_VERTEX_PROGRAM_ARB;
02748       else
02749          progTarget = GL_FRAGMENT_PROGRAM_ARB;
02750       shader->Program = ctx->Driver.NewProgram(ctx, progTarget, 1);
02751       shader->Program->Parameters = _mesa_new_parameter_list();
02752       shader->Program->Varying = _mesa_new_parameter_list();
02753       shader->Program->Attributes = _mesa_new_parameter_list();
02754    }
02755 
02756    slang_info_log_construct(&info_log);
02757    _slang_code_object_ctr(&obj);
02758 
02759    success = compile_shader(ctx, &obj, type, &info_log, shader);
02760 
02761    /* free shader's prev info log */
02762    if (shader->InfoLog) {
02763       _mesa_free(shader->InfoLog);
02764       shader->InfoLog = NULL;
02765    }
02766 
02767    if (info_log.text) {
02768       /* copy info-log string to shader object */
02769       shader->InfoLog = _mesa_strdup(info_log.text);
02770    }
02771 
02772    if (info_log.error_flag) {
02773       success = GL_FALSE;
02774    }
02775 
02776    slang_info_log_destruct(&info_log);
02777    _slang_code_object_dtr(&obj);
02778 
02779    _slang_delete_mempool((slang_mempool *) ctx->Shader.MemPool);
02780    ctx->Shader.MemPool = NULL;
02781 
02782    /* remove any reads of output registers */
02783 #if 0
02784    printf("Pre-remove output reads:\n");
02785    _mesa_print_program(shader->Program);
02786 #endif
02787    _mesa_remove_output_reads(shader->Program, PROGRAM_OUTPUT);
02788    if (shader->Type == GL_VERTEX_SHADER) {
02789       /* and remove writes to varying vars in vertex programs */
02790       _mesa_remove_output_reads(shader->Program, PROGRAM_VARYING);
02791    }
02792 #if 0
02793    printf("Post-remove output reads:\n");
02794    _mesa_print_program(shader->Program);
02795 #endif
02796 
02797    return success;
02798 }
02799 

Generated on Fri May 25 2012 04:18:48 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.