aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/glsl/s_expression.cpp
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2011-07-22 08:25:25 +0200
committermarha <marha@users.sourceforge.net>2011-07-22 08:25:25 +0200
commitc70e21be1fe5f9b47bce020ffd8d69c6012b21fc (patch)
tree2ae24d451df0e12093fd82c2cd466e05dfe1aaa0 /mesalib/src/glsl/s_expression.cpp
parent556198b74eecf7e9f7105a792a33bf699cff6507 (diff)
parent91e91b72f07f4e61db17ee86c6933a7217f0e25c (diff)
downloadvcxsrv-c70e21be1fe5f9b47bce020ffd8d69c6012b21fc.tar.gz
vcxsrv-c70e21be1fe5f9b47bce020ffd8d69c6012b21fc.tar.bz2
vcxsrv-c70e21be1fe5f9b47bce020ffd8d69c6012b21fc.zip
Merge remote-tracking branch 'origin/released'
Conflicts: mesalib/src/gallium/auxiliary/util/u_vbuf_mgr.c mesalib/src/glsl/ast_function.cpp mesalib/src/glsl/ast_to_hir.cpp mesalib/src/glsl/glsl_types.cpp mesalib/src/glsl/ir.cpp mesalib/src/glsl/ir.h mesalib/src/glsl/linker.cpp mesalib/src/glsl/s_expression.cpp mesalib/src/mesa/drivers/common/driverfuncs.c mesalib/src/mesa/main/dd.h mesalib/src/mesa/main/fbobject.c mesalib/src/mesa/main/teximage.c mesalib/src/mesa/state_tracker/st_cb_texture.c
Diffstat (limited to 'mesalib/src/glsl/s_expression.cpp')
-rw-r--r--mesalib/src/glsl/s_expression.cpp64
1 files changed, 46 insertions, 18 deletions
diff --git a/mesalib/src/glsl/s_expression.cpp b/mesalib/src/glsl/s_expression.cpp
index b47b014c6..b6a51c34e 100644
--- a/mesalib/src/glsl/s_expression.cpp
+++ b/mesalib/src/glsl/s_expression.cpp
@@ -25,10 +25,13 @@
#include <assert.h>
#include "s_expression.h"
-s_symbol::s_symbol(const char *tmp, size_t n)
+s_symbol::s_symbol(const char *str, size_t n)
{
- this->str = ralloc_strndup (this, tmp, n);
- assert(this->str != NULL);
+ /* Assume the given string is already nul-terminated and in memory that
+ * will live as long as this node.
+ */
+ assert(str[n] == '\0');
+ this->str = str;
}
s_list::s_list()
@@ -36,22 +39,26 @@ s_list::s_list()
}
static void
-skip_whitespace(const char *& src)
+skip_whitespace(const char *&src, char *&symbol_buffer)
{
- src += strspn(src, " \v\t\r\n");
+ size_t n = strspn(src, " \v\t\r\n");
+ src += n;
+ symbol_buffer += n;
/* Also skip Scheme-style comments: semi-colon 'til end of line */
if (src[0] == ';') {
- src += strcspn(src, "\n");
- skip_whitespace(src);
+ n = strcspn(src, "\n");
+ src += n;
+ symbol_buffer += n;
+ skip_whitespace(src, symbol_buffer);
}
}
static s_expression *
-read_atom(void *ctx, const char *& src)
+read_atom(void *ctx, const char *&src, char *&symbol_buffer)
{
s_expression *expr = NULL;
- skip_whitespace(src);
+ skip_whitespace(src, symbol_buffer);
size_t n = strcspn(src, "( \v\t\r\n);");
if (n == 0)
@@ -70,44 +77,65 @@ read_atom(void *ctx, const char *& src)
expr = new(ctx) s_int(i);
} else {
// Not a number; return a symbol.
- expr = new(ctx) s_symbol(src, n);
+ symbol_buffer[n] = '\0';
+ expr = new(ctx) s_symbol(symbol_buffer, n);
}
src += n;
+ symbol_buffer += n;
return expr;
}
-s_expression *
-s_expression::read_expression(void *ctx, const char *&src)
+static s_expression *
+__read_expression(void *ctx, const char *&src, char *&symbol_buffer)
{
- assert(src != NULL);
-
- s_expression *atom = read_atom(ctx, src);
+ s_expression *atom = read_atom(ctx, src, symbol_buffer);
if (atom != NULL)
return atom;
- skip_whitespace(src);
+ skip_whitespace(src, symbol_buffer);
if (src[0] == '(') {
++src;
+ ++symbol_buffer;
s_list *list = new(ctx) s_list;
s_expression *expr;
- while ((expr = read_expression(ctx, src)) != NULL) {
+ while ((expr = __read_expression(ctx, src, symbol_buffer)) != NULL) {
list->subexpressions.push_tail(expr);
}
- skip_whitespace(src);
+ skip_whitespace(src, symbol_buffer);
if (src[0] != ')') {
printf("Unclosed expression (check your parenthesis).\n");
return NULL;
}
++src;
+ ++symbol_buffer;
return list;
}
return NULL;
}
+s_expression *
+s_expression::read_expression(void *ctx, const char *&src)
+{
+ assert(src != NULL);
+
+ /* When we encounter a Symbol, we need to save a nul-terminated copy of
+ * the string. However, ralloc_strndup'ing every individual Symbol is
+ * extremely expensive. We could avoid this by simply overwriting the
+ * next character (guaranteed to be whitespace, parens, or semicolon) with
+ * a nul-byte. But overwriting non-whitespace would mess up parsing.
+ *
+ * So, just copy the whole buffer ahead of time. Walk both, leaving the
+ * original source string unmodified, and altering the copy to contain the
+ * necessary nul-bytes whenever we encounter a symbol.
+ */
+ char *symbol_buffer = ralloc_strdup(ctx, src);
+ return __read_expression(ctx, src, symbol_buffer);
+}
+
void s_int::print()
{
printf("%d", this->val);