~ubuntu-branches/ubuntu/wily/weechat/wily

« back to all changes in this revision

Viewing changes to src/core/wee-eval.c

  • Committer: Package Import Robot
  • Author(s): Emmanuel Bouthenot
  • Date: 2014-09-28 17:41:10 UTC
  • mfrom: (29.1.7 sid)
  • Revision ID: package-import@ubuntu.com-20140928174110-bwlsn7gqmqfftnmb
Tags: 1.0.1-1
New upstream release

Show diffs side-by-side

added added

removed removed

Lines of Context:
41
41
#include "../plugins/plugin.h"
42
42
 
43
43
 
44
 
char *logical_ops[EVAL_NUM_LOGICAL_OPS] = { "||", "&&" };
45
 
char *comparisons[EVAL_NUM_COMPARISONS] = { "==", "!=", "<=", "<", ">=", ">",
46
 
                                            "=~", "!~" };
 
44
char *logical_ops[EVAL_NUM_LOGICAL_OPS] =
 
45
{ "||", "&&" };
 
46
 
 
47
char *comparisons[EVAL_NUM_COMPARISONS] =
 
48
{ "=~", "!~", "==", "!=", "<=", "<", ">=", ">" };
47
49
 
48
50
struct t_hashtable *eval_hashtable_pointers = NULL;
49
51
 
252
254
            return strdup (ptr_value);
253
255
    }
254
256
 
255
 
    /* 2. look for a color */
 
257
    /* 2. convert escaped chars */
 
258
    if (strncmp (text, "esc:", 4) == 0)
 
259
        return string_convert_escaped_chars (text + 4);
 
260
    if ((text[0] == '\\') && text[1] && (text[1] != '\\'))
 
261
        return string_convert_escaped_chars (text);
 
262
 
 
263
    /* 3. look for a color */
256
264
    if (strncmp (text, "color:", 6) == 0)
257
265
    {
258
266
        ptr_value = gui_color_get_custom (text + 6);
259
267
        return strdup ((ptr_value) ? ptr_value : "");
260
268
    }
261
269
 
262
 
    /* 3. look for an info */
 
270
    /* 4. look for an info */
263
271
    if (strncmp (text, "info:", 5) == 0)
264
272
    {
265
273
        ptr_value = NULL;
279
287
        return strdup ((ptr_value) ? ptr_value : "");
280
288
    }
281
289
 
282
 
    /* 4. look for name of option: if found, return this value */
 
290
    /* 5. look for name of option: if found, return this value */
283
291
    if (strncmp (text, "sec.data.", 9) == 0)
284
292
    {
285
293
        ptr_value = hashtable_get (secure_hashtable_data, text + 9);
312
320
        }
313
321
    }
314
322
 
315
 
    /* 5. look for local variable in buffer */
 
323
    /* 6. look for local variable in buffer */
316
324
    ptr_buffer = hashtable_get (pointers, "buffer");
317
325
    if (ptr_buffer)
318
326
    {
321
329
            return strdup (ptr_value);
322
330
    }
323
331
 
324
 
    /* 6. look for hdata */
 
332
    /* 7. look for hdata */
325
333
    value = NULL;
326
334
    hdata_name = NULL;
327
335
    list_name = NULL;
387
395
                   struct t_hashtable *extra_vars,
388
396
                   const char *prefix, const char *suffix)
389
397
{
390
 
    int errors;
391
398
    void *ptr[2];
392
399
 
393
400
    ptr[0] = pointers;
394
401
    ptr[1] = extra_vars;
395
402
 
396
403
    return string_replace_with_callback (expr, prefix, suffix,
397
 
                                         &eval_replace_vars_cb,
398
 
                                         ptr,
399
 
                                         &errors);
 
404
                                         &eval_replace_vars_cb, ptr, NULL);
400
405
}
401
406
 
402
407
/*
502
507
}
503
508
 
504
509
/*
 
510
 * Searches a string in another at same level (skip sub-expressions between
 
511
 * parentheses).
 
512
 *
 
513
 * For example: eval_strstr_level ("(x || y) || z", "||")
 
514
 * will return a pointer on  "|| z" (because the first "||" is
 
515
 * in a sub-expression, which is skipped).
 
516
 *
 
517
 * Returns pointer to string found, or NULL if not found.
 
518
 */
 
519
 
 
520
const char *
 
521
eval_strstr_level (const char *string, const char *search)
 
