00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "config.h"
00035 #include <assert.h>
00036 #include <stdarg.h>
00037 #include "tuple_compiler.h"
00038
00039 #define MAX_STR (256)
00040 #define MIN_ALLOC_NODES (8)
00041 #define MIN_ALLOC_BUF (64)
00042
00043
00044 void tuple_error(TupleEvalContext *ctx, const gchar *fmt, ...)
00045 {
00046 va_list ap;
00047 g_free(ctx->errmsg);
00048 va_start(ap, fmt);
00049 ctx->errmsg = g_strdup_vprintf(fmt, ap);
00050 va_end(ap);
00051 ctx->iserror = TRUE;
00052 }
00053
00054
00055 static void tuple_evalctx_free_var(TupleEvalVar *var)
00056 {
00057 assert(var != NULL);
00058 var->fieldidx = -1;
00059 g_free(var->defvals);
00060 g_free(var->name);
00061 g_free(var);
00062 }
00063
00064
00065 static void tuple_evalctx_free_function(TupleEvalFunc *func)
00066 {
00067 assert(func != NULL);
00068
00069 g_free(func->name);
00070 g_free(func);
00071 }
00072
00073
00074
00075
00076 TupleEvalContext * tuple_evalctx_new(void)
00077 {
00078 return g_new0(TupleEvalContext, 1);
00079 }
00080
00081
00082
00083
00084 void tuple_evalctx_reset(TupleEvalContext *ctx)
00085 {
00086 gint i;
00087
00088 for (i = 0; i < ctx->nvariables; i++)
00089 if (ctx->variables[i]) {
00090 ctx->variables[i]->fieldref = NULL;
00091
00092 if (ctx->variables[i]->istemp)
00093 tuple_evalctx_free_var(ctx->variables[i]);
00094 }
00095
00096 ctx->iserror = FALSE;
00097 }
00098
00099
00100
00101
00102 void tuple_evalctx_free(TupleEvalContext *ctx)
00103 {
00104 gint i;
00105
00106 if (!ctx) return;
00107
00108
00109 for (i = 0; i < ctx->nvariables; i++)
00110 if (ctx->variables[i])
00111 tuple_evalctx_free_var(ctx->variables[i]);
00112
00113 g_free(ctx->variables);
00114
00115
00116 for (i = 0; i < ctx->nfunctions; i++)
00117 if (ctx->functions[i])
00118 tuple_evalctx_free_function(ctx->functions[i]);
00119
00120 g_free(ctx->functions);
00121 g_free(ctx);
00122 }
00123
00124
00125 gint tuple_evalctx_add_var(TupleEvalContext *ctx, const gchar *name, const gboolean istemp, const gint type, const TupleValueType ctype)
00126 {
00127 gint i, ref = -1;
00128 TupleEvalVar *tmp = g_new0(TupleEvalVar, 1);
00129 assert(tmp != NULL);
00130
00131 tmp->name = g_strdup(name);
00132 tmp->istemp = istemp;
00133 tmp->type = type;
00134 tmp->fieldidx = ref;
00135 tmp->ctype = ctype;
00136
00137
00138 switch (type) {
00139 case TUPLE_VAR_FIELD:
00140 for (i = 0; i < FIELD_LAST && ref < 0; i++)
00141 if (strcmp(tuple_fields[i].name, name) == 0) ref = i;
00142
00143 tmp->fieldidx = ref;
00144 break;
00145
00146 case TUPLE_VAR_CONST:
00147 if (ctype == TUPLE_INT)
00148 tmp->defvali = atoi(name);
00149 break;
00150 }
00151
00152
00153 for (i = 0; i < ctx->nvariables; i++)
00154 if (!ctx->variables[i]) {
00155 ctx->variables[i] = tmp;
00156 return i;
00157 }
00158
00159 i = ctx->nvariables;
00160 ctx->variables = g_renew(TupleEvalVar *, ctx->variables, ctx->nvariables + MIN_ALLOC_NODES);
00161 memset(&(ctx->variables[ctx->nvariables]), 0, MIN_ALLOC_NODES * sizeof(TupleEvalVar *));
00162 ctx->nvariables += MIN_ALLOC_NODES;
00163 ctx->variables[i] = tmp;
00164
00165 return i;
00166 }
00167
00168
00169 gint tuple_evalctx_add_function(TupleEvalContext *ctx, gchar *name)
00170 {
00171 assert(ctx != NULL);
00172 assert(name != NULL);
00173
00174 return -1;
00175 }
00176
00177
00178 static void tuple_evalnode_insert(TupleEvalNode **nodes, TupleEvalNode *node)
00179 {
00180 assert(nodes != NULL);
00181 assert(node != NULL);
00182
00183 if (*nodes) {
00184 node->prev = (*nodes)->prev;
00185 (*nodes)->prev->next = node;
00186 (*nodes)->prev = node;
00187 node->next = NULL;
00188 } else {
00189 *nodes = node;
00190 node->prev = node;
00191 node->next = NULL;
00192 }
00193 }
00194
00195
00196 static TupleEvalNode *tuple_evalnode_new(void)
00197 {
00198 return g_new0(TupleEvalNode, 1);
00199 }
00200
00201
00202 void tuple_evalnode_free(TupleEvalNode *expr)
00203 {
00204 TupleEvalNode *curr = expr, *next;
00205
00206 while (curr) {
00207 next = curr->next;
00208
00209 g_free(curr->text);
00210
00211 if (curr->children)
00212 tuple_evalnode_free(curr->children);
00213
00214 g_free(curr);
00215
00216 curr = next;
00217 }
00218 }
00219
00220
00221 static TupleEvalNode *tuple_compiler_pass1(gint *level, TupleEvalContext *ctx, gchar **expression);
00222
00223
00224 static gboolean tc_get_item(TupleEvalContext *ctx,
00225 gchar **str, gchar *buf, gssize max,
00226 gchar endch, gboolean *literal, gchar *errstr, gchar *item)
00227 {
00228 gssize i = 0;
00229 gchar *s = *str, tmpendch;
00230 assert(str != NULL);
00231 assert(buf != NULL);
00232
00233 if (*s == '"') {
00234 if (*literal == FALSE) {
00235 tuple_error(ctx, "Literal string value not allowed in '%s'.\n", item);
00236 return FALSE;
00237 }
00238 s++;
00239 *literal = TRUE;
00240 tmpendch = '"';
00241 } else {
00242 *literal = FALSE;
00243 tmpendch = endch;
00244 }
00245
00246 if (*literal == FALSE) {
00247 while (*s != '\0' && *s != tmpendch && (isalnum(*s) || *s == '-') && i < (max - 1)) {
00248 buf[i++] = *(s++);
00249 }
00250
00251 if (*s != tmpendch && *s != '}' && !isalnum(*s) && *s != '-') {
00252 tuple_error(ctx, "Invalid field '%s' in '%s'.\n", *str, item);
00253 return FALSE;
00254 } else if (*s != tmpendch) {
00255 tuple_error(ctx, "Expected '%c' in '%s'.\n", tmpendch, item);
00256 return FALSE;
00257 }
00258 } else {
00259 while (*s != '\0' && *s != tmpendch && i < (max - 1)) {
00260 if (*s == '\\') s++;
00261 buf[i++] = *(s++);
00262 }
00263 }
00264 buf[i] = '\0';
00265
00266 if (*literal) {
00267 if (*s == tmpendch)
00268 s++;
00269 else {
00270 tuple_error(ctx, "Expected literal string end ('%c') in '%s'.\n", tmpendch, item);
00271 return FALSE;
00272 }
00273 }
00274
00275 if (*s != endch) {
00276 tuple_error(ctx, "Expected '%c' after %s in '%s'\n", endch, errstr, item);
00277 return FALSE;
00278 } else {
00279 *str = s;
00280 return TRUE;
00281 }
00282 }
00283
00284
00285 static gint tc_get_variable(TupleEvalContext *ctx, gchar *name, gint type)
00286 {
00287 gint i;
00288 TupleValueType ctype = TUPLE_UNKNOWN;
00289
00290 if (name == '\0') return -1;
00291
00292 if (isdigit(name[0])) {
00293 ctype = TUPLE_INT;
00294 type = TUPLE_VAR_CONST;
00295 } else
00296 ctype = TUPLE_STRING;
00297
00298 if (type != TUPLE_VAR_CONST) {
00299 for (i = 0; i < ctx->nvariables; i++)
00300 if (ctx->variables[i] && !strcmp(ctx->variables[i]->name, name))
00301 return i;
00302 }
00303
00304 return tuple_evalctx_add_var(ctx, name, FALSE, type, ctype);
00305 }
00306
00307
00308 static gboolean tc_parse_construct(TupleEvalContext *ctx, TupleEvalNode **res, gchar *item, gchar **c, gint *level, gint opcode)
00309 {
00310 gchar tmps1[MAX_STR], tmps2[MAX_STR];
00311 gboolean literal1 = TRUE, literal2 = TRUE;
00312
00313 (*c)++;
00314 if (tc_get_item(ctx, c, tmps1, MAX_STR, ',', &literal1, "tag1", item)) {
00315 (*c)++;
00316 if (tc_get_item(ctx, c, tmps2, MAX_STR, ':', &literal2, "tag2", item)) {
00317 TupleEvalNode *tmp = tuple_evalnode_new();
00318 (*c)++;
00319
00320 tmp->opcode = opcode;
00321 if ((tmp->var[0] = tc_get_variable(ctx, tmps1, literal1 ? TUPLE_VAR_CONST : TUPLE_VAR_FIELD)) < 0) {
00322 tuple_evalnode_free(tmp);
00323 tuple_error(ctx, "Invalid variable '%s' in '%s'.\n", tmps1, item);
00324 return FALSE;
00325 }
00326 if ((tmp->var[1] = tc_get_variable(ctx, tmps2, literal2 ? TUPLE_VAR_CONST : TUPLE_VAR_FIELD)) < 0) {
00327 tuple_evalnode_free(tmp);
00328 tuple_error(ctx, "Invalid variable '%s' in '%s'.\n", tmps2, item);
00329 return FALSE;
00330 }
00331 tmp->children = tuple_compiler_pass1(level, ctx, c);
00332 tuple_evalnode_insert(res, tmp);
00333 } else
00334 return FALSE;
00335 } else
00336 return FALSE;
00337
00338 return TRUE;
00339 }
00340
00341
00342
00343
00344
00345
00346 static TupleEvalNode *tuple_compiler_pass1(gint *level, TupleEvalContext *ctx, gchar **expression)
00347 {
00348 TupleEvalNode *res = NULL, *tmp = NULL;
00349 gchar *c = *expression, *item, tmps1[MAX_STR];
00350 gboolean literal, end = FALSE;
00351 assert(ctx != NULL);
00352 assert(expression != NULL);
00353
00354 (*level)++;
00355
00356 while (*c != '\0' && !end) {
00357 tmp = NULL;
00358 if (*c == '}') {
00359 c++;
00360 (*level)--;
00361 end = TRUE;
00362 } else if (*c == '$') {
00363
00364 item = c++;
00365 if (*c == '{') {
00366 gint opcode;
00367 gchar *expr = ++c;
00368
00369 switch (*c) {
00370 case '?': c++;
00371
00372 literal = FALSE;
00373 if (tc_get_item(ctx, &c, tmps1, MAX_STR, ':', &literal, "tag", item)) {
00374 c++;
00375 tmp = tuple_evalnode_new();
00376 tmp->opcode = OP_EXISTS;
00377 if ((tmp->var[0] = tc_get_variable(ctx, tmps1, TUPLE_VAR_FIELD)) < 0) {
00378 tuple_error(ctx, "Invalid variable '%s' in '%s'.\n", tmps1, expr);
00379 goto ret_error;
00380 }
00381 tmp->children = tuple_compiler_pass1(level, ctx, &c);
00382 tuple_evalnode_insert(&res, tmp);
00383 } else
00384 goto ret_error;
00385 break;
00386
00387 case '=': c++;
00388 if (*c != '=') {
00389
00390 literal = FALSE;
00391 if (tc_get_item(ctx, &c, tmps1, MAX_STR, ',', &literal, "variable", item)) {
00392 c++;
00393 if (*c == '"') {
00394
00395 c++;
00396 } else if (isdigit(*c)) {
00397
00398 }
00399
00400 tuple_error(ctx, "Definitions are not yet supported!\n");
00401 goto ret_error;
00402 } else
00403 goto ret_error;
00404 } else {
00405
00406 if (!tc_parse_construct(ctx, &res, item, &c, level, OP_EQUALS))
00407 goto ret_error;
00408 }
00409 break;
00410
00411 case '!': c++;
00412 if (*c != '=') goto ext_expression;
00413 if (!tc_parse_construct(ctx, &res, item, &c, level, OP_NOT_EQUALS))
00414 goto ret_error;
00415 break;
00416
00417 case '<': c++;
00418 if (*c == '=') {
00419 opcode = OP_LTEQ;
00420 c++;
00421 } else
00422 opcode = OP_LT;
00423
00424 if (!tc_parse_construct(ctx, &res, item, &c, level, opcode))
00425 goto ret_error;
00426 break;
00427
00428 case '>': c++;
00429 if (*c == '=') {
00430 opcode = OP_GTEQ;
00431 c++;
00432 } else
00433 opcode = OP_GT;
00434
00435 if (!tc_parse_construct(ctx, &res, item, &c, level, opcode))
00436 goto ret_error;
00437 break;
00438
00439 case '(': c++;
00440 if (!strncmp(c, "empty)?", 7)) {
00441 c += 7;
00442 literal = FALSE;
00443 if (tc_get_item(ctx, &c, tmps1, MAX_STR, ':', &literal, "tag", item)) {
00444 c++;
00445 tmp = tuple_evalnode_new();
00446 tmp->opcode = OP_IS_EMPTY;
00447 if ((tmp->var[0] = tc_get_variable(ctx, tmps1, TUPLE_VAR_FIELD)) < 0) {
00448 tuple_error(ctx, "Invalid variable '%s' in '%s'.\n", tmps1, expr);
00449 goto ret_error;
00450 }
00451 tmp->children = tuple_compiler_pass1(level, ctx, &c);
00452 tuple_evalnode_insert(&res, tmp);
00453 } else
00454 goto ret_error;
00455 } else
00456 goto ext_expression;
00457 break;
00458
00459 default:
00460 ext_expression:
00461
00462 c = expr;
00463 literal = FALSE;
00464 if (tc_get_item(ctx, &c, tmps1, MAX_STR, '}', &literal, "field", item)) {
00465
00466
00467
00468 tmp = tuple_evalnode_new();
00469 tmp->opcode = OP_FIELD;
00470 if ((tmp->var[0] = tc_get_variable(ctx, tmps1, TUPLE_VAR_FIELD)) < 0) {
00471 tuple_error(ctx, "Invalid variable '%s' in '%s'.\n", tmps1, expr);
00472 goto ret_error;
00473 }
00474 tuple_evalnode_insert(&res, tmp);
00475 c++;
00476
00477 } else
00478 goto ret_error;
00479 }
00480 } else {
00481 tuple_error(ctx, "Expected '{', got '%c' in '%s'.\n", *c, c);
00482 goto ret_error;
00483 }
00484
00485 } else if (*c == '%') {
00486
00487 item = c++;
00488 if (*c == '{') {
00489 gssize i = 0;
00490 c++;
00491
00492 while (*c != '\0' && (isalnum(*c) || *c == '-') && *c != '}' && *c != ':' && i < (MAX_STR - 1))
00493 tmps1[i++] = *(c++);
00494 tmps1[i] = '\0';
00495
00496 if (*c == ':') {
00497 c++;
00498 } else if (*c == '}') {
00499 c++;
00500 } else if (*c == '\0') {
00501 tuple_error(ctx, "Expected '}' or function arguments in '%s'\n", item);
00502 goto ret_error;
00503 }
00504 } else {
00505 tuple_error(ctx, "Expected '{', got '%c' in '%s'.\n", *c, c);
00506 goto ret_error;
00507 }
00508 } else {
00509
00510 gssize i = 0;
00511 while (*c != '\0' && *c != '$' && *c != '%' && *c != '}' && i < (MAX_STR - 1)) {
00512 if (*c == '\\') c++;
00513 tmps1[i++] = *(c++);
00514 }
00515 tmps1[i] = '\0';
00516
00517 tmp = tuple_evalnode_new();
00518 tmp->opcode = OP_RAW;
00519 tmp->text = g_strdup(tmps1);
00520 tuple_evalnode_insert(&res, tmp);
00521 }
00522 }
00523
00524 if (*level <= 0) {
00525 tuple_error(ctx, "Syntax error! Uneven/unmatched nesting of elements in '%s'!\n", c);
00526 goto ret_error;
00527 }
00528
00529 *expression = c;
00530 return res;
00531
00532 ret_error:
00533 tuple_evalnode_free(tmp);
00534 tuple_evalnode_free(res);
00535 return NULL;
00536 }
00537
00538
00539 static TupleEvalNode *tuple_compiler_pass2(gboolean *changed, TupleEvalContext *ctx, TupleEvalNode *expr)
00540 {
00541
00542 TupleEvalNode *res = NULL;
00543 assert(ctx != NULL);
00544
00545 return res;
00546 }
00547
00548
00549 TupleEvalNode *tuple_formatter_compile(TupleEvalContext *ctx, gchar *expr)
00550 {
00551 gint level = 0;
00552 gboolean changed = FALSE;
00553 gchar *tmpexpr = expr;
00554 TupleEvalNode *res1, *res2;
00555
00556 res1 = tuple_compiler_pass1(&level, ctx, &tmpexpr);
00557
00558 if (level != 1) {
00559 tuple_error(ctx, "Syntax error! Uneven/unmatched nesting of elements! (%d)\n", level);
00560 tuple_evalnode_free(res1);
00561 return NULL;
00562 }
00563
00564 res2 = tuple_compiler_pass2(&changed, ctx, res1);
00565
00566 if (changed) {
00567 tuple_evalnode_free(res1);
00568 return res2;
00569 } else {
00570 tuple_evalnode_free(res2);
00571 return res1;
00572 }
00573 }
00574
00575
00576
00577
00578
00579 static TupleValue * tf_get_fieldref (TupleEvalVar * var, const Tuple * tuple)
00580 {
00581 if (var->type == TUPLE_VAR_FIELD && var->fieldref == NULL) {
00582 if (var->fieldidx < 0)
00583 var->fieldref = mowgli_dictionary_retrieve(tuple->dict, var->name);
00584 else
00585 var->fieldref = tuple->values[var->fieldidx];
00586 }
00587
00588 return var->fieldref;
00589 }
00590
00591
00592
00593
00594
00595 static TupleValueType tf_get_var (gchar * * tmps, gint * tmpi, TupleEvalVar *
00596 var, const Tuple * tuple)
00597 {
00598 TupleValueType type = TUPLE_UNKNOWN;
00599 *tmps = NULL;
00600 *tmpi = 0;
00601
00602 switch (var->type) {
00603 case TUPLE_VAR_DEF:
00604 switch (var->ctype) {
00605 case TUPLE_STRING: *tmps = var->defvals; break;
00606 case TUPLE_INT: *tmpi = var->defvali; break;
00607 default: break;
00608 }
00609 type = var->ctype;
00610 break;
00611
00612 case TUPLE_VAR_CONST:
00613 switch (var->ctype) {
00614 case TUPLE_STRING: *tmps = var->name; break;
00615 case TUPLE_INT: *tmpi = var->defvali; break;
00616 default: break;
00617 }
00618 type = var->ctype;
00619 break;
00620
00621 case TUPLE_VAR_FIELD:
00622 if (tf_get_fieldref(var, tuple)) {
00623 if (var->fieldref->type == TUPLE_STRING)
00624 *tmps = var->fieldref->value.string;
00625 else
00626 *tmpi = var->fieldref->value.integer;
00627 type = var->fieldref->type;
00628 }
00629 break;
00630 }
00631
00632 return type;
00633 }
00634
00635
00636
00637
00638
00639 static gboolean tuple_formatter_eval_do (TupleEvalContext * ctx, TupleEvalNode *
00640 expr, const Tuple * tuple, gchar * * res, gssize * resmax, gssize * reslen)
00641 {
00642 TupleEvalNode *curr = expr;
00643 TupleEvalVar *var0, *var1;
00644 TupleValueType type0, type1;
00645 gint tmpi0, tmpi1;
00646 gchar tmps[MAX_STR], *tmps0, *tmps1, *tmps2;
00647 gboolean result;
00648 gint resulti;
00649
00650 if (!expr) return FALSE;
00651
00652 while (curr) {
00653 const gchar *str = NULL;
00654
00655 switch (curr->opcode) {
00656 case OP_RAW:
00657 str = curr->text;
00658 break;
00659
00660 case OP_FIELD:
00661 var0 = ctx->variables[curr->var[0]];
00662
00663 switch (var0->type) {
00664 case TUPLE_VAR_DEF:
00665 switch (var0->ctype) {
00666 case TUPLE_STRING:
00667 str = var0->defvals;
00668 break;
00669
00670 case TUPLE_INT:
00671 g_snprintf(tmps, sizeof(tmps), "%d", var0->defvali);
00672 str = tmps;
00673 break;
00674
00675 default:
00676 break;
00677 }
00678 break;
00679
00680 case TUPLE_VAR_FIELD:
00681 if (tf_get_fieldref(var0, tuple)) {
00682 switch (var0->fieldref->type) {
00683 case TUPLE_STRING:
00684 str = var0->fieldref->value.string;
00685 break;
00686
00687 case TUPLE_INT:
00688 g_snprintf(tmps, sizeof(tmps), "%d", var0->fieldref->value.integer);
00689 str = tmps;
00690 break;
00691
00692 default:
00693 str = NULL;
00694 }
00695 }
00696 break;
00697 }
00698 break;
00699
00700 case OP_EQUALS:
00701 case OP_NOT_EQUALS:
00702 case OP_LT: case OP_LTEQ:
00703 case OP_GT: case OP_GTEQ:
00704 var0 = ctx->variables[curr->var[0]];
00705 var1 = ctx->variables[curr->var[1]];
00706
00707 type0 = tf_get_var(&tmps0, &tmpi0, var0, tuple);
00708 type1 = tf_get_var(&tmps1, &tmpi1, var1, tuple);
00709 result = FALSE;
00710
00711 if (type0 != TUPLE_UNKNOWN && type1 != TUPLE_UNKNOWN) {
00712 if (type0 == type1) {
00713 if (type0 == TUPLE_STRING)
00714 resulti = strcmp(tmps0, tmps1);
00715 else
00716 resulti = tmpi0 - tmpi1;
00717 } else {
00718 if (type0 == TUPLE_INT)
00719 resulti = tmpi0 - atoi(tmps1);
00720 else
00721 resulti = atoi(tmps0) - tmpi1;
00722 }
00723
00724 switch (curr->opcode) {
00725 case OP_EQUALS: result = (resulti == 0); break;
00726 case OP_NOT_EQUALS: result = (resulti != 0); break;
00727 case OP_LT: result = (resulti < 0); break;
00728 case OP_LTEQ: result = (resulti <= 0); break;
00729 case OP_GT: result = (resulti > 0); break;
00730 case OP_GTEQ: result = (resulti >= 0); break;
00731 default: result = FALSE;
00732 }
00733 }
00734
00735 if (result && !tuple_formatter_eval_do(ctx, curr->children, tuple, res, resmax, reslen))
00736 return FALSE;
00737 break;
00738
00739 case OP_EXISTS:
00740 #ifdef NO_EXISTS_HACK
00741 if (tf_get_fieldref(ctx->variables[curr->var[0]], tuple)) {
00742 if (!tuple_formatter_eval_do(ctx, curr->children, tuple, res, resmax, reslen))
00743 return FALSE;
00744 }
00745 break;
00746 #endif
00747
00748 case OP_IS_EMPTY:
00749 var0 = ctx->variables[curr->var[0]];
00750
00751 if (tf_get_fieldref(var0, tuple)) {
00752
00753 switch (var0->fieldref->type) {
00754 case TUPLE_INT:
00755 result = (var0->fieldref->value.integer == 0);
00756 break;
00757
00758 case TUPLE_STRING:
00759 result = TRUE;
00760 tmps2 = var0->fieldref->value.string;
00761
00762 while (result && tmps2 && *tmps2 != '\0') {
00763 gunichar uc = g_utf8_get_char(tmps2);
00764 if (g_unichar_isspace(uc))
00765 tmps2 = g_utf8_next_char(tmps2);
00766 else
00767 result = FALSE;
00768 }
00769 break;
00770
00771 default:
00772 result = TRUE;
00773 }
00774 } else
00775 result = TRUE;
00776
00777 #ifdef NO_EXISTS_HACK
00778 if (result && !tuple_formatter_eval_do(ctx, curr->children, tuple, res, resmax, reslen))
00779 return FALSE;
00780 #else
00781 if ((curr->opcode == OP_EXISTS && !result) || (curr->opcode == OP_IS_EMPTY && result)) {
00782 if (!tuple_formatter_eval_do(ctx, curr->children, tuple, res, resmax, reslen))
00783 return FALSE;
00784 }
00785 #endif
00786 break;
00787
00788 default:
00789 tuple_error(ctx, "Unimplemented opcode %d!\n", curr->opcode);
00790 return FALSE;
00791 break;
00792 }
00793
00794 if (str) {
00795
00796 *reslen += strlen(str);
00797 if (*res) {
00798 if (*reslen >= *resmax) {
00799 *resmax += *reslen + MIN_ALLOC_BUF;
00800 *res = g_realloc(*res, *resmax);
00801 }
00802
00803 strcat(*res, str);
00804 } else {
00805 *resmax = *reslen + MIN_ALLOC_BUF;
00806 *res = g_malloc(*resmax);
00807
00808 g_strlcpy(*res, str, *resmax);
00809 }
00810 }
00811
00812 curr = curr->next;
00813 }
00814
00815 return TRUE;
00816 }
00817
00818
00819 gchar * tuple_formatter_eval (TupleEvalContext * ctx, TupleEvalNode * expr,
00820 const Tuple * tuple)
00821 {
00822 gchar *res = g_strdup("");
00823 gssize resmax = 0, reslen = 0;
00824 assert(ctx != NULL);
00825 assert(tuple != NULL);
00826
00827 if (!expr) return res;
00828
00829 tuple_formatter_eval_do(ctx, expr, tuple, &res, &resmax, &reslen);
00830
00831 return res;
00832 }
00833
00834
00835 static void print_vars(FILE *f, TupleEvalContext *ctx, TupleEvalNode *node, gint start, gint end)
00836 {
00837 gint i;
00838
00839 for (i = start; i <= end; i++) {
00840 TupleEvalVar *v = NULL;
00841 gchar *s = NULL;
00842 gint n = node->var[i];
00843
00844 if (n >= 0) {
00845 v = ctx->variables[n];
00846 if (v) {
00847 s = v->name;
00848
00849 if (v->type == TUPLE_VAR_CONST)
00850 fprintf(f, "(const)");
00851 else if (v->type == TUPLE_VAR_DEF)
00852 fprintf(f, "(def)");
00853 }
00854 }
00855
00856 fprintf(f, "var[%d]=(%d),\"%s\" ", i, n, s);
00857 }
00858 }
00859
00860
00861 gint tuple_formatter_print(FILE *f, gint *level, TupleEvalContext *ctx, TupleEvalNode *expr)
00862 {
00863 TupleEvalNode *curr = expr;
00864
00865 if (!expr) return -1;
00866
00867 (*level)++;
00868
00869 while (curr) {
00870 gint i;
00871 for (i = 0; i < *level; i++)
00872 fprintf(f, " ");
00873
00874 switch (curr->opcode) {
00875 case OP_RAW:
00876 fprintf(f, "OP_RAW text=\"%s\"\n", curr->text);
00877 break;
00878
00879 case OP_FIELD:
00880 fprintf(f, "OP_FIELD ");
00881 print_vars(f, ctx, curr, 0, 0);
00882 fprintf(f, "\n");
00883 break;
00884
00885 case OP_EXISTS:
00886 fprintf(f, "OP_EXISTS ");
00887 print_vars(f, ctx, curr, 0, 0);
00888 fprintf(f, "\n");
00889 tuple_formatter_print(f, level, ctx, curr->children);
00890 break;
00891
00892 case OP_DEF_STRING:
00893 fprintf(f, "OP_DEF_STRING ");
00894 fprintf(f, "\n");
00895 break;
00896
00897 case OP_DEF_INT:
00898 fprintf(f, "OP_DEF_INT ");
00899 fprintf(f, "\n");
00900 break;
00901
00902 case OP_EQUALS:
00903 fprintf(f, "OP_EQUALS ");
00904 print_vars(f, ctx, curr, 0, 1);
00905 fprintf(f, "\n");
00906 tuple_formatter_print(f, level, ctx, curr->children);
00907 break;
00908
00909 case OP_NOT_EQUALS:
00910 fprintf(f, "OP_NOT_EQUALS ");
00911 print_vars(f, ctx, curr, 0, 1);
00912 fprintf(f, "\n");
00913 tuple_formatter_print(f, level, ctx, curr->children);
00914 break;
00915
00916 case OP_IS_EMPTY:
00917 fprintf(f, "OP_IS_EMPTY ");
00918 print_vars(f, ctx, curr, 0, 0);
00919 fprintf(f, "\n");
00920 tuple_formatter_print(f, level, ctx, curr->children);
00921 break;
00922
00923 default:
00924 fprintf(f, "Unimplemented opcode %d!\n", curr->opcode);
00925 break;
00926 }
00927
00928 curr = curr->next;
00929 }
00930
00931 (*level)--;
00932
00933 return 0;
00934 }