2016-03-19 15:14:35 +00:00
|
|
|
#include "first.h"
|
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
#include "buffer.h"
|
|
|
|
#include "log.h"
|
|
|
|
#include "mod_ssi.h"
|
|
|
|
#include "mod_ssi_expr.h"
|
|
|
|
#include "mod_ssi_exprparser.h"
|
|
|
|
|
2009-10-11 14:31:42 +00:00
|
|
|
#include <ctype.h>
|
2018-03-25 07:45:05 +00:00
|
|
|
#include <stdlib.h>
|
2009-10-11 14:31:42 +00:00
|
|
|
#include <string.h>
|
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
typedef struct {
|
|
|
|
const char *input;
|
|
|
|
size_t offset;
|
|
|
|
size_t size;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
int line_pos;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
int in_key;
|
|
|
|
int in_brace;
|
|
|
|
int in_cond;
|
|
|
|
} ssi_tokenizer_t;
|
|
|
|
|
2012-08-31 14:11:41 +00:00
|
|
|
ssi_val_t *ssi_val_init(void) {
|
2005-02-20 14:27:00 +00:00
|
|
|
ssi_val_t *s;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
s = calloc(1, sizeof(*s));
|
2021-03-17 00:27:05 +00:00
|
|
|
force_assert(s);
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ssi_val_free(ssi_val_t *s) {
|
|
|
|
if (s->str) buffer_free(s->str);
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
free(s);
|
|
|
|
}
|
|
|
|
|
2021-03-15 09:41:50 +00:00
|
|
|
__attribute_pure__
|
2005-02-20 14:27:00 +00:00
|
|
|
int ssi_val_tobool(ssi_val_t *B) {
|
|
|
|
if (B->type == SSI_TYPE_STRING) {
|
[multiple] reduce redundant NULL buffer checks
This commit is a large set of code changes and results in removal of
hundreds, perhaps thousands, of CPU instructions, a portion of which
are on hot code paths.
Most (buffer *) used by lighttpd are not NULL, especially since buffers
were inlined into numerous larger structs such as request_st and chunk.
In the small number of instances where that is not the case, a NULL
check is often performed earlier in a function where that buffer is
later used with a buffer_* func. In the handful of cases that remained,
a NULL check was added, e.g. with r->http_host and r->conf.server_tag.
- check for empty strings at config time and set value to NULL if blank
string will be ignored at runtime; at runtime, simple pointer check
for NULL can be used to check for a value that has been set and is not
blank ("")
- use buffer_is_blank() instead of buffer_string_is_empty(),
and use buffer_is_unset() instead of buffer_is_empty(),
where buffer is known not to be NULL so that NULL check can be skipped
- use buffer_clen() instead of buffer_string_length() when buffer is
known not to be NULL (to avoid NULL check at runtime)
- use buffer_truncate() instead of buffer_string_set_length() to
truncate string, and use buffer_extend() to extend
Examples where buffer known not to be NULL:
- cpv->v.b from config_plugin_values_init is not NULL if T_CONFIG_BOOL
(though we might set it to NULL if buffer_is_blank(cpv->v.b))
- address of buffer is arg (&foo)
(compiler optimizer detects this in most, but not all, cases)
- buffer is checked for NULL earlier in func
- buffer is accessed in same scope without a NULL check (e.g. b->ptr)
internal behavior change:
callers must not pass a NULL buffer to some funcs.
- buffer_init_buffer() requires non-null args
- buffer_copy_buffer() requires non-null args
- buffer_append_string_buffer() requires non-null args
- buffer_string_space() requires non-null arg
2021-06-09 02:57:36 +00:00
|
|
|
return !buffer_is_blank(B->str);
|
2005-02-20 14:27:00 +00:00
|
|
|
} else {
|
|
|
|
return B->bo;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-25 06:54:08 +00:00
|
|
|
static int ssi_expr_tokenizer(handler_ctx *p,
|
2005-02-20 14:27:00 +00:00
|
|
|
ssi_tokenizer_t *t, int *token_id, buffer *token) {
|
|
|
|
int tid = 0;
|
|
|
|
size_t i;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
for (tid = 0; tid == 0 && t->offset < t->size && t->input[t->offset] ; ) {
|
|
|
|
char c = t->input[t->offset];
|
2019-10-10 03:24:25 +00:00
|
|
|
const data_string *ds;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
switch (c) {
|
2006-10-04 13:26:23 +00:00
|
|
|
case '=':
|
2005-02-20 14:27:00 +00:00
|
|
|
tid = TK_EQ;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
t->offset++;
|
|
|
|
t->line_pos++;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2008-07-30 19:38:32 +00:00
|
|
|
buffer_copy_string_len(token, CONST_STR_LEN("(=)"));
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
break;
|
|
|
|
case '>':
|
|
|
|
if (t->input[t->offset + 1] == '=') {
|
|
|
|
t->offset += 2;
|
|
|
|
t->line_pos += 2;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
tid = TK_GE;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2008-07-30 19:38:32 +00:00
|
|
|
buffer_copy_string_len(token, CONST_STR_LEN("(>=)"));
|
2005-02-20 14:27:00 +00:00
|
|
|
} else {
|
|
|
|
t->offset += 1;
|
|
|
|
t->line_pos += 1;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
tid = TK_GT;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2008-07-30 19:38:32 +00:00
|
|
|
buffer_copy_string_len(token, CONST_STR_LEN("(>)"));
|
2005-02-20 14:27:00 +00:00
|
|
|
}
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
break;
|
|
|
|
case '<':
|
|
|
|
if (t->input[t->offset + 1] == '=') {
|
|
|
|
t->offset += 2;
|
|
|
|
t->line_pos += 2;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
tid = TK_LE;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2008-07-30 19:38:32 +00:00
|
|
|
buffer_copy_string_len(token, CONST_STR_LEN("(<=)"));
|
2005-02-20 14:27:00 +00:00
|
|
|
} else {
|
|
|
|
t->offset += 1;
|
|
|
|
t->line_pos += 1;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
tid = TK_LT;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2008-07-30 19:38:32 +00:00
|
|
|
buffer_copy_string_len(token, CONST_STR_LEN("(<)"));
|
2005-02-20 14:27:00 +00:00
|
|
|
}
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
break;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
case '!':
|
|
|
|
if (t->input[t->offset + 1] == '=') {
|
|
|
|
t->offset += 2;
|
|
|
|
t->line_pos += 2;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
tid = TK_NE;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2008-07-30 19:38:32 +00:00
|
|
|
buffer_copy_string_len(token, CONST_STR_LEN("(!=)"));
|
2005-02-20 14:27:00 +00:00
|
|
|
} else {
|
|
|
|
t->offset += 1;
|
|
|
|
t->line_pos += 1;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
tid = TK_NOT;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2008-07-30 19:38:32 +00:00
|
|
|
buffer_copy_string_len(token, CONST_STR_LEN("(!)"));
|
2005-02-20 14:27:00 +00:00
|
|
|
}
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
break;
|
|
|
|
case '&':
|
|
|
|
if (t->input[t->offset + 1] == '&') {
|
|
|
|
t->offset += 2;
|
|
|
|
t->line_pos += 2;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
tid = TK_AND;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2008-07-30 19:38:32 +00:00
|
|
|
buffer_copy_string_len(token, CONST_STR_LEN("(&&)"));
|
2005-02-20 14:27:00 +00:00
|
|
|
} else {
|
2019-11-25 06:54:08 +00:00
|
|
|
log_error(p->errh, __FILE__, __LINE__,
|
|
|
|
"pos: %d missing second &", t->line_pos);
|
2005-02-20 14:27:00 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
break;
|
|
|
|
case '|':
|
|
|
|
if (t->input[t->offset + 1] == '|') {
|
|
|
|
t->offset += 2;
|
|
|
|
t->line_pos += 2;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
tid = TK_OR;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2008-07-30 19:38:32 +00:00
|
|
|
buffer_copy_string_len(token, CONST_STR_LEN("(||)"));
|
2005-02-20 14:27:00 +00:00
|
|
|
} else {
|
2019-11-25 06:54:08 +00:00
|
|
|
log_error(p->errh, __FILE__, __LINE__,
|
|
|
|
"pos: %d missing second |", t->line_pos);
|
2005-02-20 14:27:00 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
break;
|
|
|
|
case '\t':
|
|
|
|
case ' ':
|
|
|
|
t->offset++;
|
|
|
|
t->line_pos++;
|
|
|
|
break;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
case '\'':
|
|
|
|
/* search for the terminating " */
|
|
|
|
for (i = 1; t->input[t->offset + i] && t->input[t->offset + i] != '\''; i++);
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
if (t->input[t->offset + i]) {
|
|
|
|
tid = TK_VALUE;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
buffer_copy_string_len(token, t->input + t->offset + 1, i-1);
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
t->offset += i + 1;
|
|
|
|
t->line_pos += i + 1;
|
|
|
|
} else {
|
|
|
|
/* ERROR */
|
2019-11-25 06:54:08 +00:00
|
|
|
log_error(p->errh, __FILE__, __LINE__,
|
|
|
|
"pos: %d missing closing quote", t->line_pos);
|
2005-02-20 14:27:00 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
break;
|
|
|
|
case '(':
|
|
|
|
t->offset++;
|
|
|
|
t->in_brace++;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
tid = TK_LPARAN;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2008-07-30 19:38:32 +00:00
|
|
|
buffer_copy_string_len(token, CONST_STR_LEN("("));
|
2005-02-20 14:27:00 +00:00
|
|
|
break;
|
|
|
|
case ')':
|
|
|
|
t->offset++;
|
|
|
|
t->in_brace--;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
tid = TK_RPARAN;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2008-07-30 19:38:32 +00:00
|
|
|
buffer_copy_string_len(token, CONST_STR_LEN(")"));
|
2005-02-20 14:27:00 +00:00
|
|
|
break;
|
|
|
|
case '$':
|
|
|
|
if (t->input[t->offset + 1] == '{') {
|
|
|
|
for (i = 2; t->input[t->offset + i] && t->input[t->offset + i] != '}'; i++);
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
if (t->input[t->offset + i] != '}') {
|
2019-11-25 06:54:08 +00:00
|
|
|
log_error(p->errh, __FILE__, __LINE__,
|
|
|
|
"pos: %d missing closing curly-brace", t->line_pos);
|
2005-02-20 14:27:00 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
buffer_copy_string_len(token, t->input + t->offset + 2, i-3);
|
|
|
|
} else {
|
2020-03-23 21:40:46 +00:00
|
|
|
for (i = 1; isalpha(((unsigned char *)t->input)[t->offset + i]) ||
|
2016-01-03 14:48:07 +00:00
|
|
|
t->input[t->offset + i] == '_' ||
|
2020-03-23 21:40:46 +00:00
|
|
|
((i > 1) && isdigit(((unsigned char *)t->input)[t->offset + i])); i++);
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
buffer_copy_string_len(token, t->input + t->offset + 1, i-1);
|
|
|
|
}
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
tid = TK_VALUE;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
[multiple] reduce redundant NULL buffer checks
This commit is a large set of code changes and results in removal of
hundreds, perhaps thousands, of CPU instructions, a portion of which
are on hot code paths.
Most (buffer *) used by lighttpd are not NULL, especially since buffers
were inlined into numerous larger structs such as request_st and chunk.
In the small number of instances where that is not the case, a NULL
check is often performed earlier in a function where that buffer is
later used with a buffer_* func. In the handful of cases that remained,
a NULL check was added, e.g. with r->http_host and r->conf.server_tag.
- check for empty strings at config time and set value to NULL if blank
string will be ignored at runtime; at runtime, simple pointer check
for NULL can be used to check for a value that has been set and is not
blank ("")
- use buffer_is_blank() instead of buffer_string_is_empty(),
and use buffer_is_unset() instead of buffer_is_empty(),
where buffer is known not to be NULL so that NULL check can be skipped
- use buffer_clen() instead of buffer_string_length() when buffer is
known not to be NULL (to avoid NULL check at runtime)
- use buffer_truncate() instead of buffer_string_set_length() to
truncate string, and use buffer_extend() to extend
Examples where buffer known not to be NULL:
- cpv->v.b from config_plugin_values_init is not NULL if T_CONFIG_BOOL
(though we might set it to NULL if buffer_is_blank(cpv->v.b))
- address of buffer is arg (&foo)
(compiler optimizer detects this in most, but not all, cases)
- buffer is checked for NULL earlier in func
- buffer is accessed in same scope without a NULL check (e.g. b->ptr)
internal behavior change:
callers must not pass a NULL buffer to some funcs.
- buffer_init_buffer() requires non-null args
- buffer_copy_buffer() requires non-null args
- buffer_append_string_buffer() requires non-null args
- buffer_string_space() requires non-null arg
2021-06-09 02:57:36 +00:00
|
|
|
if (NULL != (ds = (const data_string *)array_get_element_klen(p->ssi_cgi_env, BUF_PTR_LEN(token)))) {
|
2019-10-13 08:59:57 +00:00
|
|
|
buffer_copy_buffer(token, &ds->value);
|
[multiple] reduce redundant NULL buffer checks
This commit is a large set of code changes and results in removal of
hundreds, perhaps thousands, of CPU instructions, a portion of which
are on hot code paths.
Most (buffer *) used by lighttpd are not NULL, especially since buffers
were inlined into numerous larger structs such as request_st and chunk.
In the small number of instances where that is not the case, a NULL
check is often performed earlier in a function where that buffer is
later used with a buffer_* func. In the handful of cases that remained,
a NULL check was added, e.g. with r->http_host and r->conf.server_tag.
- check for empty strings at config time and set value to NULL if blank
string will be ignored at runtime; at runtime, simple pointer check
for NULL can be used to check for a value that has been set and is not
blank ("")
- use buffer_is_blank() instead of buffer_string_is_empty(),
and use buffer_is_unset() instead of buffer_is_empty(),
where buffer is known not to be NULL so that NULL check can be skipped
- use buffer_clen() instead of buffer_string_length() when buffer is
known not to be NULL (to avoid NULL check at runtime)
- use buffer_truncate() instead of buffer_string_set_length() to
truncate string, and use buffer_extend() to extend
Examples where buffer known not to be NULL:
- cpv->v.b from config_plugin_values_init is not NULL if T_CONFIG_BOOL
(though we might set it to NULL if buffer_is_blank(cpv->v.b))
- address of buffer is arg (&foo)
(compiler optimizer detects this in most, but not all, cases)
- buffer is checked for NULL earlier in func
- buffer is accessed in same scope without a NULL check (e.g. b->ptr)
internal behavior change:
callers must not pass a NULL buffer to some funcs.
- buffer_init_buffer() requires non-null args
- buffer_copy_buffer() requires non-null args
- buffer_append_string_buffer() requires non-null args
- buffer_string_space() requires non-null arg
2021-06-09 02:57:36 +00:00
|
|
|
} else if (NULL != (ds = (const data_string *)array_get_element_klen(p->ssi_vars, BUF_PTR_LEN(token)))) {
|
2019-10-13 08:59:57 +00:00
|
|
|
buffer_copy_buffer(token, &ds->value);
|
2005-02-20 14:27:00 +00:00
|
|
|
} else {
|
2008-07-30 19:38:32 +00:00
|
|
|
buffer_copy_string_len(token, CONST_STR_LEN(""));
|
2005-02-20 14:27:00 +00:00
|
|
|
}
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
t->offset += i;
|
|
|
|
t->line_pos += i;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
break;
|
|
|
|
default:
|
2020-03-23 21:40:46 +00:00
|
|
|
for (i = 0; isgraph(((unsigned char *)t->input)[t->offset + i]); i++) {
|
2005-02-20 14:27:00 +00:00
|
|
|
char d = t->input[t->offset + i];
|
|
|
|
switch(d) {
|
2006-10-04 13:26:23 +00:00
|
|
|
case ' ':
|
2005-02-20 14:27:00 +00:00
|
|
|
case '\t':
|
|
|
|
case ')':
|
|
|
|
case '(':
|
|
|
|
case '\'':
|
|
|
|
case '=':
|
|
|
|
case '!':
|
|
|
|
case '<':
|
|
|
|
case '>':
|
|
|
|
case '&':
|
|
|
|
case '|':
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
tid = TK_VALUE;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
buffer_copy_string_len(token, t->input + t->offset, i);
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
t->offset += i;
|
|
|
|
t->line_pos += i;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
if (tid) {
|
|
|
|
*token_id = tid;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
return 1;
|
|
|
|
} else if (t->offset < t->size) {
|
2019-11-25 06:54:08 +00:00
|
|
|
log_error(p->errh, __FILE__, __LINE__,
|
|
|
|
"pos: %d foobar", t->line_pos);
|
2005-02-20 14:27:00 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-11-25 06:54:08 +00:00
|
|
|
int ssi_eval_expr(handler_ctx *p, const char *expr) {
|
2005-02-20 14:27:00 +00:00
|
|
|
ssi_tokenizer_t t;
|
|
|
|
void *pParser;
|
|
|
|
int token_id;
|
|
|
|
buffer *token;
|
|
|
|
ssi_ctx_t context;
|
|
|
|
int ret;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
t.input = expr;
|
|
|
|
t.offset = 0;
|
|
|
|
t.size = strlen(expr);
|
|
|
|
t.line_pos = 1;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
t.in_key = 1;
|
|
|
|
t.in_brace = 0;
|
|
|
|
t.in_cond = 0;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
context.ok = 1;
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
/* default context */
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
pParser = ssiexprparserAlloc( malloc );
|
2015-10-16 19:44:06 +00:00
|
|
|
force_assert(pParser);
|
2005-02-20 14:27:00 +00:00
|
|
|
token = buffer_init();
|
2019-11-25 06:54:08 +00:00
|
|
|
while((1 == (ret = ssi_expr_tokenizer(p, &t, &token_id, token))) && context.ok) {
|
2005-02-20 14:27:00 +00:00
|
|
|
ssiexprparser(pParser, token_id, token, &context);
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
token = buffer_init();
|
|
|
|
}
|
|
|
|
ssiexprparser(pParser, 0, token, &context);
|
|
|
|
ssiexprparserFree(pParser, free );
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
buffer_free(token);
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
if (ret == -1) {
|
2019-11-25 06:54:08 +00:00
|
|
|
log_error(p->errh, __FILE__, __LINE__, "expr parser failed");
|
2005-02-20 14:27:00 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2006-10-04 13:26:23 +00:00
|
|
|
|
2005-02-20 14:27:00 +00:00
|
|
|
if (context.ok == 0) {
|
2019-11-25 06:54:08 +00:00
|
|
|
log_error(p->errh, __FILE__, __LINE__,
|
|
|
|
"pos: %d parser failed somehow near here", t.line_pos);
|
2005-02-20 14:27:00 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
#if 0
|
2019-11-25 06:54:08 +00:00
|
|
|
log_error(p->errh, __FILE__, __LINE__,
|
|
|
|
"expr: %s %d", expr, context.val.bo);
|
2006-10-04 13:26:23 +00:00
|
|
|
#endif
|
2005-02-20 14:27:00 +00:00
|
|
|
return context.val.bo;
|
|
|
|
}
|