522
{
 
523
    const char *ptr_string;
 
524
    int level, length;
 
525
 
 
526
    if (!string || !search)
 
527
        return NULL;
 
528
 
 
529
    length = strlen (search);
 
530
 
 
531
    ptr_string = string;
 
532
    level = 0;
 
533
    while (ptr_string[0])
 
534
    {
 
535
        if (ptr_string[0] == '(')
 
536
        {
 
537
            level++;
 
538
        }
 
539
        else if (ptr_string[0] == ')')
 
540
        {
 
541
            if (level > 0)
 
542
                level--;
 
543
        }
 
544
 
 
545
        if ((level == 0) && (strncmp (ptr_string, search, length) == 0))
 
546
            return ptr_string;
 
547
 
 
548
        ptr_string++;
 
549
    }
 
550
 
 
551
    return NULL;
 
552
}
 
553
 
 
554
/*
505
555
 * Evaluates a condition (this function must not be called directly).
506
556
 *
507
 
 * Argument keep_parentheses is almost always 0, it is 1 only if the expression
508
 
 * is a regex (to keep flags inside the parentheses).
509
 
 *
510
557
 * For return value, see function eval_expression().
511
558
 *
512
559
 * Note: result must be freed after use (if not NULL).
513
560
 */
514
561
 
515
562
char *
516
 
eval_expression_condition (const char *expr, struct t_hashtable *pointers,
 
563
eval_expression_condition (const char *expr,
 
564
                           struct t_hashtable *pointers,
517
565
                           struct t_hashtable *extra_vars,
518
 
                           int keep_parentheses,
519
 
                           const char *prefix, const char *suffix)
 
566
                           const char *prefix,
 
567
                           const char *suffix)
520
568
{
521
569
    int logic, comp, length, level, rc;
522
 
    const char *pos_end;
523
 
    char *expr2, *sub_expr, *pos, *pos2, *value, *tmp_value, *tmp_value2;
 
570
    const char *pos, *pos_end;
 
571
    char *expr2, *sub_expr, *value, *tmp_value, *tmp_value2;
524
572
 
525
573
    value = NULL;
526
574
 
550
598
        return NULL;
551
599
 
552
600
    /*
553
 
     * evaluate sub-expressions between parentheses and replace them with their
554
 
     * value
555
 
     */
556
 
    if (!keep_parentheses)
557
 
    {
558
 
        while ((pos = strchr (expr2, '(')) != NULL)
559
 
        {
560
 
            level = 0;
561
 
            pos2 = pos + 1;
562
 
            while (pos2[0])
563
 
            {
564
 
                if (pos2[0] == '(')
565
 
                    level++;
566
 
                else if (pos2[0] == ')')
567
 
                {
568
 
                    if (level == 0)
569
 
                        break;
570
 
                    level--;
571
 
                }
572
 
                pos2++;
573
 
            }
574
 
            /* closing parenthesis not found */
575
 
            if (pos2[0] != ')')
576
 
                goto end;
577
 
            sub_expr = string_strndup (pos + 1, pos2 - pos - 1);
578
 
            if (!sub_expr)
579
 
                goto end;
580
 
            tmp_value = eval_expression_condition (sub_expr, pointers,
581
 
                                                   extra_vars,
582
 
                                                   0, prefix, suffix);
583
 
            free (sub_expr);
584
 
            if (!pos[1])
585
 
            {
586
 
                /* nothing around parentheses, then return value of sub-expression as-is */
587
 
                value = tmp_value;
588
 
                goto end;
589
 
            }
590
 
            /*
591
 
             * build a string with string before '(' +
592
 
             * result of sub-expression + string after ')'
593
 
             */
594
 
            length = (pos - expr2) + 1
595
 
                + ((tmp_value) ? strlen (tmp_value) : 0)
596
 
                + 1 + strlen (pos2 + 1)
597
 
                + 1;
598
 
            tmp_value2 = malloc (length);
599
 
            if (!tmp_value2)
600
 
                goto end;
601
 
            tmp_value2[0] = '\0';
602
 
            if (pos > expr2)
603
 
            {
604
 
                strncat (tmp_value2, expr2, pos - expr2);
605
 
                strcat (tmp_value2, " ");
606
 
            }
607
 
            if (tmp_value)
608
 
                strcat (tmp_value2, tmp_value);
609
 
            if (pos2[1])
610
 
            {
611
 
                strcat (tmp_value2, " ");
612
 
                strcat (tmp_value2, pos2 + 1);
613
 
            }
614
 
            free (expr2);
615
 
            expr2 = tmp_value2;
616
 
        }
617
 
    }
618
 
 
619
 
    /*
620
601
     * search for a logical operator, and if one is found:
621
602
     * - split expression into two sub-expressions
622
603
     * - evaluate first sub-expression
625
606
     */
626
607
    for (logic = 0; logic < EVAL_NUM_LOGICAL_OPS; logic++)
627
608
    {
628
 
        pos = strstr (expr2, logical_ops[logic]);
 
609
        pos = eval_strstr_level (expr2, logical_ops[logic]);
629
610
        if (pos > expr2)
630
611
        {
631
612
            pos_end = pos - 1;
638
619
                goto end;
639
620
            tmp_value = eval_expression_condition (sub_expr, pointers,
640
621
                                                   extra_vars,
641
 
                                                   0, prefix, suffix);
 
622
                                                   prefix, suffix);
642
623
            free (sub_expr);
643
624
            rc = eval_is_true (tmp_value);
644
625
            if (tmp_value)
645
626
                free (tmp_value);
646
627
            /*
647
 
             * if rc == 0 with "&&" or rc == 1 with "||", no need to evaluate
648
 
             * second sub-expression, just return the rc
 
628
             * if rc == 0 with "&&" or rc == 1 with "||", no need to
 
629
             * evaluate second sub-expression, just return the rc
649
630
             */
650
631
            if ((!rc && (logic == EVAL_LOGICAL_OP_AND))
651
632
                || (rc && (logic == EVAL_LOGICAL_OP_OR)))
659
640
                pos++;
660
641
            }
661
642
            tmp_value = eval_expression_condition (pos, pointers, extra_vars,
662
 
                                                   0, prefix, suffix);
 
643
                                                   prefix, suffix);
