#endif /* !APR_CHARSET_EBCDIC */
-/*
- * +-------------------------------------------------------+
- * | |
- * | Debugging Macros
- * | |
- * +-------------------------------------------------------+
- */
-
-#ifdef DEBUG_INCLUDE
-
-#define MAX_DEBUG_SIZE MAX_STRING_LEN
-
-#define LOG_COND_STATUS(ctx, f, bb, text) \
-do { \
- char *cond_txt = apr_pstrcat((ctx)->dpool, "**** ", (text), \
- " conditional_status=\"", ((ctx)->flags & SSI_FLAG_COND_TRUE)?"1":"0", \
- "\"\n", NULL); \
- APR_BRIGADE_INSERT_TAIL((bb), apr_bucket_heap_create(cond_txt, \
- strlen(cond_txt), NULL, (f)->c->bucket_alloc)); \
-} while(0)
-
-#define DUMP_PARSE_EXPR_DEBUG(buf, f, bb) \
-do { \
- APR_BRIGADE_INSERT_TAIL((bb), apr_bucket_heap_create((buf), \
- strlen((buf)), NULL, (f)->c->bucket_alloc)); \
-} while(0)
-
-#else
-
-#define MAX_DEBUG_SIZE 10
-#define LOG_COND_STATUS(ctx, f, bb, text)
-#define DUMP_PARSE_EXPR_DEBUG(buf, f, bb)
-
-#endif
-
-
/*
* +-------------------------------------------------------+
* | |
const char *string;
} result_item_t;
+/* conditional expression parser stuff */
+typedef enum {
+ TOKEN_STRING,
+ TOKEN_RE,
+ TOKEN_AND,
+ TOKEN_OR,
+ TOKEN_NOT,
+ TOKEN_EQ,
+ TOKEN_NE,
+ TOKEN_RBRACE,
+ TOKEN_LBRACE,
+ TOKEN_GROUP,
+ TOKEN_GE,
+ TOKEN_LE,
+ TOKEN_GT,
+ TOKEN_LT
+} token_type_t;
+
+typedef struct {
+ token_type_t type;
+ const char *value;
+#ifdef DEBUG_INCLUDE
+ const char *s;
+#endif
+} token_t;
+
+typedef struct parse_node {
+ struct parse_node *parent;
+ struct parse_node *left;
+ struct parse_node *right;
+ token_t token;
+ int value;
+ int done;
+} parse_node_t;
+
typedef enum {
XBITHACK_OFF,
XBITHACK_ON,
XBITHACK_FULL
} xbithack_t;
-typedef struct {
- unsigned int T[256];
- unsigned int x;
- apr_size_t pattern_len;
-} bndm_t;
-
typedef struct {
const char *default_error_msg;
const char *default_time_fmt;
regmatch_t match[MAX_NMATCH];
} backref_t;
+typedef struct {
+ unsigned int T[256];
+ unsigned int x;
+ apr_size_t pattern_len;
+} bndm_t;
+
struct ssi_internal_ctx {
parse_state_t state;
int seen_eos;
arg_item_t *argv; /* all arguments */
backref_t *re; /* NULL if there wasn't a regex yet */
+
+#ifdef DEBUG_INCLUDE
+ struct {
+ ap_filter_t *f;
+ apr_bucket_brigade *bb;
+ } debug;
+#endif
};
+/*
+ * +-------------------------------------------------------+
+ * | |
+ * | Debugging Utilities
+ * | |
+ * +-------------------------------------------------------+
+ */
+
+#ifdef DEBUG_INCLUDE
+static void debug_printf(include_ctx_t *ctx, const char *fmt, ...)
+{
+ va_list ap;
+ char *debug__str;
+
+ va_start(ap, fmt);
+ debug__str = apr_pvsprintf(ctx->pool, fmt, ap);
+ va_end(ap);
+
+ APR_BRIGADE_INSERT_TAIL(ctx->intern->debug.bb, apr_bucket_pool_create(
+ debug__str, strlen(debug__str), ctx->pool,
+ ctx->intern->debug.f->c->bucket_alloc));
+}
+
+#define DEBUG_INIT(ctx, filter, brigade) do { \
+ (ctx)->intern->debug.f = filter; \
+ (ctx)->intern->debug.bb = brigade; \
+} while(0)
+
+#define DEBUG_PRINTF(arg) debug_printf arg
+
+#define TYPE_TOKEN(token, ttype) do { \
+ (token)->type = ttype; \
+ (token)->s = #ttype; \
+} while(0)
+
+#define DEBUG_DUMP_TOKEN(ctx, token) do { \
+ token_t *d__t = (token); \
+ \
+ if (d__t->type == TOKEN_STRING || d__t->type == TOKEN_RE) { \
+ DEBUG_PRINTF(((ctx), " Token: %s (%s)\n", d__t->s, d__t->value)); \
+ } \
+ else { \
+ DEBUG_PRINTF((ctx, " Token: %s\n", d__t->s)); \
+ } \
+} while(0)
+
+#define DEBUG_DUMP_UNMATCHED(ctx, unmatched) do { \
+ if (unmatched) { \
+ DEBUG_PRINTF(((ctx), " Umatched %c\n", (char)(unmatched))); \
+ } \
+} while(0)
+
+#define DEBUG_DUMP_COND(ctx, text) \
+ DEBUG_PRINTF(((ctx), "**** %s cond status=\"%c\"\n", (text), \
+ ((ctx)->flags & SSI_FLAG_COND_TRUE) ? '1' : '0'))
+
+#else /* DEBUG_INCLUDE */
+
+#define TYPE_TOKEN(token, ttype) (token)->type = ttype
+#define DEBUG_INIT(ctx, f, bb)
+#define DEBUG_PRINTF(arg)
+#define DEBUG_DUMP_TOKEN(ctx, token)
+#define DEBUG_DUMP_UNMATCHED(ctx, unmatched)
+#define DEBUG_DUMP_COND(ctx, text)
+
+#endif /* !DEBUG_INCLUDE */
+
+
/*
* +-------------------------------------------------------+
* | |
* +-------------------------------------------------------+
*/
-static APR_INLINE int re_check(include_ctx_t *ctx, char *string, char *rexp)
+static APR_INLINE int re_check(include_ctx_t *ctx, const char *string,
+ const char *rexp)
{
regex_t *compiled;
backref_t *re = ctx->intern->re;
re = ctx->intern->re = apr_palloc(ctx->pool, sizeof(*re));
}
- re->source = string;
- re->rexp = rexp;
+ re->source = apr_pstrdup(ctx->pool, string);
+ re->rexp = apr_pstrdup(ctx->pool, rexp);
re->nsub = compiled->re_nsub;
rc = !ap_regexec(compiled, string, MAX_NMATCH, re->match, 0);
return rc;
}
-enum token_type {
- token_string, token_re,
- token_and, token_or, token_not, token_eq, token_ne,
- token_rbrace, token_lbrace, token_group,
- token_ge, token_le, token_gt, token_lt
-};
-struct token {
- enum token_type type;
- char* value;
-};
-
-static const char *get_ptoken(request_rec *r, const char *string,
- struct token *token, int *unmatched)
+static int get_ptoken(apr_pool_t *pool, const char **parse, token_t *token)
{
- char ch;
- int next = 0;
- char qs = 0;
- int tkn_fnd = 0;
+ const char *p;
+ apr_size_t shift;
+ int unmatched;
token->value = NULL;
- /* Skip leading white space */
- if (string == (char *) NULL) {
- return (char *) NULL;
+ if (!*parse) {
+ return 0;
}
- while ((ch = *string++)) {
- if (!apr_isspace(ch)) {
- break;
- }
+
+ /* Skip leading white space */
+ while (apr_isspace(**parse)) {
+ ++*parse;
}
- if (ch == '\0') {
- return (char *) NULL;
+
+ if (!**parse) {
+ *parse = NULL;
+ return 0;
}
- token->type = token_string; /* the default type */
- switch (ch) {
+ TYPE_TOKEN(token, TOKEN_STRING); /* the default type */
+ p = *parse;
+ unmatched = 0;
+
+ switch (*(*parse)++) {
case '(':
- token->type = token_lbrace;
- return (string);
+ TYPE_TOKEN(token, TOKEN_LBRACE);
+ return 0;
case ')':
- token->type = token_rbrace;
- return (string);
+ TYPE_TOKEN(token, TOKEN_RBRACE);
+ return 0;
case '=':
- token->type = token_eq;
- return (string);
+ TYPE_TOKEN(token, TOKEN_EQ);
+ return 0;
case '!':
- if (*string == '=') {
- token->type = token_ne;
- return (string + 1);
- }
- else {
- token->type = token_not;
- return (string);
+ if (**parse == '=') {
+ TYPE_TOKEN(token, TOKEN_NE);
+ ++*parse;
+ return 0;
}
+ TYPE_TOKEN(token, TOKEN_NOT);
+ return 0;
case '\'':
- /* already token->type == token_string */
- qs = '\'';
+ unmatched = '\'';
break;
case '/':
- token->type = token_re;
- qs = '/';
+ TYPE_TOKEN(token, TOKEN_RE);
+ unmatched = '/';
break;
case '|':
- if (*string == '|') {
- token->type = token_or;
- return (string + 1);
+ if (**parse == '|') {
+ TYPE_TOKEN(token, TOKEN_OR);
+ ++*parse;
+ return 0;
}
break;
case '&':
- if (*string == '&') {
- token->type = token_and;
- return (string + 1);
+ if (**parse == '&') {
+ TYPE_TOKEN(token, TOKEN_AND);
+ ++*parse;
+ return 0;
}
break;
case '>':
- if (*string == '=') {
- token->type = token_ge;
- return (string + 1);
- }
- else {
- token->type = token_gt;
- return (string);
+ if (**parse == '=') {
+ TYPE_TOKEN(token, TOKEN_GE);
+ ++*parse;
+ return 0;
}
+ TYPE_TOKEN(token, TOKEN_GT);
+ return 0;
case '<':
- if (*string == '=') {
- token->type = token_le;
- return (string + 1);
- }
- else {
- token->type = token_lt;
- return (string);
+ if (**parse == '=') {
+ TYPE_TOKEN(token, TOKEN_LE);
+ ++*parse;
+ return 0;
}
- default:
- /* already token->type == token_string */
- break;
- }
- /* We should only be here if we are in a string */
- token->value = apr_palloc(r->pool, strlen(string) + 2); /* 2 for ch plus
- trailing null */
- if (!qs) {
- token->value[next++] = ch;
+ TYPE_TOKEN(token, TOKEN_LT);
+ return 0;
}
- /*
- * I used the ++string throughout this section so that string
- * ends up pointing to the next token and I can just return it
+ /*
+ * It's a string or regex token
*/
- for (ch = *string; ((ch != '\0') && (!tkn_fnd)); ch = *++string) {
- if (ch == '\\') {
- if ((ch = *++string) == '\0') {
- tkn_fnd = 1;
- }
- else {
- token->value[next++] = ch;
+ token->value = unmatched ? *parse : p;
+
+ /* Now search for the next token, which finishes this string */
+ shift = 0;
+ p = *parse;
+ for (; **parse; p = ++*parse) {
+ if (**parse == '\\') {
+ if (!*(++*parse)) {
+ p = *parse;
+ break;
}
+
+ ++shift;
}
else {
- if (!qs) {
- if (apr_isspace(ch)) {
- tkn_fnd = 1;
- }
- else {
- switch (ch) {
- case '(':
- case ')':
- case '=':
- case '!':
- case '<':
- case '>':
- tkn_fnd = 1;
- break;
- case '|':
- if (*(string + 1) == '|') {
- tkn_fnd = 1;
- }
- break;
- case '&':
- if (*(string + 1) == '&') {
- tkn_fnd = 1;
- }
- break;
- }
- if (!tkn_fnd) {
- token->value[next++] = ch;
- }
+ if (unmatched) {
+ if (**parse == unmatched) {
+ unmatched = 0;
+ ++*parse;
+ break;
}
+ } else if (apr_isspace(**parse)) {
+ break;
}
else {
- if (ch == qs) {
- qs = 0;
- tkn_fnd = 1;
- string++;
+ int found = 0;
+
+ switch (**parse) {
+ case '(':
+ case ')':
+ case '=':
+ case '!':
+ case '<':
+ case '>':
+ ++found;
+ break;
+
+ case '|':
+ case '&':
+ if ((*parse)[1] == **parse) {
+ ++found;
+ }
+ break;
}
- else {
- token->value[next++] = ch;
+
+ if (found) {
+ break;
}
}
}
- if (tkn_fnd) {
- break;
- }
}
- /* If qs is still set, we have an unmatched quote */
- if (qs) {
- *unmatched = 1;
- next = 0;
+ if (unmatched) {
+ token->value = apr_pstrdup(pool, "");
}
- token->value[next] = '\0';
+ else {
+ apr_size_t len = p - token->value - shift;
+ char *c = apr_palloc(pool, len + 1);
- return (string);
-}
+ p = token->value;
+ token->value = c;
+ while (shift--) {
+ const char *e = ap_strchr_c(p, '\\');
-/* there is an implicit assumption here that expr is at most MAX_STRING_LEN-1
- * characters long...
- */
-static int parse_expr(request_rec *r, include_ctx_t *ctx, const char *expr,
- int *was_error, int *was_unmatched, char *debug)
+ memcpy(c, p, e-p);
+ c += e-p;
+ *c++ = *++e;
+ len -= e-p;
+ p = e+1;
+ }
+
+ if (len) {
+ memcpy(c, p, len);
+ }
+ c[len] = '\0';
+ }
+
+ return unmatched;
+}
+
+static int parse_expr(include_ctx_t *ctx, const char *expr, int *was_error)
{
- struct parse_node {
- struct parse_node *left, *right, *parent;
- struct token token;
- int value, done;
- } *root, *current, *new;
- const char *parse;
- char* buffer;
- int retval = 0;
- apr_size_t debug_pos = 0;
-
- debug[debug_pos] = '\0';
- *was_error = 0;
- *was_unmatched = 0;
- if ((parse = expr) == (char *) NULL) {
- return (0);
- }
- root = current = (struct parse_node *) NULL;
+ parse_node_t *new, *root = NULL, *current = NULL;
+ request_rec *r = ctx->intern->r;
+ const char* buffer;
+ const char *parse = expr;
+ int retval = 0, was_unmatched = 0;
+
+ *was_error = 0;
+
+ if (!parse) {
+ return 0;
+ }
/* Create Parse Tree */
while (1) {
- new = (struct parse_node *) apr_palloc(r->pool,
- sizeof(struct parse_node));
- new->parent = new->left = new->right = (struct parse_node *) NULL;
+ new = apr_palloc(ctx->dpool, sizeof(*new));
+ new->parent = new->left = new->right = NULL;
new->done = 0;
- if ((parse = get_ptoken(r, parse, &new->token, was_unmatched)) ==
- (char *) NULL) {
+
+ was_unmatched = get_ptoken(ctx->dpool, &parse, &new->token);
+ if (!parse) {
break;
}
- switch (new->token.type) {
- case token_string:
-#ifdef DEBUG_INCLUDE
- debug_pos += sprintf (&debug[debug_pos],
- " Token: string (%s)\n",
- new->token.value);
-#endif
- if (current == (struct parse_node *) NULL) {
+ DEBUG_DUMP_UNMATCHED(ctx, was_unmatched);
+ DEBUG_DUMP_TOKEN(ctx, &new->token);
+
+ switch (new->token.type) {
+ case TOKEN_STRING:
+ if (!current) {
root = current = new;
break;
}
+
switch (current->token.type) {
- case token_string:
- current->token.value = apr_pstrcat(r->pool,
- current->token.value,
- current->token.value[0] ? " " : "",
- new->token.value,
- NULL);
-
+ case TOKEN_STRING:
+ current->token.value =
+ apr_pstrcat(ctx->dpool, current->token.value,
+ *current->token.value ? " " : "",
+ new->token.value, NULL);
break;
- case token_eq:
- case token_ne:
- case token_and:
- case token_or:
- case token_lbrace:
- case token_not:
- case token_ge:
- case token_gt:
- case token_le:
- case token_lt:
+
+ case TOKEN_EQ:
+ case TOKEN_NE:
+ case TOKEN_AND:
+ case TOKEN_OR:
+ case TOKEN_LBRACE:
+ case TOKEN_NOT:
+ case TOKEN_GE:
+ case TOKEN_GT:
+ case TOKEN_LE:
+ case TOKEN_LT:
new->parent = current;
current = current->right = new;
break;
+
default:
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
- "Invalid expression \"%s\" in file %s",
- expr, r->filename);
+ "Invalid expression \"%s\" in file %s",
+ expr, r->filename);
*was_error = 1;
return retval;
}
break;
- case token_re:
-#ifdef DEBUG_INCLUDE
- debug_pos += sprintf (&debug[debug_pos],
- " Token: regex (%s)\n",
- new->token.value);
-#endif
- if (current == (struct parse_node *) NULL) {
+ case TOKEN_RE:
+ if (!current) {
root = current = new;
break;
}
+
switch (current->token.type) {
- case token_eq:
- case token_ne:
- case token_and:
- case token_or:
- case token_lbrace:
- case token_not:
+ case TOKEN_EQ:
+ case TOKEN_NE:
+ case TOKEN_AND:
+ case TOKEN_OR:
+ case TOKEN_LBRACE:
+ case TOKEN_NOT:
new->parent = current;
current = current->right = new;
break;
+
default:
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
- "Invalid expression \"%s\" in file %s",
- expr, r->filename);
+ "Invalid expression \"%s\" in file %s",
+ expr, r->filename);
*was_error = 1;
return retval;
}
break;
- case token_and:
- case token_or:
-#ifdef DEBUG_INCLUDE
- memcpy (&debug[debug_pos], " Token: and/or\n",
- sizeof (" Token: and/or\n"));
- debug_pos += sizeof (" Token: and/or\n");
-#endif
- if (current == (struct parse_node *) NULL) {
+ case TOKEN_AND:
+ case TOKEN_OR:
+ if (!current) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
- "Invalid expression \"%s\" in file %s",
- expr, r->filename);
+ "Invalid expression \"%s\" in file %s",
+ expr, r->filename);
*was_error = 1;
return retval;
}
/* Percolate upwards */
- while (current != (struct parse_node *) NULL) {
+ while (current) {
switch (current->token.type) {
- case token_string:
- case token_re:
- case token_group:
- case token_not:
- case token_eq:
- case token_ne:
- case token_and:
- case token_or:
- case token_ge:
- case token_gt:
- case token_le:
- case token_lt:
+ case TOKEN_STRING:
+ case TOKEN_RE:
+ case TOKEN_GROUP:
+ case TOKEN_NOT:
+ case TOKEN_EQ:
+ case TOKEN_NE:
+ case TOKEN_AND:
+ case TOKEN_OR:
+ case TOKEN_GE:
+ case TOKEN_GT:
+ case TOKEN_LE:
+ case TOKEN_LT:
current = current->parent;
continue;
- case token_lbrace:
+
+ case TOKEN_LBRACE:
break;
+
default:
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
- "Invalid expression \"%s\" in file %s",
- expr, r->filename);
+ "Invalid expression \"%s\" in file %s",
+ expr, r->filename);
*was_error = 1;
return retval;
}
break;
}
- if (current == (struct parse_node *) NULL) {
+
+ if (!current) {
new->left = root;
new->left->parent = new;
- new->parent = (struct parse_node *) NULL;
+ new->parent = NULL;
root = new;
}
else {
current = new;
break;
- case token_not:
-#ifdef DEBUG_INCLUDE
- memcpy(&debug[debug_pos], " Token: not\n",
- sizeof(" Token: not\n"));
- debug_pos += sizeof(" Token: not\n");
-#endif
- if (current == (struct parse_node *) NULL) {
+ case TOKEN_NOT:
+ if (!current) {
root = current = new;
break;
}
/* Percolate upwards */
- if (current != (struct parse_node *) NULL) {
+ if (current) {
switch (current->token.type) {
- case token_not:
- case token_eq:
- case token_ne:
- case token_and:
- case token_or:
- case token_lbrace:
- case token_ge:
- case token_gt:
- case token_le:
- case token_lt:
+ case TOKEN_NOT:
+ case TOKEN_EQ:
+ case TOKEN_NE:
+ case TOKEN_AND:
+ case TOKEN_OR:
+ case TOKEN_LBRACE:
+ case TOKEN_GE:
+ case TOKEN_GT:
+ case TOKEN_LE:
+ case TOKEN_LT:
break;
+
default:
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
"Invalid expression \"%s\" in file %s",
return retval;
}
}
- if (current == (struct parse_node *) NULL) {
+
+ if (!current) {
new->left = root;
new->left->parent = new;
- new->parent = (struct parse_node *) NULL;
+ new->parent = NULL;
root = new;
}
else {
current = new;
break;
- case token_eq:
- case token_ne:
- case token_ge:
- case token_gt:
- case token_le:
- case token_lt:
-#ifdef DEBUG_INCLUDE
- memcpy(&debug[debug_pos], " Token: eq/ne/ge/gt/le/lt\n",
- sizeof(" Token: eq/ne/ge/gt/le/lt\n"));
- debug_pos += sizeof(" Token: eq/ne/ge/gt/le/lt\n");
-#endif
- if (current == (struct parse_node *) NULL) {
+ case TOKEN_EQ:
+ case TOKEN_NE:
+ case TOKEN_GE:
+ case TOKEN_GT:
+ case TOKEN_LE:
+ case TOKEN_LT:
+ if (!current) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
"Invalid expression \"%s\" in file %s",
expr, r->filename);
return retval;
}
/* Percolate upwards */
- while (current != (struct parse_node *) NULL) {
+ while (current) {
switch (current->token.type) {
- case token_string:
- case token_re:
- case token_group:
+ case TOKEN_STRING:
+ case TOKEN_RE:
+ case TOKEN_GROUP:
current = current->parent;
continue;
- case token_lbrace:
- case token_and:
- case token_or:
+
+ case TOKEN_LBRACE:
+ case TOKEN_AND:
+ case TOKEN_OR:
break;
- case token_not:
- case token_eq:
- case token_ne:
- case token_ge:
- case token_gt:
- case token_le:
- case token_lt:
+
default:
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
- "Invalid expression \"%s\" in file %s",
- expr, r->filename);
+ "Invalid expression \"%s\" in file %s",
+ expr, r->filename);
*was_error = 1;
return retval;
}
break;
}
- if (current == (struct parse_node *) NULL) {
+
+ if (!current) {
new->left = root;
new->left->parent = new;
- new->parent = (struct parse_node *) NULL;
+ new->parent = NULL;
root = new;
}
else {
current = new;
break;
- case token_rbrace:
-#ifdef DEBUG_INCLUDE
- memcpy (&debug[debug_pos], " Token: rbrace\n",
- sizeof (" Token: rbrace\n"));
- debug_pos += sizeof (" Token: rbrace\n");
-#endif
- while (current != (struct parse_node *) NULL) {
- if (current->token.type == token_lbrace) {
- current->token.type = token_group;
+ case TOKEN_RBRACE:
+ while (current) {
+ if (current->token.type == TOKEN_LBRACE) {
+ TYPE_TOKEN(¤t->token, TOKEN_GROUP);
break;
}
current = current->parent;
}
- if (current == (struct parse_node *) NULL) {
+ if (!current) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
- "Unmatched ')' in \"%s\" in file %s",
- expr, r->filename);
+ "Unmatched ')' in \"%s\" in file %s",
+ expr, r->filename);
*was_error = 1;
return retval;
}
break;
- case token_lbrace:
-#ifdef DEBUG_INCLUDE
- memcpy (&debug[debug_pos], " Token: lbrace\n",
- sizeof (" Token: lbrace\n"));
- debug_pos += sizeof (" Token: lbrace\n");
-#endif
- if (current == (struct parse_node *) NULL) {
+ case TOKEN_LBRACE:
+ if (!current) {
root = current = new;
break;
}
/* Percolate upwards */
- if (current != (struct parse_node *) NULL) {
+ if (current) {
switch (current->token.type) {
- case token_not:
- case token_eq:
- case token_ne:
- case token_and:
- case token_or:
- case token_lbrace:
- case token_ge:
- case token_gt:
- case token_le:
- case token_lt:
+ case TOKEN_NOT:
+ case TOKEN_EQ:
+ case TOKEN_NE:
+ case TOKEN_AND:
+ case TOKEN_OR:
+ case TOKEN_LBRACE:
+ case TOKEN_GE:
+ case TOKEN_GT:
+ case TOKEN_LE:
+ case TOKEN_LT:
break;
- case token_string:
- case token_re:
- case token_group:
+
default:
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
- "Invalid expression \"%s\" in file %s",
- expr, r->filename);
+ "Invalid expression \"%s\" in file %s",
+ expr, r->filename);
*was_error = 1;
return retval;
}
}
- if (current == (struct parse_node *) NULL) {
+
+ if (!current) {
new->left = root;
new->left->parent = new;
- new->parent = (struct parse_node *) NULL;
+ new->parent = NULL;
root = new;
}
else {
}
current = new;
break;
+
default:
break;
}
/* Evaluate Parse Tree */
current = root;
- while (current != (struct parse_node *) NULL) {
+ while (current) {
switch (current->token.type) {
- case token_string:
-#ifdef DEBUG_INCLUDE
- memcpy (&debug[debug_pos], " Evaluate string\n",
- sizeof (" Evaluate string\n"));
- debug_pos += sizeof (" Evaluate string\n");
-#endif
- buffer = ap_ssi_parse_string(ctx, current->token.value, NULL,
- MAX_STRING_LEN, 0);
+ case TOKEN_STRING:
+ DEBUG_PRINTF((ctx, " Evaluate %s\n", current->token.s));
+
+ buffer = ap_ssi_parse_string(ctx, current->token.value, NULL, 0,
+ SSI_EXPAND_DROP_NAME);
+
current->token.value = buffer;
- current->value = (current->token.value[0] != '\0');
+ current->value = !!*current->token.value;
current->done = 1;
current = current->parent;
break;
- case token_re:
+ case TOKEN_RE:
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
"No operator before regex of expr \"%s\" in file %s",
expr, r->filename);
*was_error = 1;
return retval;
- case token_and:
- case token_or:
-#ifdef DEBUG_INCLUDE
- memcpy(&debug[debug_pos], " Evaluate and/or\n",
- sizeof(" Evaluate and/or\n"));
- debug_pos += sizeof(" Evaluate and/or\n");
-#endif
- if (current->left == (struct parse_node *) NULL ||
- current->right == (struct parse_node *) NULL) {
+ case TOKEN_AND:
+ case TOKEN_OR:
+ DEBUG_PRINTF((ctx, " Evaluate %s\n", current->token.s));
+
+ if (!current->left || !current->right) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
"Invalid expression \"%s\" in file %s",
expr, r->filename);
}
if (!current->left->done) {
switch (current->left->token.type) {
- case token_string:
- buffer = ap_ssi_parse_string(ctx, current->left->token.value,
- NULL, MAX_STRING_LEN, 0);
+ case TOKEN_STRING:
+ buffer = ap_ssi_parse_string(ctx,
+ current->left->token.value,
+ NULL, 0, SSI_EXPAND_DROP_NAME);
+
current->left->token.value = buffer;
- current->left->value =
- (current->left->token.value[0] != '\0');
+ current->left->value = !!*current->left->token.value;
current->left->done = 1;
break;
+
default:
current = current->left;
continue;
}
if (!current->right->done) {
switch (current->right->token.type) {
- case token_string:
- buffer = ap_ssi_parse_string(ctx, current->right->token.value,
- NULL, MAX_STRING_LEN, 0);
+ case TOKEN_STRING:
+ buffer = ap_ssi_parse_string(ctx,
+ current->right->token.value,
+ NULL, 0, SSI_EXPAND_DROP_NAME);
+
current->right->token.value = buffer;
- current->right->value =
- (current->right->token.value[0] != '\0');
+ current->right->value = !!*current->right->token.value;
current->right->done = 1;
break;
+
default:
current = current->right;
continue;
}
}
-#ifdef DEBUG_INCLUDE
- debug_pos += sprintf (&debug[debug_pos], " Left: %c\n",
- current->left->value ? '1' : '0');
- debug_pos += sprintf (&debug[debug_pos], " Right: %c\n",
- current->right->value ? '1' : '0');
-#endif
- if (current->token.type == token_and) {
+
+ DEBUG_PRINTF((ctx, " Left: %c\n", current->left->value
+ ? '1' : '0'));
+ DEBUG_PRINTF((ctx, " Right: %c\n", current->right->value
+ ? '1' : '0'));
+
+ if (current->token.type == TOKEN_AND) {
current->value = current->left->value && current->right->value;
}
else {
current->value = current->left->value || current->right->value;
}
-#ifdef DEBUG_INCLUDE
- debug_pos += sprintf (&debug[debug_pos], " Returning %c\n",
- current->value ? '1' : '0');
-#endif
+
+ DEBUG_PRINTF((ctx, " Returning %c\n", current->value
+ ? '1' : '0'));
+
current->done = 1;
current = current->parent;
break;
- case token_eq:
- case token_ne:
-#ifdef DEBUG_INCLUDE
- memcpy (&debug[debug_pos], " Evaluate eq/ne\n",
- sizeof (" Evaluate eq/ne\n"));
- debug_pos += sizeof (" Evaluate eq/ne\n");
-#endif
- if ((current->left == (struct parse_node *) NULL) ||
- (current->right == (struct parse_node *) NULL) ||
- (current->left->token.type != token_string) ||
- ((current->right->token.type != token_string) &&
- (current->right->token.type != token_re))) {
+ case TOKEN_EQ:
+ case TOKEN_NE:
+ DEBUG_PRINTF((ctx, " Evaluate %s\n", current->token.s));
+
+ if (!current->left || !current->right ||
+ current->left->token.type != TOKEN_STRING ||
+ (current->right->token.type != TOKEN_STRING &&
+ current->right->token.type != TOKEN_RE)) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
"Invalid expression \"%s\" in file %s",
expr, r->filename);
return retval;
}
buffer = ap_ssi_parse_string(ctx, current->left->token.value,
- NULL, MAX_STRING_LEN, 0);
+ NULL, 0, SSI_EXPAND_DROP_NAME);
+
current->left->token.value = buffer;
buffer = ap_ssi_parse_string(ctx, current->right->token.value,
- NULL, MAX_STRING_LEN, 0);
+ NULL, 0, SSI_EXPAND_DROP_NAME);
+
current->right->token.value = buffer;
- if (current->right->token.type == token_re) {
-#ifdef DEBUG_INCLUDE
- debug_pos += sprintf (&debug[debug_pos],
- " Re Compare (%s) with /%s/\n",
- current->left->token.value,
- current->right->token.value);
-#endif
- current->value =
- re_check(ctx, current->left->token.value,
- current->right->token.value);
+
+ if (current->right->token.type == TOKEN_RE) {
+ DEBUG_PRINTF((ctx, " Re Compare (%s) with /%s/\n",
+ current->left->token.value,
+ current->right->token.value));
+
+ current->value = re_check(ctx, current->left->token.value,
+ current->right->token.value);
}
else {
-#ifdef DEBUG_INCLUDE
- debug_pos += sprintf (&debug[debug_pos],
- " Compare (%s) with (%s)\n",
- current->left->token.value,
- current->right->token.value);
-#endif
- current->value =
- (strcmp(current->left->token.value,
- current->right->token.value) == 0);
+ DEBUG_PRINTF((ctx, " Compare (%s) with (%s)\n",
+ current->left->token.value,
+ current->right->token.value));
+
+ current->value = !strcmp(current->left->token.value,
+ current->right->token.value);
}
- if (current->token.type == token_ne) {
+
+ if (current->token.type == TOKEN_NE) {
current->value = !current->value;
}
-#ifdef DEBUG_INCLUDE
- debug_pos += sprintf (&debug[debug_pos], " Returning %c\n",
- current->value ? '1' : '0');
-#endif
+
+ DEBUG_PRINTF((ctx, " Returning %c\n", current->value
+ ? '1' : '0'));
+
current->done = 1;
current = current->parent;
break;
- case token_ge:
- case token_gt:
- case token_le:
- case token_lt:
-#ifdef DEBUG_INCLUDE
- memcpy (&debug[debug_pos], " Evaluate ge/gt/le/lt\n",
- sizeof (" Evaluate ge/gt/le/lt\n"));
- debug_pos += sizeof (" Evaluate ge/gt/le/lt\n");
-#endif
- if ((current->left == (struct parse_node *) NULL) ||
- (current->right == (struct parse_node *) NULL) ||
- (current->left->token.type != token_string) ||
- (current->right->token.type != token_string)) {
+
+ case TOKEN_GE:
+ case TOKEN_GT:
+ case TOKEN_LE:
+ case TOKEN_LT:
+ DEBUG_PRINTF((ctx, " Evaluate %s\n", current->token.s));
+
+ if (!current->left || !current->right ||
+ current->left->token.type != TOKEN_STRING ||
+ current->right->token.type != TOKEN_STRING) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
- "Invalid expression \"%s\" in file %s",
- expr, r->filename);
+ "Invalid expression \"%s\" in file %s",
+ expr, r->filename);
*was_error = 1;
return retval;
}
buffer = ap_ssi_parse_string(ctx, current->left->token.value, NULL,
- MAX_STRING_LEN, 0);
+ 0, SSI_EXPAND_DROP_NAME);
+
current->left->token.value = buffer;
buffer = ap_ssi_parse_string(ctx, current->right->token.value, NULL,
- MAX_STRING_LEN, 0);
+ 0, SSI_EXPAND_DROP_NAME);
current->right->token.value = buffer;
-#ifdef DEBUG_INCLUDE
- debug_pos += sprintf (&debug[debug_pos],
- " Compare (%s) with (%s)\n",
- current->left->token.value,
- current->right->token.value);
-#endif
- current->value =
- strcmp(current->left->token.value,
- current->right->token.value);
- if (current->token.type == token_ge) {
+
+ DEBUG_PRINTF((ctx, " Compare (%s) with (%s)\n",
+ current->left->token.value,
+ current->right->token.value));
+
+ current->value = strcmp(current->left->token.value,
+ current->right->token.value);
+
+ if (current->token.type == TOKEN_GE) {
current->value = current->value >= 0;
}
- else if (current->token.type == token_gt) {
+ else if (current->token.type == TOKEN_GT) {
current->value = current->value > 0;
}
- else if (current->token.type == token_le) {
+ else if (current->token.type == TOKEN_LE) {
current->value = current->value <= 0;
}
- else if (current->token.type == token_lt) {
+ else if (current->token.type == TOKEN_LT) {
current->value = current->value < 0;
}
else {
current->value = 0; /* Don't return -1 if unknown token */
}
-#ifdef DEBUG_INCLUDE
- debug_pos += sprintf (&debug[debug_pos], " Returning %c\n",
- current->value ? '1' : '0');
-#endif
+
+ DEBUG_PRINTF((ctx, " Returning %c\n", current->value
+ ? '1' : '0'));
+
current->done = 1;
current = current->parent;
break;
- case token_not:
- if (current->right != (struct parse_node *) NULL) {
+ case TOKEN_NOT:
+ if (current->right) {
if (!current->right->done) {
current = current->right;
continue;
else {
current->value = 0;
}
-#ifdef DEBUG_INCLUDE
- debug_pos += sprintf (&debug[debug_pos], " Evaluate !: %c\n",
- current->value ? '1' : '0');
-#endif
+
+ DEBUG_PRINTF((ctx, " Evaluate %s: %c\n", current->token.s,
+ current->value ? '1' : '0'));
+
current->done = 1;
current = current->parent;
break;
- case token_group:
- if (current->right != (struct parse_node *) NULL) {
+ case TOKEN_GROUP:
+ if (current->right) {
if (!current->right->done) {
current = current->right;
continue;
else {
current->value = 1;
}
-#ifdef DEBUG_INCLUDE
- debug_pos += sprintf (&debug[debug_pos], " Evaluate (): %c\n",
- current->value ? '1' : '0');
-#endif
+
+ DEBUG_PRINTF((ctx, " Evaluate %s: %c\n", current->token.s,
+ current->value ? '1' : '0'));
+
current->done = 1;
current = current->parent;
break;
- case token_lbrace:
+ case TOKEN_LBRACE:
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
- "Unmatched '(' in \"%s\" in file %s",
- expr, r->filename);
+ "Unmatched '(' in \"%s\" in file %s",
+ expr, r->filename);
*was_error = 1;
return retval;
- case token_rbrace:
+ case TOKEN_RBRACE:
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
- "Unmatched ')' in \"%s\" in file %s",
- expr, r->filename);
+ "Unmatched ')' in \"%s\" in file %s",
+ expr, r->filename);
*was_error = 1;
return retval;
default:
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
- "bad token type");
+ "bad token type (internal parser error)");
*was_error = 1;
return retval;
}
}
- retval = (root == (struct parse_node *) NULL) ? 0 : root->value;
- return (retval);
+ return (root ? root->value : 0);
}
{
char *tag = NULL;
char *expr = NULL;
- char debug_buf[MAX_DEBUG_SIZE];
request_rec *r = f->r;
- int expr_ret, was_error, was_unmatched;
+ int expr_ret, was_error;
if (ctx->argc != 1) {
ap_log_rerror(APLOG_MARK,
SSI_CREATE_ERROR_BUCKET(ctx, f, bb);
return APR_SUCCESS;
}
-#ifdef DEBUG_INCLUDE
- do {
- apr_size_t d_len = 0;
- d_len = sprintf(debug_buf, "**** if expr=\"%s\"\n", expr);
- APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_heap_create(debug_buf, d_len,
- NULL, f->c->bucket_alloc));
- } while (0);
-#endif
+ DEBUG_PRINTF((ctx, "**** if expr=\"%s\"\n", expr));
- expr_ret = parse_expr(r, ctx, expr, &was_error, &was_unmatched, debug_buf);
+ expr_ret = parse_expr(ctx, expr, &was_error);
if (was_error) {
SSI_CREATE_ERROR_BUCKET(ctx, f, bb);
return APR_SUCCESS;
}
- if (was_unmatched) {
- DUMP_PARSE_EXPR_DEBUG("\nUnmatched '\n", f, bb);
- }
- DUMP_PARSE_EXPR_DEBUG(debug_buf, f, bb);
-
if (expr_ret) {
ctx->flags |= (SSI_FLAG_PRINTING | SSI_FLAG_COND_TRUE);
}
ctx->flags &= SSI_FLAG_CLEAR_PRINT_COND;
}
- LOG_COND_STATUS(ctx, f, bb, " if");
+ DEBUG_DUMP_COND(ctx, " if");
+
ctx->if_nesting_level = 0;
return APR_SUCCESS;
char *tag = NULL;
char *expr = NULL;
request_rec *r = f->r;
- char debug_buf[MAX_DEBUG_SIZE];
- int expr_ret, was_error, was_unmatched;
+ int expr_ret, was_error;
if (ctx->argc != 1) {
ap_log_rerror(APLOG_MARK,
SSI_CREATE_ERROR_BUCKET(ctx, f, bb);
return APR_SUCCESS;
}
-#ifdef DEBUG_INCLUDE
- do {
- apr_size_t d_len = 0;
- d_len = sprintf(debug_buf, "**** elif expr=\"%s\"\n", expr);
- APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_heap_create(debug_buf, d_len,
- NULL, f->c->bucket_alloc));
- } while (0);
-#endif
- LOG_COND_STATUS(ctx, f, bb, " elif");
+ DEBUG_PRINTF((ctx, "**** elif expr=\"%s\"\n", expr));
+ DEBUG_DUMP_COND(ctx, " elif");
if (ctx->flags & SSI_FLAG_COND_TRUE) {
ctx->flags &= SSI_FLAG_CLEAR_PRINTING;
return APR_SUCCESS;
}
- expr_ret = parse_expr(r, ctx, expr, &was_error, &was_unmatched, debug_buf);
+ expr_ret = parse_expr(ctx, expr, &was_error);
if (was_error) {
SSI_CREATE_ERROR_BUCKET(ctx, f, bb);
return APR_SUCCESS;
}
- if (was_unmatched) {
- DUMP_PARSE_EXPR_DEBUG("\nUnmatched '\n", f, bb);
- }
- DUMP_PARSE_EXPR_DEBUG(debug_buf, f, bb);
-
if (expr_ret) {
ctx->flags |= (SSI_FLAG_PRINTING | SSI_FLAG_COND_TRUE);
}
ctx->flags &= SSI_FLAG_CLEAR_PRINT_COND;
}
- LOG_COND_STATUS(ctx, f, bb, " elif");
+ DEBUG_DUMP_COND(ctx, " elif");
return APR_SUCCESS;
}
return APR_SUCCESS;
}
- LOG_COND_STATUS(ctx, f, bb, " else");
+ DEBUG_DUMP_COND(ctx, " else");
if (ctx->flags & SSI_FLAG_COND_TRUE) {
ctx->flags &= SSI_FLAG_CLEAR_PRINTING;
return APR_SUCCESS;
}
- LOG_COND_STATUS(ctx, f, bb, "endif");
+ DEBUG_DUMP_COND(ctx, "endif");
+
ctx->flags |= (SSI_FLAG_PRINTING | SSI_FLAG_COND_TRUE);
return APR_SUCCESS;
intern->directive_len);
if (handle_func) {
+ DEBUG_INIT(ctx, f, pass_bb);
rv = handle_func(ctx, f, pass_bb);
if (!APR_STATUS_IS_SUCCESS(rv)) {
apr_brigade_destroy(pass_bb);