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

📄 slang_preprocess.c

📁 Mesa is an open-source implementation of the OpenGL specification - a system for rendering interacti
💻 C
📖 第 1 页 / 共 3 页
字号:
   return &self->symbols[self->count++];}static GLbooleanpp_symbols_erase (pp_symbols *self, pp_symbol *symbol){   assert (symbol >= self->symbols && symbol < self->symbols + self->count);   self->count--;   pp_symbol_free (symbol);   if (symbol < self->symbols + self->count)      _mesa_memcpy (symbol, symbol + 1, sizeof (pp_symbol) * (self->symbols + self->count - symbol));   self->symbols = (pp_symbol *) (_mesa_realloc (self->symbols, (self->count + 1) * sizeof (pp_symbol),                                                 self->count * sizeof (pp_symbol)));   return self->symbols != NULL;}static pp_symbol *pp_symbols_find (pp_symbols *self, const char *name){   GLuint i;   for (i = 0; i < self->count; i++)      if (_mesa_strcmp (name, slang_string_cstr (&self->symbols[i].name)) == 0)         return &self->symbols[i];   return NULL;}/* * The condition context of a single #if/#else/#endif level. Those can be nested, so there * is a stack of condition contexts. * There is a special global context on the bottom of the stack. It is there to simplify * context handling. */typedef struct{   GLboolean current;         /* The condition value of this level. */   GLboolean effective;       /* The effective product of current condition, outer level conditions                               * and position within #if-#else-#endif sections. */   GLboolean else_allowed;    /* TRUE if in #if-#else section, FALSE if in #else-#endif section                               * and for global context. */   GLboolean endif_required;  /* FALSE for global context only. */} pp_cond_ctx;/* Should be enuff. */#define CONDITION_STACK_SIZE 64typedef struct{   pp_cond_ctx stack[CONDITION_STACK_SIZE];   pp_cond_ctx *top;} pp_cond_stack;static GLbooleanpp_cond_stack_push (pp_cond_stack *self, slang_info_log *elog){   if (self->top == self->stack) {      slang_info_log_error (elog, "internal compiler error: preprocessor condition stack overflow.");      return GL_FALSE;   }   self->top--;   return GL_TRUE;}static GLvoidpp_cond_stack_reevaluate (pp_cond_stack *self){   /* There must be at least 2 conditions on the stack - one global and one being evaluated. */   assert (self->top <= &self->stack[CONDITION_STACK_SIZE - 2]);   self->top->effective = self->top->current && self->top[1].effective;}/* * Extension enables through #extension directive. * NOTE: Currently, only enable/disable state is stored. */typedef struct{   GLboolean MESA_shader_debug;        /* GL_MESA_shader_debug enable */   GLboolean ARB_texture_rectangle; /* GL_ARB_texture_rectangle enable */} pp_ext;/* * Disable all extensions. Called at startup and on #extension all: disable. */static GLvoidpp_ext_disable_all (pp_ext *self){   self->MESA_shader_debug = GL_FALSE;}static GLvoidpp_ext_init (pp_ext *self){   pp_ext_disable_all (self);   self->ARB_texture_rectangle = GL_TRUE;   /* Other initialization code goes here. */}static GLbooleanpp_ext_set (pp_ext *self, const char *name, GLboolean enable){   if (_mesa_strcmp (name, "MESA_shader_debug") == 0)      self->MESA_shader_debug = enable;   else if (_mesa_strcmp (name, "GL_ARB_texture_rectangle") == 0)      self->ARB_texture_rectangle = enable;   /* Next extension name tests go here. */   else      return GL_FALSE;   return GL_TRUE;}/* * The state of preprocessor: current line, file and version number, list of all defined macros * and the #if/#endif context. */typedef struct{   GLint line;   GLint file;   GLint version;   pp_symbols symbols;   pp_ext ext;   slang_info_log *elog;   pp_cond_stack cond;} pp_state;static GLvoidpp_state_init (pp_state *self, slang_info_log *elog){   self->line = 0;   self->file = 1;#if FEATURE_es2_glsl   self->version = 100;#else   self->version = 110;#endif   pp_symbols_init (&self->symbols);   pp_ext_init (&self->ext);   self->elog = elog;   /* Initialize condition stack and create the global context. */   self->cond.top = &self->cond.stack[CONDITION_STACK_SIZE - 1];   self->cond.top->current = GL_TRUE;   self->cond.top->effective = GL_TRUE;   self->cond.top->else_allowed = GL_FALSE;   self->cond.top->endif_required = GL_FALSE;}static GLvoidpp_state_free (pp_state *self){   pp_symbols_free (&self->symbols);}#define IS_FIRST_ID_CHAR(x) (((x) >= 'a' && (x) <= 'z') || ((x) >= 'A' && (x) <= 'Z') || (x) == '_')#define IS_NEXT_ID_CHAR(x) (IS_FIRST_ID_CHAR(x) || ((x) >= '0' && (x) <= '9'))#define IS_WHITE(x) ((x) == ' ' || (x) == '\n')#define IS_NULL(x) ((x) == '\0')#define SKIP_WHITE(x) do { while (IS_WHITE(*(x))) (x)++; } while (GL_FALSE)typedef struct{   slang_string *output;   const char *input;   pp_state *state;} expand_state;static GLbooleanexpand_defined (expand_state *e, slang_string *buffer){   GLboolean in_paren = GL_FALSE;   const char *id;   /* Parse the optional opening parenthesis. */   SKIP_WHITE(e->input);   if (*e->input == '(') {      e->input++;      in_paren = GL_TRUE;      SKIP_WHITE(e->input);   }   /* Parse operand. */   if (!IS_FIRST_ID_CHAR(*e->input)) {      slang_info_log_error (e->state->elog,                            "preprocess error: identifier expected after operator 'defined'.");      return GL_FALSE;   }   slang_string_reset (buffer);   slang_string_pushc (buffer, *e->input++);   while (IS_NEXT_ID_CHAR(*e->input))      slang_string_pushc (buffer, *e->input++);   id = slang_string_cstr (buffer);   /* Check if the operand is defined. Output 1 if it is defined, output 0 if not. */   if (pp_symbols_find (&e->state->symbols, id) == NULL)      slang_string_pushs (e->output, " 0 ", 3);   else      slang_string_pushs (e->output, " 1 ", 3);   /* Parse the closing parentehesis if the opening one was there. */   if (in_paren) {      SKIP_WHITE(e->input);      if (*e->input != ')') {         slang_info_log_error (e->state->elog, "preprocess error: ')' expected.");         return GL_FALSE;      }      e->input++;      SKIP_WHITE(e->input);   }   return GL_TRUE;}static GLbooleanexpand (expand_state *, pp_symbols *);static GLbooleanexpand_symbol (expand_state *e, pp_symbol *symbol){   expand_state es;   /* If the macro has some parameters, we need to parse them. */   if (symbol->parameters.count != 0) {      GLuint i;      /* Parse the opening parenthesis. */      SKIP_WHITE(e->input);      if (*e->input != '(') {         slang_info_log_error (e->state->elog, "preprocess error: '(' expected.");         return GL_FALSE;      }      e->input++;      SKIP_WHITE(e->input);      /* Parse macro actual parameters. This can be anything, separated by a colon.       * TODO: What about nested/grouped parameters by parenthesis? */      for (i = 0; i < symbol->parameters.count; i++) {         if (*e->input == ')') {            slang_info_log_error (e->state->elog, "preprocess error: unexpected ')'.");            return GL_FALSE;         }         /* Eat all characters up to the comma or closing parentheses. */         pp_symbol_reset (&symbol->parameters.symbols[i]);         while (!IS_NULL(*e->input) && *e->input != ',' && *e->input != ')')            slang_string_pushc (&symbol->parameters.symbols[i].replacement, *e->input++);         /* If it was not the last paremeter, skip the comma. Otherwise, skip the          * closing parentheses. */         if (i + 1 == symbol->parameters.count) {            /* This is the last paremeter - skip the closing parentheses. */            if (*e->input != ')') {               slang_info_log_error (e->state->elog, "preprocess error: ')' expected.");               return GL_FALSE;            }            e->input++;            SKIP_WHITE(e->input);         }         else {            /* Skip the separating comma. */            if (*e->input != ',') {               slang_info_log_error (e->state->elog, "preprocess error: ',' expected.");               return GL_FALSE;            }            e->input++;            SKIP_WHITE(e->input);         }      }   }   /* Expand the macro. Use its parameters as a priority symbol list to expand    * macro parameters correctly. */   es.output = e->output;   es.input = slang_string_cstr (&symbol->replacement);   es.state = e->state;   slang_string_pushc (e->output, ' ');   if (!expand (&es, &symbol->parameters))      return GL_FALSE;   slang_string_pushc (e->output, ' ');   return GL_TRUE;}/* * Function expand() expands source text from <input> to <output>. The expansion is made using * the list passed in <symbols> parameter. It allows us to expand macro formal parameters with * actual parameters. The global list of symbols from pp state is used when doing a recursive * call of expand(). */static GLbooleanexpand (expand_state *e, pp_symbols *symbols){   while (!IS_NULL(*e->input)) {      if (IS_FIRST_ID_CHAR(*e->input)) {         slang_string buffer;         const char *id;         /* Parse the identifier. */         slang_string_init (&buffer);         slang_string_pushc (&buffer, *e->input++);         while (IS_NEXT_ID_CHAR(*e->input))            slang_string_pushc (&buffer, *e->input++);         id = slang_string_cstr (&buffer);         /* Now check if the identifier is special in some way. The "defined" identifier is          * actually an operator that we must handle here and expand it either to " 0 " or " 1 ".          * The other identifiers start with "__" and we expand it to appropriate values          * taken from the preprocessor state. */         if (_mesa_strcmp (id, "defined") == 0) {            if (!expand_defined (e, &buffer))               return GL_FALSE;         }         else if (_mesa_strcmp (id, "__LINE__") == 0) {            slang_string_pushc (e->output, ' ');            slang_string_pushi (e->output, e->state->line);            slang_string_pushc (e->output, ' ');         }         else if (_mesa_strcmp (id, "__FILE__") == 0) {            slang_string_pushc (e->output, ' ');            slang_string_pushi (e->output, e->state->file);            slang_string_pushc (e->output, ' ');         }         else if (_mesa_strcmp (id, "__VERSION__") == 0) {            slang_string_pushc (e->output, ' ');            slang_string_pushi (e->output, e->state->version);            slang_string_pushc (e->output, ' ');         }#if FEATURE_es2_glsl         else if (_mesa_strcmp (id, "GL_ES") == 0 ||                  _mesa_strcmp (id, "GL_FRAGMENT_PRECISION_HIGH") == 0) {            slang_string_pushc (e->output, ' ');            slang_string_pushi (e->output, '1');            slang_string_pushc (e->output, ' ');         }#endif         else {            pp_symbol *symbol;            /* The list of symbols from <symbols> take precedence over the list from <state>.             * Note that in some cases this is the same list so avoid double look-up. */            symbol = pp_symbols_find (symbols, id);            if (symbol == NULL && symbols != &e->state->symbols)               symbol = pp_symbols_find (&e->state->symbols, id);            /* If the symbol was found, recursively expand its definition. */            if (symbol != NULL) {               if (!expand_symbol (e, symbol)) {                  slang_string_free (&buffer);                  return GL_FALSE;               }            }            else {               slang_string_push (e->output, &buffer);            }         }         slang_string_free (&buffer);      }      else if (IS_WHITE(*e->input)) {         slang_string_pushc (e->output, *e->input++);      }      else {         while (!IS_WHITE(*e->input) && !IS_NULL(*e->input) && !IS_FIRST_ID_CHAR(*e->input))            slang_string_pushc (e->output, *e->input++);      }   }   return GL_TRUE;}static GLbooleanparse_if (slang_string *output, const byte *prod, GLuint *pi, GLint *result, pp_state *state,          grammar eid){   const char *text;   GLuint len;   text = (const char *) (&prod[*pi]);   len = _mesa_strlen (text);   if (state->cond.top->effective) {      slang_string expr;      GLuint count;      GLint results[2];      expand_state es;      /* Expand the expression. */      slang_string_init (&expr);      es.output = &expr;      es.input = text;      es.state = state;      if (!expand (&es, &state->symbols))         return GL_FALSE;      /* Execute the expression. */      count = execute_expressions (output, eid, (const byte *) (slang_string_cstr (&expr)),                                   results, state->elog);      slang_string_free (&expr);      if (count != 1)         return GL_FALSE;

⌨️ 快捷键说明

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