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.
49 Subtract integers from the first.
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.
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 * parse_list (ESExp *f, gint gotbrace);
106 static struct _ESExpTerm * parse_value (ESExp *f);
109 static void parse_dump_term (struct _ESExpTerm *t, gint depth);
112 #ifdef E_SEXP_IS_G_OBJECT
113 static GObjectClass *parent_class;
116 typedef gboolean (ESGeneratorFunc) (gint argc, struct _ESExpResult **argv, struct _ESExpResult *r);
117 typedef gboolean (ESOperatorFunc) (gint argc, struct _ESExpResult **argv, struct _ESExpResult *r);
119 /* FIXME: constant _TIME_MAX used in different files, move it somewhere */
120 #define _TIME_MAX ((time_t) INT_MAX) /* Max valid time_t */
122 static const GScannerConfig scanner_config =
124 ( (gchar *) " \t\r\n") /* cset_skip_characters */,
125 ( (gchar *) G_CSET_a_2_z
127 G_CSET_A_2_Z) /* cset_identifier_first */,
128 ( (gchar *) G_CSET_a_2_z
132 G_CSET_LATINC ) /* cset_identifier_nth */,
133 ( (gchar *) ";\n" ) /* cpair_comment_single */,
135 FALSE /* case_sensitive */,
137 TRUE /* skip_comment_multi */,
138 TRUE /* skip_comment_single */,
139 TRUE /* scan_comment_multi */,
140 TRUE /* scan_identifier */,
141 TRUE /* scan_identifier_1char */,
142 FALSE /* scan_identifier_NULL */,
143 TRUE /* scan_symbols */,
144 FALSE /* scan_binary */,
145 TRUE /* scan_octal */,
146 TRUE /* scan_float */,
148 FALSE /* scan_hex_dollar */,
149 TRUE /* scan_string_sq */,
150 TRUE /* scan_string_dq */,
151 TRUE /* numbers_2_int */,
152 FALSE /* int_2_float */,
153 FALSE /* identifier_2_string */,
154 TRUE /* char_2_token */,
155 FALSE /* symbol_2_token */,
156 FALSE /* scope_0_fallback */,
159 /* jumps back to the caller of f->failenv, only to be called from inside a callback */
161 e_sexp_fatal_error (struct _ESExp *f, const gchar *why, ...)
168 va_start (args, why);
169 f->error = g_strdup_vprintf (why, args);
172 longjmp (f->failenv, 1);
176 e_sexp_error (struct _ESExp *f)
181 struct _ESExpResult *
182 e_sexp_result_new (struct _ESExp *f, gint type)
184 struct _ESExpResult *r = e_memchunk_alloc0 (f->result_chunks);
186 r->occuring_start = 0;
187 r->occuring_end = _TIME_MAX;
188 r->time_generator = FALSE;
193 e_sexp_result_free (struct _ESExp *f, struct _ESExpResult *t)
199 case ESEXP_RES_ARRAY_PTR:
200 g_ptr_array_free (t->value.ptrarray, TRUE);
206 case ESEXP_RES_STRING:
207 g_free (t->value.string);
209 case ESEXP_RES_UNDEFINED:
212 g_assert_not_reached ();
214 e_memchunk_free (f->result_chunks, t);
217 /* used in normal functions if they have to abort, and free their arguments */
219 e_sexp_resultv_free (struct _ESExp *f, gint argc, struct _ESExpResult **argv)
223 for (i=0;i<argc;i++) {
224 e_sexp_result_free (f, argv[i]);
228 /* implementations for the builtin functions */
230 /* we can only itereate a hashtable from a called function */
236 /* ok, store any values that are in all sets */
238 htand (gchar *key, gint value, struct IterData *iter_data)
240 if (value == iter_data->count) {
241 g_ptr_array_add (iter_data->uids, key);
245 /* or, store all unique values */
247 htor (gchar *key, gint value, struct IterData *iter_data)
249 g_ptr_array_add (iter_data->uids, key);
253 term_eval_and (struct _ESExp *f, gint argc, struct _ESExpTerm **argv, gpointer data)
255 struct _ESExpResult *r, *r1;
256 GHashTable *ht = g_hash_table_new (g_str_hash, g_str_equal);
257 struct IterData lambdafoo;
263 r(printf("( and\n"));
265 r = e_sexp_result_new (f, ESEXP_RES_UNDEFINED);
268 f->operators = g_slist_prepend (f->operators, (gpointer) oper);
270 for (i=0;bool && i<argc;i++) {
271 r1 = e_sexp_term_eval (f, argv[i]);
274 if (type != r1->type) {
275 e_sexp_result_free (f, r);
276 e_sexp_result_free (f, r1);
277 g_hash_table_destroy (ht);
278 e_sexp_fatal_error(f, "Invalid types in AND");
279 } else if (r1->type == ESEXP_RES_ARRAY_PTR) {
283 a1 = (gchar **) r1->value.ptrarray->pdata;
284 l1 = r1->value.ptrarray->len;
288 ptr = g_hash_table_lookup (ht, a1[j]);
289 n = GPOINTER_TO_INT (ptr);
290 g_hash_table_insert (ht, a1[j], GINT_TO_POINTER (n+1));
292 } else if (r1->type == ESEXP_RES_BOOL) {
293 bool = bool && r1->value.boolean;
295 e_sexp_result_free (f, r1);
298 if (type == ESEXP_RES_ARRAY_PTR) {
299 lambdafoo.count = argc;
300 lambdafoo.uids = g_ptr_array_new ();
301 g_hash_table_foreach (ht, (GHFunc) htand, &lambdafoo);
302 r->type = ESEXP_RES_ARRAY_PTR;
303 r->value.ptrarray = lambdafoo.uids;
304 } else if (type == ESEXP_RES_BOOL) {
305 r->type = ESEXP_RES_BOOL;
306 r->value.boolean = bool;
309 g_hash_table_destroy (ht);
310 f->operators = g_slist_remove (f->operators, oper);
316 term_eval_or (struct _ESExp *f, gint argc, struct _ESExpTerm **argv, gpointer data)
318 struct _ESExpResult *r, *r1;
319 GHashTable *ht = g_hash_table_new (g_str_hash, g_str_equal);
320 struct IterData lambdafoo;
329 f->operators = g_slist_prepend (f->operators, (gpointer) oper);
331 r = e_sexp_result_new (f, ESEXP_RES_UNDEFINED);
333 for (i=0;!bool && i<argc;i++) {
334 r1 = e_sexp_term_eval (f, argv[i]);
337 if (r1->type != type) {
338 e_sexp_result_free (f, r);
339 e_sexp_result_free (f, r1);
340 g_hash_table_destroy (ht);
341 e_sexp_fatal_error(f, "Invalid types in OR");
342 } else if (r1->type == ESEXP_RES_ARRAY_PTR) {
346 a1 = (gchar **) r1->value.ptrarray->pdata;
347 l1 = r1->value.ptrarray->len;
349 g_hash_table_insert (ht, a1[j], (gpointer) 1);
351 } else if (r1->type == ESEXP_RES_BOOL) {
352 bool |= r1->value.boolean;
354 e_sexp_result_free (f, r1);
357 if (type == ESEXP_RES_ARRAY_PTR) {
358 lambdafoo.count = argc;
359 lambdafoo.uids = g_ptr_array_new ();
360 g_hash_table_foreach (ht, (GHFunc) htor, &lambdafoo);
361 r->type = ESEXP_RES_ARRAY_PTR;
362 r->value.ptrarray = lambdafoo.uids;
363 } else if (type == ESEXP_RES_BOOL) {
364 r->type = ESEXP_RES_BOOL;
365 r->value.boolean = bool;
367 g_hash_table_destroy (ht);
369 f->operators = g_slist_remove (f->operators, oper);
374 term_eval_not (struct _ESExp *f, gint argc, struct _ESExpResult **argv, gpointer data)
380 if (argv[0]->type == ESEXP_RES_BOOL
381 && argv[0]->value.boolean)
384 r = e_sexp_result_new (f, ESEXP_RES_BOOL);
385 r->value.boolean = res;
389 /* this should support all arguments ...? */
391 term_eval_lt (struct _ESExp *f, gint argc, struct _ESExpTerm **argv, gpointer data)
393 struct _ESExpResult *r, *r1, *r2;
395 r = e_sexp_result_new (f, ESEXP_RES_UNDEFINED);
398 r1 = e_sexp_term_eval (f, argv[0]);
399 r2 = e_sexp_term_eval (f, argv[1]);
400 if (r1->type != r2->type) {
401 e_sexp_result_free (f, r1);
402 e_sexp_result_free (f, r2);
403 e_sexp_result_free (f, r);
404 e_sexp_fatal_error(f, "Incompatible types in compare <");
405 } else if (r1->type == ESEXP_RES_INT) {
406 r->type = ESEXP_RES_BOOL;
407 r->value.boolean = r1->value.number < r2->value.number;
408 } else if (r1->type == ESEXP_RES_TIME) {
409 r->type = ESEXP_RES_BOOL;
410 r->value.boolean = r1->value.time < r2->value.time;
411 } else if (r1->type == ESEXP_RES_STRING) {
412 r->type = ESEXP_RES_BOOL;
413 r->value.boolean = strcmp (r1->value.string, r2->value.string) < 0;
415 e_sexp_result_free (f, r1);
416 e_sexp_result_free (f, r2);
421 /* this should support all arguments ...? */
423 term_eval_gt (struct _ESExp *f, gint argc, struct _ESExpTerm **argv, gpointer data)
425 struct _ESExpResult *r, *r1, *r2;
427 r = e_sexp_result_new (f, ESEXP_RES_UNDEFINED);
430 r1 = e_sexp_term_eval (f, argv[0]);
431 r2 = e_sexp_term_eval (f, argv[1]);
432 if (r1->type != r2->type) {
433 e_sexp_result_free (f, r1);
434 e_sexp_result_free (f, r2);
435 e_sexp_result_free (f, r);
436 e_sexp_fatal_error(f, "Incompatible types in compare >");
437 } else if (r1->type == ESEXP_RES_INT) {
438 r->type = ESEXP_RES_BOOL;
439 r->value.boolean = r1->value.number > r2->value.number;
440 } else if (r1->type == ESEXP_RES_TIME) {
441 r->type = ESEXP_RES_BOOL;
442 r->value.boolean = r1->value.time > r2->value.time;
443 } else if (r1->type == ESEXP_RES_STRING) {
444 r->type = ESEXP_RES_BOOL;
445 r->value.boolean = strcmp (r1->value.string, r2->value.string) > 0;
447 e_sexp_result_free (f, r1);
448 e_sexp_result_free (f, r2);
453 /* this should support all arguments ...? */
455 term_eval_eq (struct _ESExp *f, gint argc, struct _ESExpTerm **argv, gpointer data)
457 struct _ESExpResult *r, *r1, *r2;
459 r = e_sexp_result_new (f, ESEXP_RES_BOOL);
462 r1 = e_sexp_term_eval (f, argv[0]);
463 r2 = e_sexp_term_eval (f, argv[1]);
464 if (r1->type != r2->type) {
465 r->value.boolean = FALSE;
466 } else if (r1->type == ESEXP_RES_INT) {
467 r->value.boolean = r1->value.number == r2->value.number;
468 } else if (r1->type == ESEXP_RES_BOOL) {
469 r->value.boolean = r1->value.boolean == r2->value.boolean;
470 } else if (r1->type == ESEXP_RES_TIME) {
471 r->value.boolean = r1->value.time == r2->value.time;
472 } else if (r1->type == ESEXP_RES_STRING) {
473 r->value.boolean = strcmp (r1->value.string, r2->value.string) == 0;
475 e_sexp_result_free (f, r1);
476 e_sexp_result_free (f, r2);
482 term_eval_plus (struct _ESExp *f, gint argc, struct _ESExpResult **argv, gpointer data)
484 struct _ESExpResult *r=NULL;
489 type = argv[0]->type;
491 case ESEXP_RES_INT: {
492 gint total = argv[0]->value.number;
493 for (i=1;i<argc && argv[i]->type == ESEXP_RES_INT;i++) {
494 total += argv[i]->value.number;
497 e_sexp_resultv_free (f, argc, argv);
498 e_sexp_fatal_error(f, "Invalid types in (+ ints)");
500 r = e_sexp_result_new (f, ESEXP_RES_INT);
501 r->value.number = total;
503 case ESEXP_RES_STRING: {
504 GString *s = g_string_new (argv[0]->value.string);
505 for (i=1;i<argc && argv[i]->type == ESEXP_RES_STRING;i++) {
506 g_string_append (s, argv[i]->value.string);
509 e_sexp_resultv_free (f, argc, argv);
510 e_sexp_fatal_error(f, "Invalid types in (+ strings)");
512 r = e_sexp_result_new (f, ESEXP_RES_STRING);
513 r->value.string = s->str;
514 g_string_free (s, FALSE);
516 case ESEXP_RES_TIME: {
519 total = argv[0]->value.time;
521 for (i = 1; i < argc && argv[i]->type == ESEXP_RES_TIME; i++)
522 total += argv[i]->value.time;
525 e_sexp_resultv_free (f, argc, argv);
526 e_sexp_fatal_error (f, "Invalid types in (+ time_t)");
529 r = e_sexp_result_new (f, ESEXP_RES_TIME);
530 r->value.time = total;
536 r = e_sexp_result_new (f, ESEXP_RES_INT);
543 term_eval_sub (struct _ESExp *f, gint argc, struct _ESExpResult **argv, gpointer data)
545 struct _ESExpResult *r=NULL;
550 type = argv[0]->type;
552 case ESEXP_RES_INT: {
553 gint total = argv[0]->value.number;
554 for (i=1;i<argc && argv[i]->type == ESEXP_RES_INT;i++) {
555 total -= argv[i]->value.number;
558 e_sexp_resultv_free (f, argc, argv);
559 e_sexp_fatal_error(f, "Invalid types in -");
561 r = e_sexp_result_new (f, ESEXP_RES_INT);
562 r->value.number = total;
564 case ESEXP_RES_TIME: {
567 total = argv[0]->value.time;
569 for (i = 1; i < argc && argv[i]->type == ESEXP_RES_TIME; i++)
570 total -= argv[i]->value.time;
573 e_sexp_resultv_free (f, argc, argv);
574 e_sexp_fatal_error (f, "Invalid types in (- time_t)");
577 r = e_sexp_result_new (f, ESEXP_RES_TIME);
578 r->value.time = total;
584 r = e_sexp_result_new (f, ESEXP_RES_INT);
592 term_eval_castint (struct _ESExp *f, gint argc, struct _ESExpResult **argv, gpointer data)
594 struct _ESExpResult *r;
597 e_sexp_fatal_error(f, "Incorrect argument count to (gint )");
599 r = e_sexp_result_new (f, ESEXP_RES_INT);
600 switch (argv[0]->type) {
602 r->value.number = argv[0]->value.number;
605 r->value.number = argv[0]->value.boolean != 0;
607 case ESEXP_RES_STRING:
608 r->value.number = strtoul (argv[0]->value.string, NULL, 10);
611 e_sexp_result_free (f, r);
612 e_sexp_fatal_error(f, "Invalid type in (cast-int )");
620 term_eval_caststring (struct _ESExp *f, gint argc, struct _ESExpResult **argv, gpointer data)
622 struct _ESExpResult *r;
625 e_sexp_fatal_error(f, "Incorrect argument count to (cast-string )");
627 r = e_sexp_result_new (f, ESEXP_RES_STRING);
628 switch (argv[0]->type) {
630 r->value.string = g_strdup_printf("%d", argv[0]->value.number);
633 r->value.string = g_strdup_printf("%d", argv[0]->value.boolean != 0);
635 case ESEXP_RES_STRING:
636 r->value.string = g_strdup (argv[0]->value.string);
639 e_sexp_result_free (f, r);
640 e_sexp_fatal_error(f, "Invalid type in (gint )");
646 /* implements 'if' function */
648 term_eval_if (struct _ESExp *f, gint argc, struct _ESExpTerm **argv, gpointer data)
650 struct _ESExpResult *r;
653 if (argc >=2 && argc<=3) {
654 r = e_sexp_term_eval (f, argv[0]);
655 doit = (r->type == ESEXP_RES_BOOL && r->value.boolean);
656 e_sexp_result_free (f, r);
658 return e_sexp_term_eval (f, argv[1]);
660 return e_sexp_term_eval (f, argv[2]);
663 return e_sexp_result_new (f, ESEXP_RES_UNDEFINED);
666 /* implements 'begin' statement */
668 term_eval_begin (struct _ESExp *f, gint argc, struct _ESExpTerm **argv, gpointer data)
670 struct _ESExpResult *r=NULL;
673 for (i=0;i<argc;i++) {
675 e_sexp_result_free (f, r);
676 r = e_sexp_term_eval (f, argv[i]);
681 return e_sexp_result_new (f, ESEXP_RES_UNDEFINED);
684 /* this must only be called from inside term evaluation callbacks! */
685 struct _ESExpResult *
686 e_sexp_term_eval (struct _ESExp *f, struct _ESExpTerm *t)
688 struct _ESExpResult *r = NULL;
690 struct _ESExpResult **argv;
692 g_return_val_if_fail (t != NULL, NULL);
694 r(printf("eval term :\n"));
695 r (parse_dump_term (t, 0));
698 case ESEXP_TERM_STRING:
699 r(printf(" (string \"%s\")\n", t->value.string));
700 r = e_sexp_result_new (f, ESEXP_RES_STRING);
701 /* erk, this shoul;dn't need to strdup this ... */
702 r->value.string = g_strdup (t->value.string);
705 r(printf(" (gint %d)\n", t->value.number));
706 r = e_sexp_result_new (f, ESEXP_RES_INT);
707 r->value.number = t->value.number;
709 case ESEXP_TERM_BOOL:
710 r(printf(" (gint %d)\n", t->value.number));
711 r = e_sexp_result_new (f, ESEXP_RES_BOOL);
712 r->value.boolean = t->value.boolean;
714 case ESEXP_TERM_TIME:
715 r(printf(" (time_t %ld)\n", t->value.time));
716 r = e_sexp_result_new (f, ESEXP_RES_TIME);
717 r->value.time = t->value.time;
719 case ESEXP_TERM_IFUNC:
720 if (t->value.func.sym && t->value.func.sym->f.ifunc)
721 r = t->value.func.sym->f.ifunc (f, t->value.func.termcount, t->value.func.terms, t->value.func.sym->data);
723 case ESEXP_TERM_FUNC:
724 /* first evaluate all arguments to result types */
725 argv = alloca (sizeof (argv[0]) * t->value.func.termcount);
726 for (i=0;i<t->value.func.termcount;i++) {
727 argv[i] = e_sexp_term_eval (f, t->value.func.terms[i]);
729 /* call the function */
730 if (t->value.func.sym->f.func)
731 r = t->value.func.sym->f.func (f, t->value.func.termcount, argv, t->value.func.sym->data);
733 e_sexp_resultv_free (f, t->value.func.termcount, argv);
736 e_sexp_fatal_error(f, "Unknown type in parse tree: %d", t->type);
740 r = e_sexp_result_new (f, ESEXP_RES_UNDEFINED);
747 eval_dump_result (ESExpResult *r, gint depth)
752 printf("null result???\n");
756 for (i=0;i<depth;i++)
760 case ESEXP_RES_ARRAY_PTR:
761 printf("array pointers\n");
764 printf("int: %d\n", r->value.number);
766 case ESEXP_RES_STRING:
767 printf("string: '%s'\n", r->value.string);
770 printf("bool: %c\n", r->value.boolean?'t':'f');
773 printf("time_t: %ld\n", (glong) r->value.time);
775 case ESEXP_RES_UNDEFINED:
776 printf(" <undefined>\n");
785 parse_dump_term (struct _ESExpTerm *t, gint depth)
790 printf("null term??\n");
794 for (i=0;i<depth;i++)
798 case ESEXP_TERM_STRING:
799 printf(" \"%s\"", t->value.string);
802 printf(" %d", t->value.number);
804 case ESEXP_TERM_BOOL:
805 printf(" #%c", t->value.boolean?'t':'f');
807 case ESEXP_TERM_TIME:
808 printf(" %ld", (glong) t->value.time);
810 case ESEXP_TERM_IFUNC:
811 case ESEXP_TERM_FUNC:
812 printf(" (function %s\n", t->value.func.sym->name);
813 /*printf(" [%d] ", t->value.func.termcount);*/
814 for (i=0;i<t->value.func.termcount;i++) {
815 parse_dump_term (t->value.func.terms[i], depth+1);
817 for (i=0;i<depth;i++)
822 printf(" (variable %s )\n", t->value.var->name);
825 printf("unknown type: %d\n", t->type);
832 const gchar *time_functions[] = {
841 binary_generator (gint argc, struct _ESExpResult **argv, struct _ESExpResult *r)
843 g_return_val_if_fail (r != NULL, FALSE);
844 g_return_val_if_fail (argc == 2, FALSE);
846 if ((argv[0]->type != ESEXP_RES_TIME) || (argv[1]->type != ESEXP_RES_TIME))
849 r->occuring_start = argv[0]->value.time;
850 r->occuring_end = argv[1]->value.time;
856 unary_generator (gint argc, struct _ESExpResult **argv, struct _ESExpResult *r)
858 /* unary generator with end time */
859 g_return_val_if_fail (r != NULL, FALSE);
860 g_return_val_if_fail (argc == 1, FALSE);
862 if (argv[0]->type != ESEXP_RES_TIME)
865 r->occuring_start = 0;
866 r->occuring_end = argv[0]->value.time;
871 static const struct {
873 ESGeneratorFunc *func;
875 {"occur-in-time-range?", binary_generator},
876 {"due-in-time-range?", binary_generator},
877 {"has-alarms-in-range?", binary_generator},
878 {"completed-before?", unary_generator},
881 const gint generators_count = sizeof (generators) / sizeof (generators[0]);
884 or_operator (gint argc, struct _ESExpResult **argv, struct _ESExpResult *r)
891 norm (0) norm (0) norm (0)
892 gen (1) norm (0) norm (0)
893 norm (0) gen (1) norm (0)
894 gen (1) gen (1) gen*(1)
897 g_return_val_if_fail (r != NULL, FALSE);
898 g_return_val_if_fail (argc > 0, FALSE);
900 r->time_generator = TRUE;
901 for (ii = 0; ii < argc && r->time_generator; ii++) {
902 r->time_generator = argv[ii]->time_generator;
905 if (r->time_generator) {
906 r->occuring_start = argv[0]->occuring_start;
907 r->occuring_end = argv[0]->occuring_end;
909 for (ii = 1; ii < argc; ii++) {
910 r->occuring_start = MIN (r->occuring_start, argv[ii]->occuring_start);
911 r->occuring_end = MAX (r->occuring_end, argv[ii]->occuring_end);
919 and_operator (gint argc, struct _ESExpResult **argv, struct _ESExpResult *r)
926 norm (0) norm (0) norm (0)
927 gen (1) norm (0) gen (1)
928 norm (0) gen (1) gen (1)
929 gen (1) gen (1) gen (1)
932 g_return_val_if_fail (r != NULL, FALSE);
933 g_return_val_if_fail (argc > 0, FALSE);
935 r->time_generator = FALSE;
936 for (ii = 0; ii < argc && !r->time_generator; ii++) {
937 r->time_generator = argv[ii]->time_generator;
940 if (r->time_generator) {
941 r->occuring_start = argv[0]->occuring_start;
942 r->occuring_end = argv[0]->occuring_end;
944 for (ii = 1; ii < argc; ii++) {
945 r->occuring_start = MAX (r->occuring_start, argv[ii]->occuring_start);
946 r->occuring_end = MIN (r->occuring_end, argv[ii]->occuring_end);
953 static const struct {
955 ESOperatorFunc *func;
958 {"and", and_operator}
961 const gint operators_count = sizeof (operators) / sizeof (operators[0]);
963 static ESOperatorFunc*
964 get_operator_function (const gchar *fname)
968 g_return_val_if_fail (fname != NULL, NULL);
970 for (i = 0; i < sizeof (operators) / sizeof (operators[0]); i++)
971 if (strcmp (operators[i].name, fname) == 0)
972 return operators[i].func;
977 static inline gboolean
978 is_time_function (const gchar *fname)
982 g_return_val_if_fail (fname != NULL, FALSE);
984 for (i = 0; i < sizeof (time_functions) / sizeof (time_functions[0]); i++)
985 if (strcmp (time_functions[i], fname) == 0)
991 static ESGeneratorFunc*
992 get_generator_function (const gchar *fname)
996 g_return_val_if_fail (fname != NULL, NULL);
998 for (i = 0; i < sizeof (generators) / sizeof (generators[0]); i++)
999 if (strcmp (generators[i].name, fname) == 0)
1000 return generators[i].func;
1005 /* this must only be called from inside term evaluation callbacks! */
1006 static struct _ESExpResult *
1007 e_sexp_term_evaluate_occur_times (struct _ESExp *f, struct _ESExpTerm *t, time_t *start, time_t *end)
1009 struct _ESExpResult *r = NULL;
1011 struct _ESExpResult **argv;
1014 g_return_val_if_fail (t != NULL, NULL);
1015 g_return_val_if_fail (start != NULL, NULL);
1016 g_return_val_if_fail (end != NULL, NULL);
1019 printf("eval term :\n");
1020 parse_dump_term (t, 0);
1024 case ESEXP_TERM_STRING:
1025 r(printf(" (string \"%s\")\n", t->value.string));
1026 r = e_sexp_result_new (f, ESEXP_RES_STRING);
1027 r->value.string = g_strdup (t->value.string);
1029 case ESEXP_TERM_IFUNC:
1030 case ESEXP_TERM_FUNC:
1032 ESGeneratorFunc *generator = NULL;
1033 ESOperatorFunc *operator = NULL;
1035 r(printf(" (function \"%s\"\n", t->value.func.sym->name));
1037 r = e_sexp_result_new (f, ESEXP_RES_UNDEFINED);
1038 argc = t->value.func.termcount;
1039 argv = alloca (sizeof (argv[0]) * argc);
1041 for (i=0;i<t->value.func.termcount;i++) {
1042 argv[i] = e_sexp_term_evaluate_occur_times (f, t->value.func.terms[i],
1046 if (is_time_function (t->value.func.sym->name)) {
1048 if (t->value.func.sym->f.func)
1049 r = t->value.func.sym->f.func (f, t->value.func.termcount,
1050 argv, t->value.func.sym->data);
1051 } else if ((generator = get_generator_function (t->value.func.sym->name)) != NULL) {
1052 /* evaluate generator function */
1053 r->time_generator = TRUE;
1054 ok = generator (argc, argv, r);
1055 } else if ((operator = get_operator_function (t->value.func.sym->name)) != NULL)
1056 /* evaluate operator function */
1057 ok = operator (argc, argv, r);
1059 /* normal function: we need to scan all objects */
1060 r->time_generator = FALSE;
1063 e_sexp_resultv_free (f, t->value.func.termcount, argv);
1066 case ESEXP_TERM_INT:
1067 case ESEXP_TERM_BOOL:
1068 case ESEXP_TERM_TIME:
1076 e_sexp_fatal_error(f, "Error in parse tree");
1079 r = e_sexp_result_new (f, ESEXP_RES_UNDEFINED);
1088 static struct _ESExpTerm *
1089 parse_term_new (struct _ESExp *f, gint type)
1091 struct _ESExpTerm *s = e_memchunk_alloc0 (f->term_chunks);
1097 parse_term_free (struct _ESExp *f, struct _ESExpTerm *t)
1106 case ESEXP_TERM_INT:
1107 case ESEXP_TERM_BOOL:
1108 case ESEXP_TERM_TIME:
1109 case ESEXP_TERM_VAR:
1112 case ESEXP_TERM_STRING:
1113 g_free (t->value.string);
1116 case ESEXP_TERM_FUNC:
1117 case ESEXP_TERM_IFUNC:
1118 for (i=0;i<t->value.func.termcount;i++) {
1119 parse_term_free (f, t->value.func.terms[i]);
1121 g_free (t->value.func.terms);
1125 printf("parse_term_free: unknown type: %d\n", t->type);
1127 e_memchunk_free (f->term_chunks, t);
1130 static struct _ESExpTerm **
1131 parse_values (ESExp *f, gint *len)
1134 struct _ESExpTerm **terms;
1136 GScanner *gs = f->scanner;
1137 GSList *list = NULL, *l;
1139 p(printf("parsing values\n"));
1141 while ( (token = g_scanner_peek_next_token (gs)) != G_TOKEN_EOF
1143 list = g_slist_prepend (list, parse_value (f));
1147 /* go over the list, and put them backwards into the term array */
1148 terms = g_malloc (size * sizeof (*terms));
1150 for (i=size-1;i>=0;i--) {
1154 l = g_slist_next (l);
1156 g_slist_free (list);
1158 p(printf("found %d subterms\n", size));
1161 p(printf("done parsing values\n"));
1166 * e_sexp_parse_value:
1171 e_sexp_parse_value (ESExp *f)
1173 return parse_value (f);
1176 static struct _ESExpTerm *
1177 parse_value (ESExp *f)
1179 gint token, negative = FALSE;
1180 struct _ESExpTerm *t = NULL;
1181 GScanner *gs = f->scanner;
1182 struct _ESExpSymbol *s;
1184 p(printf("parsing value\n"));
1186 token = g_scanner_get_next_token (gs);
1190 case G_TOKEN_LEFT_PAREN:
1191 p(printf("got brace, its a list!\n"));
1192 return parse_list (f, TRUE);
1193 case G_TOKEN_STRING:
1194 p(printf("got string '%s'\n", g_scanner_cur_value(gs).v_string));
1195 t = parse_term_new (f, ESEXP_TERM_STRING);
1196 t->value.string = g_strdup (g_scanner_cur_value (gs).v_string);
1199 p(printf ("got negative int?\n"));
1200 token = g_scanner_get_next_token (gs);
1201 if (token != G_TOKEN_INT) {
1202 e_sexp_fatal_error (f, "Invalid format for a integer value");
1207 /* fall through... */
1209 t = parse_term_new (f, ESEXP_TERM_INT);
1210 t->value.number = g_scanner_cur_value (gs).v_int;
1212 t->value.number = -t->value.number;
1213 p(printf("got gint %d\n", t->value.number));
1218 p(printf("got bool?\n"));
1219 token = g_scanner_get_next_token (gs);
1220 if (token != G_TOKEN_IDENTIFIER) {
1221 e_sexp_fatal_error (f, "Invalid format for a boolean value");
1225 str = g_scanner_cur_value (gs).v_identifier;
1227 g_assert (str != NULL);
1228 if (!(strlen (str) == 1 && (str[0] == 't' || str[0] == 'f'))) {
1229 e_sexp_fatal_error (f, "Invalid format for a boolean value");
1233 t = parse_term_new (f, ESEXP_TERM_BOOL);
1234 t->value.boolean = (str[0] == 't');
1236 case G_TOKEN_SYMBOL:
1237 s = g_scanner_cur_value (gs).v_symbol;
1238 p(printf("got symbol '%s'\n", s->name));
1240 case ESEXP_TERM_FUNC:
1241 case ESEXP_TERM_IFUNC:
1242 /* this is basically invalid, since we can't use function
1243 pointers, but let the runtime catch it ... */
1244 t = parse_term_new (f, s->type);
1245 t->value.func.sym = s;
1246 t->value.func.terms = parse_values (f, &t->value.func.termcount);
1248 case ESEXP_TERM_VAR:
1249 t = parse_term_new (f, s->type);
1253 e_sexp_fatal_error(f, "Invalid symbol type: %s: %d", s->name, s->type);
1256 case G_TOKEN_IDENTIFIER:
1257 p(printf("got unknown identifider '%s'\n", g_scanner_cur_value(gs).v_identifier));
1258 e_sexp_fatal_error(f, "Unknown identifier: %s", g_scanner_cur_value(gs).v_identifier);
1261 e_sexp_fatal_error(f, "Unexpected token encountered: %d", token);
1263 p(printf("done parsing value\n"));
1267 /* FIXME: this needs some robustification */
1268 static struct _ESExpTerm *
1269 parse_list (ESExp *f, gint gotbrace)
1272 struct _ESExpTerm *t = NULL;
1273 GScanner *gs = f->scanner;
1275 p(printf("parsing list\n"));
1279 token = g_scanner_get_next_token (gs);
1281 token = g_scanner_get_next_token (gs);
1283 case G_TOKEN_SYMBOL: {
1284 struct _ESExpSymbol *s;
1286 s = g_scanner_cur_value (gs).v_symbol;
1287 p(printf("got funciton: %s\n", s->name));
1288 t = parse_term_new (f, s->type);
1289 p(printf("created new list %p\n", t));
1290 /* if we have a variable, find out its base type */
1291 while (s->type == ESEXP_TERM_VAR) {
1292 s = ((ESExpTerm *)(s->data))->value.var;
1294 if (s->type == ESEXP_TERM_FUNC
1295 || s->type == ESEXP_TERM_IFUNC) {
1296 t->value.func.sym = s;
1297 t->value.func.terms = parse_values (f, &t->value.func.termcount);
1299 parse_term_free (f, t);
1300 e_sexp_fatal_error(f, "Trying to call variable as function: %s", s->name);
1303 case G_TOKEN_IDENTIFIER:
1304 e_sexp_fatal_error(f, "Unknown identifier: %s", g_scanner_cur_value(gs).v_identifier);
1306 case G_TOKEN_LEFT_PAREN:
1307 return parse_list (f, TRUE);
1309 e_sexp_fatal_error(f, "Unexpected token encountered: %d", token);
1311 token = g_scanner_get_next_token (gs);
1313 e_sexp_fatal_error(f, "Missing ')'");
1316 e_sexp_fatal_error(f, "Missing '('");
1319 p(printf("returning list %p\n", t));
1323 static void e_sexp_finalise (gpointer);
1325 #ifdef E_SEXP_IS_G_OBJECT
1327 e_sexp_class_init (ESExpClass *klass)
1329 GObjectClass *object_class = G_OBJECT_CLASS (klass);
1331 object_class->finalize = e_sexp_finalise;
1333 parent_class = g_type_class_ref (g_object_get_type ());
1337 /* 'builtin' functions */
1338 static const struct {
1341 gint type; /* set to 1 if a function can perform shortcut evaluation, or
1342 doesn't execute everything, 0 otherwise */
1344 { "and", (ESExpFunc *)term_eval_and, 1 },
1345 { "or", (ESExpFunc *)term_eval_or, 1 },
1346 { "not", (ESExpFunc *)term_eval_not, 0 },
1347 { "<", (ESExpFunc *)term_eval_lt, 1 },
1348 { ">", (ESExpFunc *)term_eval_gt, 1 },
1349 { "=", (ESExpFunc *)term_eval_eq, 1 },
1350 { "+", (ESExpFunc *)term_eval_plus, 0 },
1351 { "-", (ESExpFunc *)term_eval_sub, 0 },
1352 { "cast-int", (ESExpFunc *)term_eval_castint, 0 },
1353 { "cast-string", (ESExpFunc *)term_eval_caststring, 0 },
1354 { "if", (ESExpFunc *)term_eval_if, 1 },
1355 { "begin", (ESExpFunc *)term_eval_begin, 1 },
1359 free_symbol (gpointer key, gpointer value, gpointer data)
1361 struct _ESExpSymbol *s = value;
1368 e_sexp_finalise (gpointer o)
1370 ESExp *s = (ESExp *) o;
1373 parse_term_free (s, s->tree);
1377 e_memchunk_destroy (s->term_chunks);
1378 e_memchunk_destroy (s->result_chunks);
1380 g_scanner_scope_foreach_symbol (s->scanner, 0, free_symbol, NULL);
1381 g_scanner_destroy (s->scanner);
1383 #ifdef E_SEXP_IS_G_OBJECT
1384 G_OBJECT_CLASS (parent_class)->finalize (o);
1389 e_sexp_init (ESExp *s)
1393 s->scanner = g_scanner_new (&scanner_config);
1394 s->term_chunks = e_memchunk_new (16, sizeof (struct _ESExpTerm));
1395 s->result_chunks = e_memchunk_new (16, sizeof (struct _ESExpResult));
1397 /* load in builtin symbols? */
1398 for (i = 0; i < G_N_ELEMENTS (symbols); i++) {
1399 if (symbols[i].type == 1) {
1400 e_sexp_add_ifunction (s, 0, symbols[i].name, (ESExpIFunc *) symbols[i].func, (gpointer)&symbols[i]);
1402 e_sexp_add_function (s, 0, symbols[i].name, symbols[i].func, (gpointer)&symbols[i]);
1406 #ifndef E_SEXP_IS_G_OBJECT
1414 #ifdef E_SEXP_IS_G_OBJECT
1415 ESExp *f = (ESexp *) g_object_new (E_TYPE_SEXP, NULL);
1417 ESExp *f = g_malloc0 (sizeof (ESExp));
1424 #ifndef E_SEXP_IS_G_OBJECT
1426 e_sexp_ref (ESExp *f)
1432 e_sexp_unref (ESExp *f)
1435 if (f->refcount == 0) {
1436 e_sexp_finalise (f);
1443 e_sexp_add_function (ESExp *f, gint scope, const gchar *name, ESExpFunc *func, gpointer data)
1445 struct _ESExpSymbol *s;
1447 g_return_if_fail (IS_E_SEXP (f));
1448 g_return_if_fail (name != NULL);
1450 e_sexp_remove_symbol (f, scope, name);
1452 s = g_malloc0 (sizeof (*s));
1453 s->name = g_strdup (name);
1455 s->type = ESEXP_TERM_FUNC;
1457 g_scanner_scope_add_symbol (f->scanner, scope, s->name, s);
1461 e_sexp_add_ifunction (ESExp *f, gint scope, const gchar *name, ESExpIFunc *ifunc, gpointer data)
1463 struct _ESExpSymbol *s;
1465 g_return_if_fail (IS_E_SEXP (f));
1466 g_return_if_fail (name != NULL);
1468 e_sexp_remove_symbol (f, scope, name);
1470 s = g_malloc0 (sizeof (*s));
1471 s->name = g_strdup (name);
1473 s->type = ESEXP_TERM_IFUNC;
1475 g_scanner_scope_add_symbol (f->scanner, scope, s->name, s);
1479 e_sexp_add_variable (ESExp *f, gint scope, gchar *name, ESExpTerm *value)
1481 struct _ESExpSymbol *s;
1483 g_return_if_fail (IS_E_SEXP (f));
1484 g_return_if_fail (name != NULL);
1486 s = g_malloc0 (sizeof (*s));
1487 s->name = g_strdup (name);
1488 s->type = ESEXP_TERM_VAR;
1490 g_scanner_scope_add_symbol (f->scanner, scope, s->name, s);
1494 e_sexp_remove_symbol (ESExp *f, gint scope, const gchar *name)
1497 struct _ESExpSymbol *s;
1499 g_return_if_fail (IS_E_SEXP (f));
1500 g_return_if_fail (name != NULL);
1502 oldscope = g_scanner_set_scope (f->scanner, scope);
1503 s = g_scanner_lookup_symbol (f->scanner, name);
1504 g_scanner_scope_remove_symbol (f->scanner, scope, name);
1505 g_scanner_set_scope (f->scanner, oldscope);
1513 e_sexp_set_scope (ESExp *f, gint scope)
1515 g_return_val_if_fail (IS_E_SEXP (f), 0);
1517 return g_scanner_set_scope (f->scanner, scope);
1521 e_sexp_input_text (ESExp *f, const gchar *text, gint len)
1523 g_return_if_fail (IS_E_SEXP (f));
1524 g_return_if_fail (text != NULL);
1526 g_scanner_input_text (f->scanner, text, len);
1530 e_sexp_input_file (ESExp *f, gint fd)
1532 g_return_if_fail (IS_E_SEXP (f));
1534 g_scanner_input_file (f->scanner, fd);
1537 /* returns -1 on error */
1539 e_sexp_parse (ESExp *f)
1541 g_return_val_if_fail (IS_E_SEXP (f), -1);
1543 if (setjmp (f->failenv)) {
1544 g_warning("Error in parsing: %s", f->error);
1549 parse_term_free (f, f->tree);
1551 f->tree = parse_value (f);
1556 /* returns NULL on error */
1557 struct _ESExpResult *
1558 e_sexp_eval (ESExp *f)
1560 g_return_val_if_fail (IS_E_SEXP (f), NULL);
1561 g_return_val_if_fail (f->tree != NULL, NULL);
1563 if (setjmp (f->failenv)) {
1564 g_warning("Error in execution: %s", f->error);
1568 return e_sexp_term_eval (f, f->tree);
1572 * e_cal_backend_sexp_evaluate_occur_times:
1573 * @f: An #ESExp object.
1574 * @start: Start of the time window will be stored here.
1575 * @end: End of the time window will be stored here.
1577 * Determines biggest time window given by expressions "occur-in-range" in sexp.
1582 e_sexp_evaluate_occur_times (ESExp *f, time_t *start, time_t *end)
1584 struct _ESExpResult *r;
1586 g_return_val_if_fail (IS_E_SEXP (f), FALSE);
1587 g_return_val_if_fail (f->tree != NULL, FALSE);
1588 g_return_val_if_fail (start != NULL, FALSE);
1589 g_return_val_if_fail (end != NULL, FALSE);
1593 if (setjmp (f->failenv)) {
1594 g_warning("Error in execution: %s", f->error);
1598 r = e_sexp_term_evaluate_occur_times (f, f->tree, start, end);
1599 generator = r->time_generator;
1602 *start = r->occuring_start;
1603 *end = r->occuring_end;
1606 e_sexp_result_free (f, r);
1612 * e_sexp_encode_bool:
1616 * Encode a bool into an s-expression @s. Bools are
1617 * encoded using #t #f syntax.
1620 e_sexp_encode_bool (GString *s, gboolean state)
1623 g_string_append(s, " #t");
1625 g_string_append(s, " #f");
1629 * e_sexp_encode_string:
1630 * @s: Destination string.
1631 * @string: String expression.
1633 * Add a c string @string to the s-expression stored in
1634 * the gstring @s. Quotes are added, and special characters
1635 * are escaped appropriately.
1638 e_sexp_encode_string (GString *s, const gchar *string)
1647 g_string_append(s, " \"");
1648 while ((c = *p++)) {
1649 if (c=='\\' || c=='\"' || c=='\'')
1650 g_string_append_c (s, '\\');
1651 g_string_append_c (s, c);
1653 g_string_append(s, "\"");
1657 gint main (gint argc, gchar **argv)
1660 gchar *t = "(+ \"foo\" \"\\\"\" \"bar\" \"\\\\ blah \\x \")";
1667 e_sexp_add_variable(f, 0, "test", NULL);
1669 if (argc < 2 || !argv[1])
1672 e_sexp_input_text (f, t, t);
1676 parse_dump_term (f->tree, 0);
1679 r = e_sexp_eval (f);
1681 eval_dump_result (r, 0);
1683 printf("no result?|\n");