2 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
4 * A simple, extensible s-exp evaluation engine.
7 * Michael Zucchi <notzed@ximian.com>
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of version 2 of the GNU Lesser General Public
11 * License as published by the Free Software Foundation.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
25 * The following built-in s-exp's are supported:
28 * perform an intersection of a number of lists, and return that.
31 * perform a boolean AND of boolean values.
34 * perform a union of a number of lists, returning the new list.
37 * perform a boolean OR of boolean values.
42 * string = (+ string*)
45 * time_t = (+ time_t*)
48 * gint = (- gint int*)
49 * Subtract integers from the first.
51 * time_t = (- time_t*)
52 * Subtract time_t values from the first.
54 * gint = (cast-int string|int|bool)
55 * Cast to an integer value.
57 * string = (cast-string string|int|bool)
58 * Cast to an string value.
60 * Comparison operators:
62 * bool = (< gint gint)
63 * bool = (> gint gint)
64 * bool = (= gint gint)
66 * bool = (< string string)
67 * bool = (> string string)
68 * bool = (= string string)
70 * bool = (< time_t time_t)
71 * bool = (> time_t time_t)
72 * bool = (= time_t time_t)
73 * Perform a comparision of 2 integers, 2 string values, or 2 time values.
77 * type = (if bool function)
78 * type = (if bool function function)
79 * Choose a flow path based on a boolean value
81 * type = (begin func func func)
82 * Execute a sequence. The last function return is the return type.
97 #define p(x) /* parse debug */
98 #define r(x) /* run debug */
99 #define d(x) /* general debug */
101 #ifdef E_SEXP_IS_G_OBJECT
102 G_DEFINE_TYPE (ESExp, e_sexp, G_TYPE_OBJECT)
105 static struct _ESExpTerm *
106 parse_list (ESExp *f,
108 static struct _ESExpTerm *
109 parse_value (ESExp *f);
112 static void parse_dump_term (struct _ESExpTerm *t,
116 typedef gboolean (ESGeneratorFunc) (gint argc,
117 struct _ESExpResult **argv,
118 struct _ESExpResult *r);
119 typedef gboolean (ESOperatorFunc) (gint argc,
120 struct _ESExpResult **argv,
121 struct _ESExpResult *r);
123 /* FIXME: constant _TIME_MAX used in different files, move it somewhere */
124 #define _TIME_MAX ((time_t) INT_MAX) /* Max valid time_t */
126 static const GScannerConfig scanner_config =
128 ( (gchar *) " \t\r\n") /* cset_skip_characters */,
129 ( (gchar *) G_CSET_a_2_z
131 G_CSET_A_2_Z) /* cset_identifier_first */,
132 ( (gchar *) G_CSET_a_2_z
136 G_CSET_LATINC ) /* cset_identifier_nth */,
137 ( (gchar *) ";\n" ) /* cpair_comment_single */,
139 FALSE /* case_sensitive */,
141 TRUE /* skip_comment_multi */,
142 TRUE /* skip_comment_single */,
143 TRUE /* scan_comment_multi */,
144 TRUE /* scan_identifier */,
145 TRUE /* scan_identifier_1char */,
146 FALSE /* scan_identifier_NULL */,
147 TRUE /* scan_symbols */,
148 FALSE /* scan_binary */,
149 TRUE /* scan_octal */,
150 TRUE /* scan_float */,
152 FALSE /* scan_hex_dollar */,
153 TRUE /* scan_string_sq */,
154 TRUE /* scan_string_dq */,
155 TRUE /* numbers_2_int */,
156 FALSE /* int_2_float */,
157 FALSE /* identifier_2_string */,
158 TRUE /* char_2_token */,
159 FALSE /* symbol_2_token */,
160 FALSE /* scope_0_fallback */,
163 /* jumps back to the caller of f->failenv, only to be called from inside a callback */
165 e_sexp_fatal_error (struct _ESExp *f,
174 va_start (args, why);
175 f->error = g_strdup_vprintf (why, args);
178 longjmp (f->failenv, 1);
182 e_sexp_error (struct _ESExp *f)
187 struct _ESExpResult *
188 e_sexp_result_new (struct _ESExp *f,
191 struct _ESExpResult *r = e_memchunk_alloc0 (f->result_chunks);
193 r->occuring_start = 0;
194 r->occuring_end = _TIME_MAX;
195 r->time_generator = FALSE;
200 e_sexp_result_free (struct _ESExp *f,
201 struct _ESExpResult *t)
207 case ESEXP_RES_ARRAY_PTR:
208 g_ptr_array_free (t->value.ptrarray, TRUE);
214 case ESEXP_RES_STRING:
215 g_free (t->value.string);
217 case ESEXP_RES_UNDEFINED:
220 g_assert_not_reached ();
222 e_memchunk_free (f->result_chunks, t);
225 /* used in normal functions if they have to abort, and free their arguments */
227 e_sexp_resultv_free (struct _ESExp *f,
229 struct _ESExpResult **argv)
233 for (i = 0; i < argc; i++) {
234 e_sexp_result_free (f, argv[i]);
238 /* implementations for the builtin functions */
240 /* we can only itereate a hashtable from a called function */
246 /* ok, store any values that are in all sets */
250 struct IterData *iter_data)
252 if (value == iter_data->count) {
253 g_ptr_array_add (iter_data->uids, key);
257 /* or, store all unique values */
261 struct IterData *iter_data)
263 g_ptr_array_add (iter_data->uids, key);
267 term_eval_and (struct _ESExp *f,
269 struct _ESExpTerm **argv,
272 struct _ESExpResult *r, *r1;
273 GHashTable *ht = g_hash_table_new (g_str_hash, g_str_equal);
274 struct IterData lambdafoo;
280 r (printf ("( and\n"));
282 r = e_sexp_result_new (f, ESEXP_RES_UNDEFINED);
285 f->operators = g_slist_prepend (f->operators, (gpointer) oper);
287 for (i = 0; bool && i < argc; i++) {
288 r1 = e_sexp_term_eval (f, argv[i]);
291 if (type != r1->type) {
292 e_sexp_result_free (f, r);
293 e_sexp_result_free (f, r1);
294 g_hash_table_destroy (ht);
295 e_sexp_fatal_error (f, "Invalid types in AND");
296 } else if (r1->type == ESEXP_RES_ARRAY_PTR) {
300 a1 = (gchar **) r1->value.ptrarray->pdata;
301 l1 = r1->value.ptrarray->len;
302 for (j = 0; j < l1; j++) {
305 ptr = g_hash_table_lookup (ht, a1[j]);
306 n = GPOINTER_TO_INT (ptr);
307 g_hash_table_insert (ht, a1[j], GINT_TO_POINTER (n + 1));
309 } else if (r1->type == ESEXP_RES_BOOL) {
310 bool = bool && r1->value.boolean;
312 e_sexp_result_free (f, r1);
315 if (type == ESEXP_RES_ARRAY_PTR) {
316 lambdafoo.count = argc;
317 lambdafoo.uids = g_ptr_array_new ();
318 g_hash_table_foreach (ht, (GHFunc) htand, &lambdafoo);
319 r->type = ESEXP_RES_ARRAY_PTR;
320 r->value.ptrarray = lambdafoo.uids;
321 } else if (type == ESEXP_RES_BOOL) {
322 r->type = ESEXP_RES_BOOL;
323 r->value.boolean = bool;
326 g_hash_table_destroy (ht);
327 f->operators = g_slist_remove (f->operators, oper);
333 term_eval_or (struct _ESExp *f,
335 struct _ESExpTerm **argv,
338 struct _ESExpResult *r, *r1;
339 GHashTable *ht = g_hash_table_new (g_str_hash, g_str_equal);
340 struct IterData lambdafoo;
346 r (printf ("(or \n"));
349 f->operators = g_slist_prepend (f->operators, (gpointer) oper);
351 r = e_sexp_result_new (f, ESEXP_RES_UNDEFINED);
353 for (i = 0; !bool && i < argc; i++) {
354 r1 = e_sexp_term_eval (f, argv[i]);
357 if (r1->type != type) {
358 e_sexp_result_free (f, r);
359 e_sexp_result_free (f, r1);
360 g_hash_table_destroy (ht);
361 e_sexp_fatal_error (f, "Invalid types in OR");
362 } else if (r1->type == ESEXP_RES_ARRAY_PTR) {
366 a1 = (gchar **) r1->value.ptrarray->pdata;
367 l1 = r1->value.ptrarray->len;
368 for (j = 0; j < l1; j++) {
369 g_hash_table_insert (ht, a1[j], (gpointer) 1);
371 } else if (r1->type == ESEXP_RES_BOOL) {
372 bool |= r1->value.boolean;
374 e_sexp_result_free (f, r1);
377 if (type == ESEXP_RES_ARRAY_PTR) {
378 lambdafoo.count = argc;
379 lambdafoo.uids = g_ptr_array_new ();
380 g_hash_table_foreach (ht, (GHFunc) htor, &lambdafoo);
381 r->type = ESEXP_RES_ARRAY_PTR;
382 r->value.ptrarray = lambdafoo.uids;
383 } else if (type == ESEXP_RES_BOOL) {
384 r->type = ESEXP_RES_BOOL;
385 r->value.boolean = bool;
387 g_hash_table_destroy (ht);
389 f->operators = g_slist_remove (f->operators, oper);
394 term_eval_not (struct _ESExp *f,
396 struct _ESExpResult **argv,
403 if (argv[0]->type == ESEXP_RES_BOOL
404 && argv[0]->value.boolean)
407 r = e_sexp_result_new (f, ESEXP_RES_BOOL);
408 r->value.boolean = res;
412 /* this should support all arguments ...? */
414 term_eval_lt (struct _ESExp *f,
416 struct _ESExpTerm **argv,
419 struct _ESExpResult *r, *r1, *r2;
421 r = e_sexp_result_new (f, ESEXP_RES_UNDEFINED);
424 r1 = e_sexp_term_eval (f, argv[0]);
425 r2 = e_sexp_term_eval (f, argv[1]);
426 if (r1->type != r2->type) {
427 e_sexp_result_free (f, r1);
428 e_sexp_result_free (f, r2);
429 e_sexp_result_free (f, r);
430 e_sexp_fatal_error (f, "Incompatible types in compare <");
431 } else if (r1->type == ESEXP_RES_INT) {
432 r->type = ESEXP_RES_BOOL;
433 r->value.boolean = r1->value.number < r2->value.number;
434 } else if (r1->type == ESEXP_RES_TIME) {
435 r->type = ESEXP_RES_BOOL;
436 r->value.boolean = r1->value.time < r2->value.time;
437 } else if (r1->type == ESEXP_RES_STRING) {
438 r->type = ESEXP_RES_BOOL;
439 r->value.boolean = strcmp (r1->value.string, r2->value.string) < 0;
441 e_sexp_result_free (f, r1);
442 e_sexp_result_free (f, r2);
447 /* this should support all arguments ...? */
449 term_eval_gt (struct _ESExp *f,
451 struct _ESExpTerm **argv,
454 struct _ESExpResult *r, *r1, *r2;
456 r = e_sexp_result_new (f, ESEXP_RES_UNDEFINED);
459 r1 = e_sexp_term_eval (f, argv[0]);
460 r2 = e_sexp_term_eval (f, argv[1]);
461 if (r1->type != r2->type) {
462 e_sexp_result_free (f, r1);
463 e_sexp_result_free (f, r2);
464 e_sexp_result_free (f, r);
465 e_sexp_fatal_error (f, "Incompatible types in compare >");
466 } else if (r1->type == ESEXP_RES_INT) {
467 r->type = ESEXP_RES_BOOL;
468 r->value.boolean = r1->value.number > r2->value.number;
469 } else if (r1->type == ESEXP_RES_TIME) {
470 r->type = ESEXP_RES_BOOL;
471 r->value.boolean = r1->value.time > r2->value.time;
472 } else if (r1->type == ESEXP_RES_STRING) {
473 r->type = ESEXP_RES_BOOL;
474 r->value.boolean = strcmp (r1->value.string, r2->value.string) > 0;
476 e_sexp_result_free (f, r1);
477 e_sexp_result_free (f, r2);
482 /* this should support all arguments ...? */
484 term_eval_eq (struct _ESExp *f,
486 struct _ESExpTerm **argv,
489 struct _ESExpResult *r, *r1, *r2;
491 r = e_sexp_result_new (f, ESEXP_RES_BOOL);
494 r1 = e_sexp_term_eval (f, argv[0]);
495 r2 = e_sexp_term_eval (f, argv[1]);
496 if (r1->type != r2->type) {
497 r->value.boolean = FALSE;
498 } else if (r1->type == ESEXP_RES_INT) {
499 r->value.boolean = r1->value.number == r2->value.number;
500 } else if (r1->type == ESEXP_RES_BOOL) {
501 r->value.boolean = r1->value.boolean == r2->value.boolean;
502 } else if (r1->type == ESEXP_RES_TIME) {
503 r->value.boolean = r1->value.time == r2->value.time;
504 } else if (r1->type == ESEXP_RES_STRING) {
505 r->value.boolean = strcmp (r1->value.string, r2->value.string) == 0;
507 e_sexp_result_free (f, r1);
508 e_sexp_result_free (f, r2);
514 term_eval_plus (struct _ESExp *f,
516 struct _ESExpResult **argv,
519 struct _ESExpResult *r = NULL;
524 type = argv[0]->type;
526 case ESEXP_RES_INT: {
527 gint total = argv[0]->value.number;
528 for (i = 1; i < argc && argv[i]->type == ESEXP_RES_INT; i++) {
529 total += argv[i]->value.number;
532 e_sexp_resultv_free (f, argc, argv);
533 e_sexp_fatal_error (f, "Invalid types in (+ ints)");
535 r = e_sexp_result_new (f, ESEXP_RES_INT);
536 r->value.number = total;
538 case ESEXP_RES_STRING: {
539 GString *s = g_string_new (argv[0]->value.string);
540 for (i = 1; i < argc && argv[i]->type == ESEXP_RES_STRING; i++) {
541 g_string_append (s, argv[i]->value.string);
544 e_sexp_resultv_free (f, argc, argv);
545 e_sexp_fatal_error (f, "Invalid types in (+ strings)");
547 r = e_sexp_result_new (f, ESEXP_RES_STRING);
548 r->value.string = s->str;
549 g_string_free (s, FALSE);
551 case ESEXP_RES_TIME: {
554 total = argv[0]->value.time;
556 for (i = 1; i < argc && argv[i]->type == ESEXP_RES_TIME; i++)
557 total += argv[i]->value.time;
560 e_sexp_resultv_free (f, argc, argv);
561 e_sexp_fatal_error (f, "Invalid types in (+ time_t)");
564 r = e_sexp_result_new (f, ESEXP_RES_TIME);
565 r->value.time = total;
571 r = e_sexp_result_new (f, ESEXP_RES_INT);
578 term_eval_sub (struct _ESExp *f,
580 struct _ESExpResult **argv,
583 struct _ESExpResult *r = NULL;
588 type = argv[0]->type;
590 case ESEXP_RES_INT: {
591 gint total = argv[0]->value.number;
592 for (i = 1; i < argc && argv[i]->type == ESEXP_RES_INT; i++) {
593 total -= argv[i]->value.number;
596 e_sexp_resultv_free (f, argc, argv);
597 e_sexp_fatal_error (f, "Invalid types in -");
599 r = e_sexp_result_new (f, ESEXP_RES_INT);
600 r->value.number = total;
602 case ESEXP_RES_TIME: {
605 total = argv[0]->value.time;
607 for (i = 1; i < argc && argv[i]->type == ESEXP_RES_TIME; i++)
608 total -= argv[i]->value.time;
611 e_sexp_resultv_free (f, argc, argv);
612 e_sexp_fatal_error (f, "Invalid types in (- time_t)");
615 r = e_sexp_result_new (f, ESEXP_RES_TIME);
616 r->value.time = total;
622 r = e_sexp_result_new (f, ESEXP_RES_INT);
630 term_eval_castint (struct _ESExp *f,
632 struct _ESExpResult **argv,
635 struct _ESExpResult *r;
638 e_sexp_fatal_error (f, "Incorrect argument count to (gint )");
640 r = e_sexp_result_new (f, ESEXP_RES_INT);
641 switch (argv[0]->type) {
643 r->value.number = argv[0]->value.number;
646 r->value.number = argv[0]->value.boolean != 0;
648 case ESEXP_RES_STRING:
649 r->value.number = strtoul (argv[0]->value.string, NULL, 10);
652 e_sexp_result_free (f, r);
653 e_sexp_fatal_error (f, "Invalid type in (cast-int )");
661 term_eval_caststring (struct _ESExp *f,
663 struct _ESExpResult **argv,
666 struct _ESExpResult *r;
669 e_sexp_fatal_error (f, "Incorrect argument count to (cast-string )");
671 r = e_sexp_result_new (f, ESEXP_RES_STRING);
672 switch (argv[0]->type) {
674 r->value.string = g_strdup_printf ("%d", argv[0]->value.number);
677 r->value.string = g_strdup_printf ("%d", argv[0]->value.boolean != 0);
679 case ESEXP_RES_STRING:
680 r->value.string = g_strdup (argv[0]->value.string);
683 e_sexp_result_free (f, r);
684 e_sexp_fatal_error (f, "Invalid type in (gint )");
690 /* implements 'if' function */
692 term_eval_if (struct _ESExp *f,
694 struct _ESExpTerm **argv,
697 struct _ESExpResult *r;
700 if (argc >=2 && argc <= 3) {
701 r = e_sexp_term_eval (f, argv[0]);
702 doit = (r->type == ESEXP_RES_BOOL && r->value.boolean);
703 e_sexp_result_free (f, r);
705 return e_sexp_term_eval (f, argv[1]);
706 } else if (argc > 2) {
707 return e_sexp_term_eval (f, argv[2]);
710 return e_sexp_result_new (f, ESEXP_RES_UNDEFINED);
713 /* implements 'begin' statement */
715 term_eval_begin (struct _ESExp *f,
717 struct _ESExpTerm **argv,
720 struct _ESExpResult *r = NULL;
723 for (i = 0; i < argc; i++) {
725 e_sexp_result_free (f, r);
726 r = e_sexp_term_eval (f, argv[i]);
731 return e_sexp_result_new (f, ESEXP_RES_UNDEFINED);
734 /* this must only be called from inside term evaluation callbacks! */
735 struct _ESExpResult *
736 e_sexp_term_eval (struct _ESExp *f,
737 struct _ESExpTerm *t)
739 struct _ESExpResult *r = NULL;
741 struct _ESExpResult **argv;
743 g_return_val_if_fail (t != NULL, NULL);
745 r (printf ("eval term :\n"));
746 r (parse_dump_term (t, 0));
749 case ESEXP_TERM_STRING:
750 r (printf (" (string \"%s\")\n", t->value.string));
751 r = e_sexp_result_new (f, ESEXP_RES_STRING);
752 /* erk, this shoul;dn't need to strdup this ... */
753 r->value.string = g_strdup (t->value.string);
756 r (printf (" (gint %d)\n", t->value.number));
757 r = e_sexp_result_new (f, ESEXP_RES_INT);
758 r->value.number = t->value.number;
760 case ESEXP_TERM_BOOL:
761 r (printf (" (gint %d)\n", t->value.number));
762 r = e_sexp_result_new (f, ESEXP_RES_BOOL);
763 r->value.boolean = t->value.boolean;
765 case ESEXP_TERM_TIME:
766 r (printf (" (time_t %ld)\n", t->value.time));
767 r = e_sexp_result_new (f, ESEXP_RES_TIME);
768 r->value.time = t->value.time;
770 case ESEXP_TERM_IFUNC:
771 if (t->value.func.sym && t->value.func.sym->f.ifunc)
772 r = t->value.func.sym->f.ifunc (
773 f, t->value.func.termcount,
774 t->value.func.terms, t->value.func.sym->data);
776 case ESEXP_TERM_FUNC:
777 /* first evaluate all arguments to result types */
778 argv = alloca (sizeof (argv[0]) * t->value.func.termcount);
779 for (i = 0; i < t->value.func.termcount; i++) {
780 argv[i] = e_sexp_term_eval (f, t->value.func.terms[i]);
782 /* call the function */
783 if (t->value.func.sym->f.func)
784 r = t->value.func.sym->f.func (
785 f, t->value.func.termcount,
786 argv, t->value.func.sym->data);
788 e_sexp_resultv_free (f, t->value.func.termcount, argv);
791 e_sexp_fatal_error (f, "Unknown type in parse tree: %d", t->type);
795 r = e_sexp_result_new (f, ESEXP_RES_UNDEFINED);
802 eval_dump_result (ESExpResult *r,
808 printf ("null result???\n");
812 for (i = 0; i < depth; i++)
816 case ESEXP_RES_ARRAY_PTR:
817 printf ("array pointers\n");
820 printf ("int: %d\n", r->value.number);
822 case ESEXP_RES_STRING:
823 printf ("string: '%s'\n", r->value.string);
826 printf ("bool: %c\n", r->value.boolean ? 't':'f');
829 printf ("time_t: %ld\n", (glong) r->value.time);
831 case ESEXP_RES_UNDEFINED:
832 printf (" <undefined>\n");
841 parse_dump_term (struct _ESExpTerm *t,
847 printf ("null term??\n");
851 for (i = 0; i < depth; i++)
855 case ESEXP_TERM_STRING:
856 printf (" \"%s\"", t->value.string);
859 printf (" %d", t->value.number);
861 case ESEXP_TERM_BOOL:
862 printf (" #%c", t->value.boolean ? 't':'f');
864 case ESEXP_TERM_TIME:
865 printf (" %ld", (glong) t->value.time);
867 case ESEXP_TERM_IFUNC:
868 case ESEXP_TERM_FUNC:
869 printf (" (function %s\n", t->value.func.sym->name);
870 /*printf(" [%d] ", t->value.func.termcount);*/
871 for (i = 0; i < t->value.func.termcount; i++) {
872 parse_dump_term (t->value.func.terms[i], depth + 1);
874 for (i = 0; i < depth; i++)
879 printf (" (variable %s )\n", t->value.var->name);
882 printf ("unknown type: %d\n", t->type);
889 const gchar *time_functions[] = {
898 occur_in_time_range_generator (gint argc,
899 struct _ESExpResult **argv,
900 struct _ESExpResult *r)
902 g_return_val_if_fail (r != NULL, FALSE);
903 g_return_val_if_fail (argc == 2 || argc == 3, FALSE);
905 if ((argv[0]->type != ESEXP_RES_TIME) || (argv[1]->type != ESEXP_RES_TIME))
908 r->occuring_start = argv[0]->value.time;
909 r->occuring_end = argv[1]->value.time;
915 binary_generator (gint argc,
916 struct _ESExpResult **argv,
917 struct _ESExpResult *r)
919 g_return_val_if_fail (r != NULL, FALSE);
920 g_return_val_if_fail (argc == 2, FALSE);
922 if ((argv[0]->type != ESEXP_RES_TIME) || (argv[1]->type != ESEXP_RES_TIME))
925 r->occuring_start = argv[0]->value.time;
926 r->occuring_end = argv[1]->value.time;
932 unary_generator (gint argc,
933 struct _ESExpResult **argv,
934 struct _ESExpResult *r)
936 /* unary generator with end time */
937 g_return_val_if_fail (r != NULL, FALSE);
938 g_return_val_if_fail (argc == 1, FALSE);
940 if (argv[0]->type != ESEXP_RES_TIME)
943 r->occuring_start = 0;
944 r->occuring_end = argv[0]->value.time;
949 static const struct {
951 ESGeneratorFunc *func;
953 {"occur-in-time-range?", occur_in_time_range_generator},
954 {"due-in-time-range?", binary_generator},
955 {"has-alarms-in-range?", binary_generator},
956 {"completed-before?", unary_generator},
959 const gint generators_count = sizeof (generators) / sizeof (generators[0]);
962 or_operator (gint argc,
963 struct _ESExpResult **argv,
964 struct _ESExpResult *r)
971 * norm (0) norm (0) norm (0)
972 * gen (1) norm (0) norm (0)
973 * norm (0) gen (1) norm (0)
974 * gen (1) gen (1) gen*(1)
977 g_return_val_if_fail (r != NULL, FALSE);
978 g_return_val_if_fail (argc > 0, FALSE);
980 r->time_generator = TRUE;
981 for (ii = 0; ii < argc && r->time_generator; ii++) {
982 r->time_generator = argv[ii]->time_generator;
985 if (r->time_generator) {
986 r->occuring_start = argv[0]->occuring_start;
987 r->occuring_end = argv[0]->occuring_end;
989 for (ii = 1; ii < argc; ii++) {
990 r->occuring_start = MIN (r->occuring_start, argv[ii]->occuring_start);
991 r->occuring_end = MAX (r->occuring_end, argv[ii]->occuring_end);
999 and_operator (gint argc,
1000 struct _ESExpResult **argv,
1001 struct _ESExpResult *r)
1007 * ---- ---- ------- -
1008 * norm (0) norm (0) norm (0)
1009 * gen (1) norm (0) gen (1)
1010 * norm (0) gen (1) gen (1)
1011 * gen (1) gen (1) gen (1)
1014 g_return_val_if_fail (r != NULL, FALSE);
1015 g_return_val_if_fail (argc > 0, FALSE);
1017 r->time_generator = FALSE;
1018 for (ii = 0; ii < argc && !r->time_generator; ii++) {
1019 r->time_generator = argv[ii]->time_generator;
1022 if (r->time_generator) {
1023 r->occuring_start = argv[0]->occuring_start;
1024 r->occuring_end = argv[0]->occuring_end;
1026 for (ii = 1; ii < argc; ii++) {
1027 r->occuring_start = MAX (r->occuring_start, argv[ii]->occuring_start);
1028 r->occuring_end = MIN (r->occuring_end, argv[ii]->occuring_end);
1035 static const struct {
1037 ESOperatorFunc *func;
1039 {"or", or_operator},
1040 {"and", and_operator}
1043 const gint operators_count = sizeof (operators) / sizeof (operators[0]);
1045 static ESOperatorFunc *
1046 get_operator_function (const gchar *fname)
1050 g_return_val_if_fail (fname != NULL, NULL);
1052 for (i = 0; i < sizeof (operators) / sizeof (operators[0]); i++)
1053 if (strcmp (operators[i].name, fname) == 0)
1054 return operators[i].func;
1059 static inline gboolean
1060 is_time_function (const gchar *fname)
1064 g_return_val_if_fail (fname != NULL, FALSE);
1066 for (i = 0; i < sizeof (time_functions) / sizeof (time_functions[0]); i++)
1067 if (strcmp (time_functions[i], fname) == 0)
1073 static ESGeneratorFunc *
1074 get_generator_function (const gchar *fname)
1078 g_return_val_if_fail (fname != NULL, NULL);
1080 for (i = 0; i < sizeof (generators) / sizeof (generators[0]); i++)
1081 if (strcmp (generators[i].name, fname) == 0)
1082 return generators[i].func;
1087 /* this must only be called from inside term evaluation callbacks! */
1088 static struct _ESExpResult *
1089 e_sexp_term_evaluate_occur_times (struct _ESExp *f,
1090 struct _ESExpTerm *t,
1094 struct _ESExpResult *r = NULL;
1096 struct _ESExpResult **argv;
1099 g_return_val_if_fail (t != NULL, NULL);
1100 g_return_val_if_fail (start != NULL, NULL);
1101 g_return_val_if_fail (end != NULL, NULL);
1104 printf ("eval term :\n");
1105 parse_dump_term (t, 0);
1109 case ESEXP_TERM_STRING:
1110 r (printf (" (string \"%s\")\n", t->value.string));
1111 r = e_sexp_result_new (f, ESEXP_RES_STRING);
1112 r->value.string = g_strdup (t->value.string);
1114 case ESEXP_TERM_IFUNC:
1115 case ESEXP_TERM_FUNC:
1117 ESGeneratorFunc *generator = NULL;
1118 ESOperatorFunc *operator = NULL;
1120 r (printf (" (function \"%s\"\n", t->value.func.sym->name));
1122 r = e_sexp_result_new (f, ESEXP_RES_UNDEFINED);
1123 argc = t->value.func.termcount;
1124 argv = alloca (sizeof (argv[0]) * argc);
1126 for (i = 0; i < t->value.func.termcount; i++) {
1127 argv[i] = e_sexp_term_evaluate_occur_times (
1128 f, t->value.func.terms[i], start, end);
1131 if (is_time_function (t->value.func.sym->name)) {
1133 if (t->value.func.sym->f.func)
1134 r = t->value.func.sym->f.func (f, t->value.func.termcount,
1135 argv, t->value.func.sym->data);
1136 } else if ((generator = get_generator_function (t->value.func.sym->name)) != NULL) {
1137 /* evaluate generator function */
1138 r->time_generator = TRUE;
1139 ok = generator (argc, argv, r);
1140 } else if ((operator = get_operator_function (t->value.func.sym->name)) != NULL)
1141 /* evaluate operator function */
1142 ok = operator (argc, argv, r);
1144 /* normal function: we need to scan all objects */
1145 r->time_generator = FALSE;
1148 e_sexp_resultv_free (f, t->value.func.termcount, argv);
1151 case ESEXP_TERM_INT:
1152 case ESEXP_TERM_BOOL:
1153 case ESEXP_TERM_TIME:
1161 e_sexp_fatal_error (f, "Error in parse tree");
1164 r = e_sexp_result_new (f, ESEXP_RES_UNDEFINED);
1173 static struct _ESExpTerm *
1174 parse_term_new (struct _ESExp *f,
1177 struct _ESExpTerm *s = e_memchunk_alloc0 (f->term_chunks);
1183 parse_term_free (struct _ESExp *f,
1184 struct _ESExpTerm *t)
1193 case ESEXP_TERM_INT:
1194 case ESEXP_TERM_BOOL:
1195 case ESEXP_TERM_TIME:
1196 case ESEXP_TERM_VAR:
1199 case ESEXP_TERM_STRING:
1200 g_free (t->value.string);
1203 case ESEXP_TERM_FUNC:
1204 case ESEXP_TERM_IFUNC:
1205 for (i = 0; i < t->value.func.termcount; i++) {
1206 parse_term_free (f, t->value.func.terms[i]);
1208 g_free (t->value.func.terms);
1212 printf ("parse_term_free: unknown type: %d\n", t->type);
1214 e_memchunk_free (f->term_chunks, t);
1217 static struct _ESExpTerm **
1218 parse_values (ESExp *f,
1222 struct _ESExpTerm **terms;
1224 GScanner *gs = f->scanner;
1225 GSList *list = NULL, *l;
1227 p (printf ("parsing values\n"));
1229 while ( (token = g_scanner_peek_next_token (gs)) != G_TOKEN_EOF
1231 list = g_slist_prepend (list, parse_value (f));
1235 /* go over the list, and put them backwards into the term array */
1236 terms = g_malloc (size * sizeof (*terms));
1238 for (i = size - 1; i >= 0; i--) {
1242 l = g_slist_next (l);
1244 g_slist_free (list);
1246 p (printf ("found %d subterms\n", size));
1249 p (printf ("done parsing values\n"));
1254 * e_sexp_parse_value:
1259 e_sexp_parse_value (ESExp *f)
1261 return parse_value (f);
1264 static struct _ESExpTerm *
1265 parse_value (ESExp *f)
1267 gint token, negative = FALSE;
1268 struct _ESExpTerm *t = NULL;
1269 GScanner *gs = f->scanner;
1270 struct _ESExpSymbol *s;
1272 p (printf ("parsing value\n"));
1274 token = g_scanner_get_next_token (gs);
1278 case G_TOKEN_LEFT_PAREN:
1279 p (printf ("got brace, its a list!\n"));
1280 return parse_list (f, TRUE);
1281 case G_TOKEN_STRING:
1283 "got string '%s'\n",
1284 g_scanner_cur_value (gs).v_string));
1285 t = parse_term_new (f, ESEXP_TERM_STRING);
1286 t->value.string = g_strdup (g_scanner_cur_value (gs).v_string);
1289 p (printf ("got negative int?\n"));
1290 token = g_scanner_get_next_token (gs);
1291 if (token != G_TOKEN_INT) {
1292 e_sexp_fatal_error (
1293 f, "Invalid format for a integer value");
1298 /* fall through... */
1300 t = parse_term_new (f, ESEXP_TERM_INT);
1301 t->value.number = g_scanner_cur_value (gs).v_int;
1303 t->value.number = -t->value.number;
1304 p (printf ("got gint %d\n", t->value.number));
1309 p (printf ("got bool?\n"));
1310 token = g_scanner_get_next_token (gs);
1311 if (token != G_TOKEN_IDENTIFIER) {
1312 e_sexp_fatal_error (
1313 f, "Invalid format for a boolean value");
1317 str = g_scanner_cur_value (gs).v_identifier;
1319 g_assert (str != NULL);
1320 if (!(strlen (str) == 1 && (str[0] == 't' || str[0] == 'f'))) {
1321 e_sexp_fatal_error (
1322 f, "Invalid format for a boolean value");
1326 t = parse_term_new (f, ESEXP_TERM_BOOL);
1327 t->value.boolean = (str[0] == 't');
1329 case G_TOKEN_SYMBOL:
1330 s = g_scanner_cur_value (gs).v_symbol;
1331 p (printf ("got symbol '%s'\n", s->name));
1333 case ESEXP_TERM_FUNC:
1334 case ESEXP_TERM_IFUNC:
1335 /* this is basically invalid, since we can't use
1336 * function pointers, but let the runtime catch it */
1337 t = parse_term_new (f, s->type);
1338 t->value.func.sym = s;
1339 t->value.func.terms = parse_values (
1340 f, &t->value.func.termcount);
1342 case ESEXP_TERM_VAR:
1343 t = parse_term_new (f, s->type);
1347 e_sexp_fatal_error (
1348 f, "Invalid symbol type: %s: %d",
1352 case G_TOKEN_IDENTIFIER:
1354 "got unknown identifider '%s'\n",
1355 g_scanner_cur_value (gs).v_identifier));
1356 e_sexp_fatal_error (
1357 f, "Unknown identifier: %s",
1358 g_scanner_cur_value (gs).v_identifier);
1361 e_sexp_fatal_error (
1362 f, "Unexpected token encountered: %d", token);
1364 p (printf ("done parsing value\n"));
1368 /* FIXME: this needs some robustification */
1369 static struct _ESExpTerm *
1370 parse_list (ESExp *f,
1374 struct _ESExpTerm *t = NULL;
1375 GScanner *gs = f->scanner;
1377 p (printf ("parsing list\n"));
1381 token = g_scanner_get_next_token (gs);
1383 token = g_scanner_get_next_token (gs);
1385 case G_TOKEN_SYMBOL: {
1386 struct _ESExpSymbol *s;
1388 s = g_scanner_cur_value (gs).v_symbol;
1389 p (printf ("got funciton: %s\n", s->name));
1390 t = parse_term_new (f, s->type);
1391 p (printf ("created new list %p\n", t));
1392 /* if we have a variable, find out its base type */
1393 while (s->type == ESEXP_TERM_VAR) {
1394 s = ((ESExpTerm *)(s->data))->value.var;
1396 if (s->type == ESEXP_TERM_FUNC
1397 || s->type == ESEXP_TERM_IFUNC) {
1398 t->value.func.sym = s;
1399 t->value.func.terms = parse_values (
1400 f, &t->value.func.termcount);
1402 parse_term_free (f, t);
1403 e_sexp_fatal_error (
1404 f, "Trying to call variable "
1405 "as function: %s", s->name);
1408 case G_TOKEN_IDENTIFIER:
1409 e_sexp_fatal_error (
1410 f, "Unknown identifier: %s",
1411 g_scanner_cur_value (gs).v_identifier);
1413 case G_TOKEN_LEFT_PAREN:
1414 return parse_list (f, TRUE);
1416 e_sexp_fatal_error (f, "Unexpected token encountered: %d", token);
1418 token = g_scanner_get_next_token (gs);
1420 e_sexp_fatal_error (f, "Missing ')'");
1423 e_sexp_fatal_error (f, "Missing '('");
1426 p (printf ("returning list %p\n", t));
1430 static void e_sexp_finalise (gpointer);
1432 #ifdef E_SEXP_IS_G_OBJECT
1434 e_sexp_class_init (ESExpClass *class)
1436 GObjectClass *object_class = G_OBJECT_CLASS (class);
1438 object_class->finalize = e_sexp_finalise;
1442 /* 'builtin' functions */
1443 static const struct {
1446 gint type; /* set to 1 if a function can perform shortcut evaluation, or
1447 doesn't execute everything, 0 otherwise */
1449 { "and", (ESExpFunc *) term_eval_and, 1 },
1450 { "or", (ESExpFunc *) term_eval_or, 1 },
1451 { "not", (ESExpFunc *) term_eval_not, 0 },
1452 { "<", (ESExpFunc *) term_eval_lt, 1 },
1453 { ">", (ESExpFunc *) term_eval_gt, 1 },
1454 { "=", (ESExpFunc *) term_eval_eq, 1 },
1455 { "+", (ESExpFunc *) term_eval_plus, 0 },
1456 { "-", (ESExpFunc *) term_eval_sub, 0 },
1457 { "cast-int", (ESExpFunc *) term_eval_castint, 0 },
1458 { "cast-string", (ESExpFunc *) term_eval_caststring, 0 },
1459 { "if", (ESExpFunc *) term_eval_if, 1 },
1460 { "begin", (ESExpFunc *) term_eval_begin, 1 },
1464 free_symbol (gpointer key,
1468 struct _ESExpSymbol *s = value;
1475 e_sexp_finalise (gpointer o)
1477 ESExp *s = (ESExp *) o;
1480 parse_term_free (s, s->tree);
1484 e_memchunk_destroy (s->term_chunks);
1485 e_memchunk_destroy (s->result_chunks);
1487 g_scanner_scope_foreach_symbol (s->scanner, 0, free_symbol, NULL);
1488 g_scanner_destroy (s->scanner);
1490 #ifdef E_SEXP_IS_G_OBJECT
1491 G_OBJECT_CLASS (e_sexp_parent_class)->finalize (o);
1496 e_sexp_init (ESExp *s)
1500 s->scanner = g_scanner_new (&scanner_config);
1501 s->term_chunks = e_memchunk_new (16, sizeof (struct _ESExpTerm));
1502 s->result_chunks = e_memchunk_new (16, sizeof (struct _ESExpResult));
1504 /* load in builtin symbols? */
1505 for (i = 0; i < G_N_ELEMENTS (symbols); i++) {
1506 if (symbols[i].type == 1) {
1507 e_sexp_add_ifunction (
1510 (ESExpIFunc *) symbols[i].func,
1511 (gpointer) &symbols[i]);
1513 e_sexp_add_function (
1517 (gpointer) &symbols[i]);
1521 #ifndef E_SEXP_IS_G_OBJECT
1529 #ifdef E_SEXP_IS_G_OBJECT
1530 ESExp *f = (ESexp *) g_object_new (E_TYPE_SEXP, NULL);
1532 ESExp *f = g_malloc0 (sizeof (ESExp));
1539 #ifndef E_SEXP_IS_G_OBJECT
1541 e_sexp_ref (ESExp *f)
1547 e_sexp_unref (ESExp *f)
1550 if (f->refcount == 0) {
1551 e_sexp_finalise (f);
1558 e_sexp_add_function (ESExp *f,
1564 struct _ESExpSymbol *s;
1566 g_return_if_fail (IS_E_SEXP (f));
1567 g_return_if_fail (name != NULL);
1569 e_sexp_remove_symbol (f, scope, name);
1571 s = g_malloc0 (sizeof (*s));
1572 s->name = g_strdup (name);
1574 s->type = ESEXP_TERM_FUNC;
1576 g_scanner_scope_add_symbol (f->scanner, scope, s->name, s);
1580 e_sexp_add_ifunction (ESExp *f,
1586 struct _ESExpSymbol *s;
1588 g_return_if_fail (IS_E_SEXP (f));
1589 g_return_if_fail (name != NULL);
1591 e_sexp_remove_symbol (f, scope, name);
1593 s = g_malloc0 (sizeof (*s));
1594 s->name = g_strdup (name);
1596 s->type = ESEXP_TERM_IFUNC;
1598 g_scanner_scope_add_symbol (f->scanner, scope, s->name, s);
1602 e_sexp_add_variable (ESExp *f,
1607 struct _ESExpSymbol *s;
1609 g_return_if_fail (IS_E_SEXP (f));
1610 g_return_if_fail (name != NULL);
1612 s = g_malloc0 (sizeof (*s));
1613 s->name = g_strdup (name);
1614 s->type = ESEXP_TERM_VAR;
1616 g_scanner_scope_add_symbol (f->scanner, scope, s->name, s);
1620 e_sexp_remove_symbol (ESExp *f,
1625 struct _ESExpSymbol *s;
1627 g_return_if_fail (IS_E_SEXP (f));
1628 g_return_if_fail (name != NULL);
1630 oldscope = g_scanner_set_scope (f->scanner, scope);
1631 s = g_scanner_lookup_symbol (f->scanner, name);
1632 g_scanner_scope_remove_symbol (f->scanner, scope, name);
1633 g_scanner_set_scope (f->scanner, oldscope);
1641 e_sexp_set_scope (ESExp *f,
1644 g_return_val_if_fail (IS_E_SEXP (f), 0);
1646 return g_scanner_set_scope (f->scanner, scope);
1650 e_sexp_input_text (ESExp *f,
1654 g_return_if_fail (IS_E_SEXP (f));
1655 g_return_if_fail (text != NULL);
1657 g_scanner_input_text (f->scanner, text, len);
1661 e_sexp_input_file (ESExp *f,
1664 g_return_if_fail (IS_E_SEXP (f));
1666 g_scanner_input_file (f->scanner, fd);
1669 /* returns -1 on error */
1671 e_sexp_parse (ESExp *f)
1673 g_return_val_if_fail (IS_E_SEXP (f), -1);
1675 if (setjmp (f->failenv))
1679 parse_term_free (f, f->tree);
1681 f->tree = parse_value (f);
1686 /* returns NULL on error */
1687 struct _ESExpResult *
1688 e_sexp_eval (ESExp *f)
1690 g_return_val_if_fail (IS_E_SEXP (f), NULL);
1691 g_return_val_if_fail (f->tree != NULL, NULL);
1693 if (setjmp (f->failenv)) {
1694 g_warning ("Error in execution: %s", f->error);
1698 return e_sexp_term_eval (f, f->tree);
1702 * e_cal_backend_sexp_evaluate_occur_times:
1703 * @f: An #ESExp object.
1704 * @start: Start of the time window will be stored here.
1705 * @end: End of the time window will be stored here.
1707 * Determines biggest time window given by expressions "occur-in-range" in sexp.
1712 e_sexp_evaluate_occur_times (ESExp *f,
1716 struct _ESExpResult *r;
1718 g_return_val_if_fail (IS_E_SEXP (f), FALSE);
1719 g_return_val_if_fail (f->tree != NULL, FALSE);
1720 g_return_val_if_fail (start != NULL, FALSE);
1721 g_return_val_if_fail (end != NULL, FALSE);
1725 if (setjmp (f->failenv)) {
1726 g_warning ("Error in execution: %s", f->error);
1730 r = e_sexp_term_evaluate_occur_times (f, f->tree, start, end);
1731 generator = r->time_generator;
1734 *start = r->occuring_start;
1735 *end = r->occuring_end;
1738 e_sexp_result_free (f, r);
1744 * e_sexp_encode_bool:
1748 * Encode a bool into an s-expression @s. Bools are
1749 * encoded using #t #f syntax.
1752 e_sexp_encode_bool (GString *s,
1756 g_string_append (s, " #t");
1758 g_string_append (s, " #f");
1762 * e_sexp_encode_string:
1763 * @s: Destination string.
1764 * @string: String expression.
1766 * Add a c string @string to the s-expression stored in
1767 * the gstring @s. Quotes are added, and special characters
1768 * are escaped appropriately.
1771 e_sexp_encode_string (GString *s,
1772 const gchar *string)
1781 g_string_append (s, " \"");
1782 while ((c = *p++)) {
1783 if (c == '\\' || c == '\"' || c == '\'')
1784 g_string_append_c (s, '\\');
1785 g_string_append_c (s, c);
1787 g_string_append (s, "\"");
1791 gint main (gint argc, gchar **argv)
1794 gchar *t = "(+ \"foo\" \"\\\"\" \"bar\" \"\\\\ blah \\x \")";
1801 e_sexp_add_variable (f, 0, "test", NULL);
1803 if (argc < 2 || !argv[1])
1806 e_sexp_input_text (f, t, t);
1810 parse_dump_term (f->tree, 0);
1813 r = e_sexp_eval (f);
1815 eval_dump_result (r, 0);
1817 printf ("no result?|\n");