663
644
            rc = eval_is_true (tmp_value);
664
645
            if (tmp_value)
665
646
                free (tmp_value);
677
658
     */
678
659
    for (comp = 0; comp < EVAL_NUM_COMPARISONS; comp++)
679
660
    {
680
 
        pos = strstr (expr2, comparisons[comp]);
 
661
        pos = eval_strstr_level (expr2, comparisons[comp]);
681
662
        if (pos > expr2)
682
663
        {
683
664
            pos_end = pos - 1;
688
669
            sub_expr = string_strndup (expr2, pos_end + 1 - expr2);
689
670
            if (!sub_expr)
690
671
                goto end;
691
 
            tmp_value = eval_expression_condition (sub_expr, pointers,
692
 
                                                   extra_vars,
693
 
                                                   0, prefix, suffix);
694
 
            free (sub_expr);
695
672
            pos += strlen (comparisons[comp]);
696
673
            while (pos[0] == ' ')
697
674
            {
698
675
                pos++;
699
676
            }
700
 
            tmp_value2 = eval_expression_condition (pos, pointers, extra_vars,
701
 
                                                    ((comp == EVAL_COMPARE_REGEX_MATCHING)
702
 
                                                     || (comp == EVAL_COMPARE_REGEX_NOT_MATCHING)) ? 1 : 0,
703
 
                                                    prefix, suffix);
 
677
            if ((comp == EVAL_COMPARE_REGEX_MATCHING)
 
678
                || (comp == EVAL_COMPARE_REGEX_NOT_MATCHING))
 
679
            {
 
680
                /* for regex: just replace vars in both expressions */
 
681
                tmp_value = eval_replace_vars (sub_expr, pointers,
 
682
                                               extra_vars,
 
683
                                               prefix, suffix);
 
684
                tmp_value2 = eval_replace_vars (pos, pointers,
 
685
                                                extra_vars,
 
686
                                                prefix, suffix);
 
687
            }
 
688
            else
 
689
            {
 
690
                /* other comparison: fully evaluate both expressions */
 
691
                tmp_value = eval_expression_condition (sub_expr, pointers,
 
692
                                                       extra_vars,
 
693
                                                       prefix, suffix);
 
694
                tmp_value2 = eval_expression_condition (pos, pointers,
 
695
                                                        extra_vars,
 
696
                                                        prefix, suffix);
 
697
            }
 
698
            free (sub_expr);
704
699
            value = eval_compare (tmp_value, comp, tmp_value2);
705
700
            if (tmp_value)
706
701
                free (tmp_value);
711
706
    }
712
707
 
713
708
    /*
 
709
     * evaluate sub-expressions between parentheses and replace them with their
 
710
     * value
 
711
     */
 
712
    while (expr2[0] == '(')
 
713
    {
 
714
        level = 0;
 
715
        pos = expr2 + 1;
 
716
        while (pos[0])
 
717
        {
 
718
            if (pos[0] == '(')
 
719
                level++;
 
720
            else if (pos[0] == ')')
 
721
            {
 
722
                if (level == 0)
 
723
                    break;
 
724
                level--;
 
725
            }
 
726
            pos++;
 
727
        }
 
728
        /* closing parenthesis not found */
 
729
        if (pos[0] != ')')
 
730
            goto end;
 
731
        sub_expr = string_strndup (expr2 + 1, pos - expr2 - 1);
 
732
        if (!sub_expr)
 
733
            goto end;
 
734
        tmp_value = eval_expression_condition (sub_expr, pointers, extra_vars,
 
735
                                               prefix, suffix);
 
736
        free (sub_expr);
 
737
        if (!pos[1])
 
738
        {
 
739
            /*
 
740
             * nothing around parentheses, then return value of
 
741
             * sub-expression as-is
 
742
             */
 
743
            value = tmp_value;
 
744
            goto end;
 
745
        }
 
746
        length = ((tmp_value) ? strlen (tmp_value) : 0) + 1 +
 
747
            strlen (pos + 1) + 1;
 
748
        tmp_value2 = malloc (length);
 
749
        if (!tmp_value2)
 
750
        {
 
751
            if (tmp_value)
 
752
                free (tmp_value);
 
753
            goto end;
 
754
        }
 
755
        tmp_value2[0] = '\0';
 
756
        if (tmp_value)
 
757
            strcat (tmp_value2, tmp_value);
 
758
        strcat (tmp_value2, " ");
 
759
        strcat (tmp_value2, pos + 1);
 
760
        free (expr2);
 
761
        expr2 = tmp_value2;
 
762
        if (tmp_value)
 
763
            free (tmp_value);
 
764
    }
 
765
 
 
766
    /*
714
767
     * at this point, there is no more logical operator neither comparison,
715
768
     * so we just replace variables in string and return the result
716
769
     */
768
821
eval_expression (const char *expr, struct t_hashtable *pointers,
769
822
                 struct t_hashtable *extra_vars, struct t_hashtable *options)
770
823
{
771
 
    int condition, rc;
 
824
    int condition, rc, pointers_allocated;
772
825
    char *value;
773
826
    const char *prefix, *suffix, *default_prefix = "${", *default_suffix = "}";
774
827
    const char *ptr_value;
778
831
        return NULL;
779
832
 
780
833
    condition = 0;
 
834
    pointers_allocated = 0;
781
835
    prefix = default_prefix;
782
836
    suffix = default_suffix;
783
837
 
784
838
    /* create hashtable pointers if it's NULL */
785
839
    if (!pointers)
786
840
    {
787
 
        if (eval_hashtable_pointers)
788
 
            hashtable_remove_all (eval_hashtable_pointers);
789
 
        else
790
 
        {
791
 
            eval_hashtable_pointers = hashtable_new (32,
792
 
                                                     WEECHAT_HASHTABLE_STRING,
793
 
                                                     WEECHAT_HASHTABLE_POINTER,
794
 
                                                     NULL,
795
 
                                                     NULL);
796
 
            if (!eval_hashtable_pointers)
797
 
                return NULL;
798
 
        }
799
 
        pointers = eval_hashtable_pointers;
 
841
        pointers = hashtable_new (32,
 
842
                                  WEECHAT_HASHTABLE_STRING,
 
843
                                  WEECHAT_HASHTABLE_POINTER,
 
844
                                  NULL,
 
845
                                  NULL);
 
846
        if (!pointers)
 
847
            return NULL;
 
848
        pointers_allocated = 1;
800
849
    }
801
850
 
802
851
    /*
839
888
    {
840
889
        /* evaluate as condition (return a boolean: "0" or "1") */
841
890
        value = eval_expression_condition (expr, pointers, extra_vars,
842
 
                                           0, prefix, suffix);
 
891
                                           prefix, suffix);
843
892
        rc = eval_is_true (value);
844
893
        if (value)
845
894
            free (value);
851
900
        value = eval_replace_vars (expr, pointers, extra_vars, prefix, suffix);
852
901
    }
853
902
 
 
903
    if (pointers_allocated)
 
904
        hashtable_free (pointers);
 
905
 
854
906
    return value;
855
907
}
856
 
 
857
 
/*
858
 
 * Frees all allocated data.
859
 
 */
860
 
 
861
 
void
862
 
eval_end ()
863
 
{
864
 
    if (eval_hashtable_pointers)
865
 
    {
866
 
        hashtable_free (eval_hashtable_pointers);
867
 
        eval_hashtable_pointers = NULL;
868
 
    }
869
 
}