comparison src/audacious/tuple_compiler.c @ 3954:7afbcd87cd65

The compiler should now correctly recognize integer constants, thanks to Yuri K. Schlesner for spotting this really stupid bug .. which I should've seen much earlier.
author Matti Hamalainen <ccr@tnsp.org>
date Fri, 16 Nov 2007 09:14:40 +0200
parents 047bf3ed21b2
children c4295265f61d
comparison
equal deleted inserted replaced
3953:de76dbec8e1e 3954:7afbcd87cd65
54 54
55 static void tuple_evalctx_free_var(TupleEvalVar *var) 55 static void tuple_evalctx_free_var(TupleEvalVar *var)
56 { 56 {
57 assert(var != NULL); 57 assert(var != NULL);
58 var->fieldidx = -1; 58 var->fieldidx = -1;
59 g_free(var->defval); 59 g_free(var->defvals);
60 g_free(var->name); 60 g_free(var->name);
61 g_free(var); 61 g_free(var);
62 } 62 }
63 63
64 64
122 /* Zero context */ 122 /* Zero context */
123 memset(ctx, 0, sizeof(TupleEvalContext)); 123 memset(ctx, 0, sizeof(TupleEvalContext));
124 } 124 }
125 125
126 126
127 gint tuple_evalctx_add_var(TupleEvalContext *ctx, const gchar *name, const gboolean istemp, const gint type) 127 gint tuple_evalctx_add_var(TupleEvalContext *ctx, const gchar *name, const gboolean istemp, const gint type, const TupleValueType ctype)
128 { 128 {
129 gint i, ref = -1; 129 gint i, ref = -1;
130 TupleEvalVar *tmp = g_new0(TupleEvalVar, 1); 130 TupleEvalVar *tmp = g_new0(TupleEvalVar, 1);
131 assert(tmp != NULL); 131 assert(tmp != NULL);
132 132
133 tmp->name = g_strdup(name); 133 tmp->name = g_strdup(name);
134 tmp->istemp = istemp; 134 tmp->istemp = istemp;
135 tmp->type = type; 135 tmp->type = type;
136 tmp->fieldidx = ref; 136 tmp->fieldidx = ref;
137 tmp->ctype = ctype;
137 138
138 /* Find fieldidx, if any */ 139 /* Find fieldidx, if any */
139 if (type == VAR_FIELD) { 140 switch (type) {
140 for (i = 0; i < FIELD_LAST && ref < 0; i++) 141 case VAR_FIELD:
141 if (strcmp(tuple_fields[i].name, name) == 0) ref = i; 142 for (i = 0; i < FIELD_LAST && ref < 0; i++)
142 143 if (strcmp(tuple_fields[i].name, name) == 0) ref = i;
143 tmp->fieldidx = ref; 144
145 tmp->fieldidx = ref;
146 break;
147
148 case VAR_CONST:
149 if (ctype == TUPLE_INT)
150 tmp->defvali = atoi(name);
151 break;
144 } 152 }
145 153
146 /* Find a free slot */ 154 /* Find a free slot */
147 for (i = 0; i < ctx->nvariables; i++) 155 for (i = 0; i < ctx->nvariables; i++)
148 if (!ctx->variables[i]) { 156 if (!ctx->variables[i]) {
277 285
278 286
279 static gint tc_get_variable(TupleEvalContext *ctx, gchar *name, gint type) 287 static gint tc_get_variable(TupleEvalContext *ctx, gchar *name, gint type)
280 { 288 {
281 gint i; 289 gint i;
282 290 TupleValueType ctype = TUPLE_UNKNOWN;
283 if (*name == '\0') return -1; 291
284 292 if (name == '\0') return -1;
285 for (i = 0; i < ctx->nvariables; i++) 293
286 if (ctx->variables[i] && !strcmp(ctx->variables[i]->name, name)) 294 if (isdigit(name[0])) {
287 return i; 295 ctype = TUPLE_INT;
288 296 type = VAR_CONST;
289 return tuple_evalctx_add_var(ctx, name, FALSE, type); 297 } else
290 } 298 ctype = TUPLE_STRING;
291 299
292 300 if (type != VAR_CONST) {
293 static gboolean tc_parse_construct1(TupleEvalContext *ctx, TupleEvalNode **res, gchar *item, gchar **c, gint *level, gint opcode) 301 for (i = 0; i < ctx->nvariables; i++)
302 if (ctx->variables[i] && !strcmp(ctx->variables[i]->name, name))
303 return i;
304 }
305
306 return tuple_evalctx_add_var(ctx, name, FALSE, type, ctype);
307 }
308
309
310 static gboolean tc_parse_construct(TupleEvalContext *ctx, TupleEvalNode **res, gchar *item, gchar **c, gint *level, gint opcode)
294 { 311 {
295 gchar tmps1[MAX_STR], tmps2[MAX_STR]; 312 gchar tmps1[MAX_STR], tmps2[MAX_STR];
296 gboolean literal1 = TRUE, literal2 = TRUE; 313 gboolean literal1 = TRUE, literal2 = TRUE;
297 314
298 (*c)++; 315 (*c)++;
386 goto ret_error; 403 goto ret_error;
387 } else 404 } else
388 goto ret_error; 405 goto ret_error;
389 } else { 406 } else {
390 /* Equals? */ 407 /* Equals? */
391 if (!tc_parse_construct1(ctx, &res, item, &c, level, OP_EQUALS)) 408 if (!tc_parse_construct(ctx, &res, item, &c, level, OP_EQUALS))
392 goto ret_error; 409 goto ret_error;
393 } 410 }
394 break; 411 break;
395 412
396 case '!': c++; 413 case '!': c++;
397 if (*c != '=') goto ext_expression; 414 if (*c != '=') goto ext_expression;
398 if (!tc_parse_construct1(ctx, &res, item, &c, level, OP_NOT_EQUALS)) 415 if (!tc_parse_construct(ctx, &res, item, &c, level, OP_NOT_EQUALS))
399 goto ret_error; 416 goto ret_error;
400 break; 417 break;
401 418
402 case '<': c++; 419 case '<': c++;
403 if (*c == '=') { 420 if (*c == '=') {
404 opcode = OP_LTEQ; 421 opcode = OP_LTEQ;
405 c++; 422 c++;
406 } else 423 } else
407 opcode = OP_LT; 424 opcode = OP_LT;
408 425
409 if (!tc_parse_construct1(ctx, &res, item, &c, level, opcode)) 426 if (!tc_parse_construct(ctx, &res, item, &c, level, opcode))
410 goto ret_error; 427 goto ret_error;
411 break; 428 break;
412 429
413 case '>': c++; 430 case '>': c++;
414 if (*c == '=') { 431 if (*c == '=') {
415 opcode = OP_GTEQ; 432 opcode = OP_GTEQ;
416 c++; 433 c++;
417 } else 434 } else
418 opcode = OP_GT; 435 opcode = OP_GT;
419 436
420 if (!tc_parse_construct1(ctx, &res, item, &c, level, opcode)) 437 if (!tc_parse_construct(ctx, &res, item, &c, level, opcode))
421 goto ret_error; 438 goto ret_error;
422 break; 439 break;
423 440
424 case '(': c++; 441 case '(': c++;
425 if (!strncmp(c, "empty)?", 7)) { 442 if (!strncmp(c, "empty)?", 7)) {
578 * Return VAR_* type for the variable. 595 * Return VAR_* type for the variable.
579 */ 596 */
580 static TupleValueType tf_get_var(gchar **tmps, gint *tmpi, TupleEvalVar *var, Tuple *tuple) 597 static TupleValueType tf_get_var(gchar **tmps, gint *tmpi, TupleEvalVar *var, Tuple *tuple)
581 { 598 {
582 TupleValueType type = TUPLE_UNKNOWN; 599 TupleValueType type = TUPLE_UNKNOWN;
600 *tmps = NULL;
601 *tmpi = 0;
583 602
584 switch (var->type) { 603 switch (var->type) {
585 case VAR_DEF: *tmps = var->defval; type = TUPLE_STRING; break; 604 case VAR_DEF:
586 case VAR_CONST: *tmps = var->name; type = TUPLE_STRING; break; 605 switch (var->ctype) {
606 case TUPLE_STRING: *tmps = var->defvals; break;
607 case TUPLE_INT: *tmpi = var->defvali; break;
608 default: /* Possible, but should be prevented elsewhere */ break;
609 }
610 type = var->ctype;
611 break;
612
613 case VAR_CONST:
614 switch (var->ctype) {
615 case TUPLE_STRING: *tmps = var->name; break;
616 case TUPLE_INT: *tmpi = var->defvali; break;
617 default: /* Cannot happen */ break;
618 }
619 type = var->ctype;
620 break;
621
587 case VAR_FIELD: 622 case VAR_FIELD:
588 if (tf_get_fieldref(var, tuple)) { 623 if (tf_get_fieldref(var, tuple)) {
589 if (var->fieldref->type == TUPLE_STRING) 624 if (var->fieldref->type == TUPLE_STRING)
590 *tmps = var->fieldref->value.string; 625 *tmps = var->fieldref->value.string;
591 else 626 else
592 *tmpi = var->fieldref->value.integer; 627 *tmpi = var->fieldref->value.integer;
593 type = var->fieldref->type; 628 type = var->fieldref->type;
594 } 629 }
595 break; 630 break;
596 default:
597 tmps = NULL;
598 tmpi = 0;
599 } 631 }
600 632
601 return type; 633 return type;
602 } 634 }
603 635
628 case OP_FIELD: 660 case OP_FIELD:
629 var0 = ctx->variables[curr->var[0]]; 661 var0 = ctx->variables[curr->var[0]];
630 662
631 switch (var0->type) { 663 switch (var0->type) {
632 case VAR_DEF: 664 case VAR_DEF:
633 str = var0->defval; 665 switch (var0->ctype) {
666 case TUPLE_STRING:
667 str = var0->defvals;
668 break;
669
670 case TUPLE_INT:
671 g_snprintf(tmps, sizeof(tmps), "%d", var0->defvali);
672 str = tmps;
673 break;
674
675 default:
676 break;
677 }
634 break; 678 break;
635 679
636 case VAR_FIELD: 680 case VAR_FIELD:
637 if (tf_get_fieldref(var0, tuple)) { 681 if (tf_get_fieldref(var0, tuple)) {
638 switch (var0->fieldref->type) { 682 switch (var0->fieldref->type) {
660 var0 = ctx->variables[curr->var[0]]; 704 var0 = ctx->variables[curr->var[0]];
661 var1 = ctx->variables[curr->var[1]]; 705 var1 = ctx->variables[curr->var[1]];
662 706
663 type0 = tf_get_var(&tmps0, &tmpi0, var0, tuple); 707 type0 = tf_get_var(&tmps0, &tmpi0, var0, tuple);
664 type1 = tf_get_var(&tmps1, &tmpi1, var1, tuple); 708 type1 = tf_get_var(&tmps1, &tmpi1, var1, tuple);
665 709 result = FALSE;
666 if (type0 == type1) { 710
667 if (type0 == TUPLE_STRING) 711 if (type0 != TUPLE_UNKNOWN && type1 != TUPLE_UNKNOWN) {
668 resulti = strcmp(tmps0, tmps1); 712 if (type0 == type1) {
669 else 713 if (type0 == TUPLE_STRING)
670 resulti = tmpi0 - tmpi1; 714 resulti = strcmp(tmps0, tmps1);
671 715 else
716 resulti = tmpi0 - tmpi1;
717 } else {
718 if (type0 == TUPLE_INT)
719 resulti = tmpi0 - atoi(tmps1);
720 else
721 resulti = atoi(tmps0) - tmpi1;
722 }
723
672 switch (curr->opcode) { 724 switch (curr->opcode) {
673 case OP_EQUALS: result = (resulti == 0); break; 725 case OP_EQUALS: result = (resulti == 0); break;
674 case OP_NOT_EQUALS: result = (resulti != 0); break; 726 case OP_NOT_EQUALS: result = (resulti != 0); break;
675 case OP_LT: result = (resulti < 0); break; 727 case OP_LT: result = (resulti < 0); break;
676 case OP_LTEQ: result = (resulti <= 0); break; 728 case OP_LTEQ: result = (resulti <= 0); break;
677 case OP_GT: result = (resulti > 0); break; 729 case OP_GT: result = (resulti > 0); break;
678 case OP_GTEQ: result = (resulti >= 0); break; 730 case OP_GTEQ: result = (resulti >= 0); break;
679 default: result = FALSE; 731 default: result = FALSE;
680 } 732 }
733 }
681 734
682 if (result && !tuple_formatter_eval_do(ctx, curr->children, tuple, res, resmax, reslen)) 735 if (result && !tuple_formatter_eval_do(ctx, curr->children, tuple, res, resmax, reslen))
683 return FALSE; 736 return FALSE;
684 } else {
685 /* FIXME?! Warn that types are not same? */
686 }
687 break; 737 break;
688 738
689 case OP_EXISTS: 739 case OP_EXISTS:
690 #ifdef NO_EXISTS_HACK 740 #ifdef NO_EXISTS_HACK
691 if (tf_get_fieldref(ctx->variables[curr->var[0]], tuple)) { 741 if (tf_get_fieldref(ctx->variables[curr->var[0]], tuple)) {