⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 slang_preprocess.c

📁 Mesa is an open-source implementation of the OpenGL specification - a system for rendering interacti
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Mesa 3-D graphics library * Version:  6.5.2 * * Copyright (C) 2005-2006  Brian Paul   All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *//** * \file slang_preprocess.c * slang preprocessor * \author Michal Krol */#include "main/imports.h"#include "shader/grammar/grammar_mesa.h"#include "slang_preprocess.h"LONGSTRING static const char *slang_pp_directives_syn =#include "library/slang_pp_directives_syn.h";LONGSTRING static const char *slang_pp_expression_syn =#include "library/slang_pp_expression_syn.h";LONGSTRING static const char *slang_pp_version_syn =#include "library/slang_pp_version_syn.h";static GLvoidgrammar_error_to_log (slang_info_log *log){   char buf[1024];   GLint pos;   grammar_get_last_error ((byte *) (buf), sizeof (buf), &pos);   slang_info_log_error (log, buf);}GLboolean_slang_preprocess_version (const char *text, GLuint *version, GLuint *eaten, slang_info_log *log){   grammar id;   byte *prod, *I;   unsigned int size;   id = grammar_load_from_text ((const byte *) (slang_pp_version_syn));   if (id == 0) {      grammar_error_to_log (log);      return GL_FALSE;   }   if (!grammar_fast_check (id, (const byte *) (text), &prod, &size, 8)) {      grammar_error_to_log (log);      grammar_destroy (id);      return GL_FALSE;   }   /* there can be multiple #version directives - grab the last one */   I = &prod[size - 6];   *version = (GLuint) (I[0]) + (GLuint) (I[1]) * 100;   *eaten = (GLuint) (I[2]) + ((GLuint) (I[3]) << 8) + ((GLuint) (I[4]) << 16) + ((GLuint) (I[5]) << 24);   grammar_destroy (id);   grammar_alloc_free (prod);   return GL_TRUE;}/* * The preprocessor does the following work. * 1. Remove comments. Each comment block is replaced with a single space and if the *    block contains new-lines, they are preserved. This ensures that line numbers *    stay the same and if a comment block delimits two tokens, the are delitmited *    by the space after comment removal. * 2. Remove preprocessor directives from the source string, checking their syntax and *    executing them if appropriate. Again, new-lines are preserved. * 3. Expand macros. * 4. Tokenize the source string by ensuring there is at least one space between every *    two adjacent tokens. */#define PP_ANNOTATE 0static GLvoidpp_annotate (slang_string *output, const char *fmt, ...){#if PP_ANNOTATE   va_list va;   char buffer[1024];   va_start (va, fmt);   _mesa_vsprintf (buffer, fmt, va);   va_end (va);   slang_string_pushs (output, buffer, _mesa_strlen (buffer));#else   (GLvoid) (output);   (GLvoid) (fmt);#endif} /* * The expression is executed on a fixed-sized stack. The PUSH macro makes a runtime * check if the stack is not overflown by too complex expressions. In that situation the * GLSL preprocessor should report internal compiler error. * The BINARYDIV makes a runtime check if the divider is not 0. If it is, it reports * compilation error. */#define EXECUTION_STACK_SIZE 1024#define PUSH(x)\   do {\      if (sp == 0) {\         slang_info_log_error (elog, "internal compiler error: preprocessor execution stack overflow.");\         return GL_FALSE;\      }\      stack[--sp] = x;\   } while (GL_FALSE)#define POP(x)\   do {\      assert (sp < EXECUTION_STACK_SIZE);\      x = stack[sp++];\   } while (GL_FALSE)#define BINARY(op)\   do {\      GLint a, b;\      POP(b);\      POP(a);\      PUSH(a op b);\   } while (GL_FALSE)#define BINARYDIV(op)\   do {\      GLint a, b;\      POP(b);\      POP(a);\      if (b == 0) {\         slang_info_log_error (elog, "division by zero in preprocessor expression.");\         return GL_FALSE;\      }\      PUSH(a op b);\   } while (GL_FALSE)#define UNARY(op)\   do {\      GLint a;\      POP(a);\      PUSH(op a);\   } while (GL_FALSE)#define OP_END          0#define OP_PUSHINT      1#define OP_LOGICALOR    2#define OP_LOGICALAND   3#define OP_OR           4#define OP_XOR          5#define OP_AND          6#define OP_EQUAL        7#define OP_NOTEQUAL     8#define OP_LESSEQUAL    9#define OP_GREATEREQUAL 10#define OP_LESS         11#define OP_GREATER      12#define OP_LEFTSHIFT    13#define OP_RIGHTSHIFT   14#define OP_ADD          15#define OP_SUBTRACT     16#define OP_MULTIPLY     17#define OP_DIVIDE       18#define OP_MODULUS      19#define OP_PLUS         20#define OP_MINUS        21#define OP_NEGATE       22#define OP_COMPLEMENT   23static GLbooleanexecute_expression (slang_string *output, const byte *code, GLuint *pi, GLint *result,                    slang_info_log *elog){   GLuint i = *pi;   GLint stack[EXECUTION_STACK_SIZE];   GLuint sp = EXECUTION_STACK_SIZE;   while (code[i] != OP_END) {      switch (code[i++]) {         case OP_PUSHINT:            i++;            PUSH(_mesa_atoi ((const char *) (&code[i])));            i += _mesa_strlen ((const char *) (&code[i])) + 1;            break;         case OP_LOGICALOR:            BINARY(||);            break;         case OP_LOGICALAND:            BINARY(&&);            break;         case OP_OR:            BINARY(|);            break;         case OP_XOR:            BINARY(^);            break;         case OP_AND:            BINARY(&);            break;         case OP_EQUAL:            BINARY(==);            break;         case OP_NOTEQUAL:            BINARY(!=);            break;         case OP_LESSEQUAL:            BINARY(<=);            break;         case OP_GREATEREQUAL:            BINARY(>=);            break;         case OP_LESS:            BINARY(<);            break;         case OP_GREATER:            BINARY(>);            break;         case OP_LEFTSHIFT:            BINARY(<<);            break;         case OP_RIGHTSHIFT:            BINARY(>>);            break;         case OP_ADD:            BINARY(+);            break;         case OP_SUBTRACT:            BINARY(-);            break;         case OP_MULTIPLY:            BINARY(*);            break;         case OP_DIVIDE:            BINARYDIV(/);            break;         case OP_MODULUS:            BINARYDIV(%);            break;         case OP_PLUS:            UNARY(+);            break;         case OP_MINUS:            UNARY(-);            break;         case OP_NEGATE:            UNARY(!);            break;         case OP_COMPLEMENT:            UNARY(~);            break;         default:            assert (0);      }   }   /* Write-back the index skipping the OP_END. */   *pi = i + 1;   /* There should be exactly one value left on the stack. This is our result. */   POP(*result);   pp_annotate (output, "%d ", *result);   assert (sp == EXECUTION_STACK_SIZE);   return GL_TRUE;}/* * Function execute_expressions() executes up to 2 expressions. The second expression is there * for the #line directive which takes 1 or 2 expressions that indicate line and file numbers. * If it fails, it returns 0. If it succeeds, it returns the number of executed expressions. */#define EXP_END        0#define EXP_EXPRESSION 1static GLuintexecute_expressions (slang_string *output, grammar eid, const byte *expr, GLint results[2],                     slang_info_log *elog){   GLint success;   byte *code;   GLuint size, count = 0;   success = grammar_fast_check (eid, expr, &code, &size, 64);   if (success) {      GLuint i = 0;      while (code[i++] == EXP_EXPRESSION) {         assert (count < 2);         if (!execute_expression (output, code, &i, &results[count], elog)) {            count = 0;            break;         }         count++;      }      grammar_alloc_free (code);   }   else {      slang_info_log_error (elog, "syntax error in preprocessor expression.");\   }   return count;}/* * The pp_symbol structure is used to hold macro definitions and macro formal parameters. The * pp_symbols strcture is a collection of pp_symbol. It is used both for storing macro formal * parameters and all global macro definitions. Making this unification wastes some memory, * becuse macro formal parameters don't need further lists of symbols. We lose 8 bytes per * formal parameter here, but making this we can use the same code to substitute macro parameters * as well as macros in the source string. */typedef struct{   struct pp_symbol_ *symbols;   GLuint count;} pp_symbols;static GLvoidpp_symbols_init (pp_symbols *self){   self->symbols = NULL;   self->count = 0;}static GLvoidpp_symbols_free (pp_symbols *);typedef struct pp_symbol_{   slang_string name;   slang_string replacement;   pp_symbols parameters;} pp_symbol;static GLvoidpp_symbol_init (pp_symbol *self){   slang_string_init (&self->name);   slang_string_init (&self->replacement);   pp_symbols_init (&self->parameters);}static GLvoidpp_symbol_free (pp_symbol *self){   slang_string_free (&self->name);   slang_string_free (&self->replacement);   pp_symbols_free (&self->parameters);}static GLvoidpp_symbol_reset (pp_symbol *self){   /* Leave symbol name intact. */   slang_string_reset (&self->replacement);   pp_symbols_free (&self->parameters);   pp_symbols_init (&self->parameters);}static GLvoidpp_symbols_free (pp_symbols *self){   GLuint i;   for (i = 0; i < self->count; i++)      pp_symbol_free (&self->symbols[i]);   _mesa_free (self->symbols);}static pp_symbol *pp_symbols_push (pp_symbols *self){   self->symbols = (pp_symbol *) (_mesa_realloc (self->symbols, self->count * sizeof (pp_symbol),                                                 (self->count + 1) * sizeof (pp_symbol)));   if (self->symbols == NULL)      return NULL;   pp_symbol_init (&self->symbols[self->count]);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -