1 /*
2  * This library is free software: you can redistribute it and/or modify it
3  * under the terms of the GNU Lesser General Public License as published by
4  * the Free Software Foundation.
5  *
6  * This library is distributed in the hope that it will be useful, but
7  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
8  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
9  * for more details.
10  *
11  * You should have received a copy of the GNU Lesser General Public License
12  * along with this library. If not, see <http://www.gnu.org/licenses/>.
13  *
14  */
15 
16 #if !defined (__CAMEL_H_INSIDE__) && !defined (CAMEL_COMPILATION)
17 #error "Only <camel/camel.h> can be included directly."
18 #endif
19 
20 #ifndef CAMEL_SEXP_H
21 #define CAMEL_SEXP_H
22 
23 #include <setjmp.h>
24 #include <time.h>
25 #include <glib.h>
26 
27 #include <glib-object.h>
28 
29 #include <camel/camel-memchunk.h>
30 
31 /* Standard GObject macros */
32 #define CAMEL_TYPE_SEXP \
33 	(camel_sexp_get_type ())
34 #define CAMEL_SEXP(obj) \
35 	(G_TYPE_CHECK_INSTANCE_CAST \
36 	((obj), CAMEL_TYPE_SEXP, CamelSExp))
37 #define CAMEL_SEXP_CLASS(cls) \
38 	(G_TYPE_CHECK_CLASS_CAST \
39 	((cls), CAMEL_TYPE_SEXP, CamelSExpClass))
40 #define CAMEL_IS_SEXP(obj) \
41 	(G_TYPE_CHECK_INSTANCE_TYPE \
42 	((obj), CAMEL_TYPE_SEXP))
43 #define CAMEL_IS_SEXP_CLASS(cls) \
44 	(G_TYPE_CHECK_CLASS_TYPE \
45 	((cls), CAMEL_TYPE_SEXP))
46 #define CAMEL_SEXP_GET_CLASS(obj) \
47 	(G_TYPE_INSTANCE_GET_CLASS \
48 	((obj), CAMEL_TYPE_SEXP, CamelSExpClass))
49 
50 G_BEGIN_DECLS
51 
52 typedef struct _CamelSExp CamelSExp;
53 typedef struct _CamelSExpClass CamelSExpClass;
54 typedef struct _CamelSExpPrivate CamelSExpPrivate;
55 
56 typedef struct _CamelSExpSymbol CamelSExpSymbol;
57 typedef struct _CamelSExpResult CamelSExpResult;
58 typedef struct _CamelSExpTerm CamelSExpTerm;
59 
60 /**
61  * CamelSExpResultType:
62  * @CAMEL_SEXP_RES_ARRAY_PTR: type is a ptrarray, what it points to is implementation dependant
63  * @CAMEL_SEXP_RES_INT: type is a number
64  * @CAMEL_SEXP_RES_STRING: type is a pointer to a single string
65  * @CAMEL_SEXP_RES_BOOL: boolean type
66  * @CAMEL_SEXP_RES_TIME: time_t type
67  * @CAMEL_SEXP_RES_UNDEFINED: unknown type
68  *
69  * Defines type of a #CamelSExpResult.
70  *
71  * Since: 3.4
72  **/
73 typedef enum {
74 	CAMEL_SEXP_RES_ARRAY_PTR,	/* type is a ptrarray, what it points to is implementation dependant */
75 	CAMEL_SEXP_RES_INT,		/* type is a number */
76 	CAMEL_SEXP_RES_STRING,		/* type is a pointer to a single string */
77 	CAMEL_SEXP_RES_BOOL,		/* boolean type */
78 	CAMEL_SEXP_RES_TIME,		/* time_t type */
79 	CAMEL_SEXP_RES_UNDEFINED	/* unknown type */
80 } CamelSExpResultType;
81 
82 /**
83  * CamelSExpResult:
84  * @type: a #CamelSExpResultType, defining the @value type
85  * @value: a union with the actual value
86  * @time_generator: a boolean whether the occuring times are used
87  * @occuring_start: start time
88  * @occuring_end: end time
89  *
90  * Since: 3.4
91  **/
92 struct _CamelSExpResult {
93 	CamelSExpResultType type;
94 	union {
95 		GPtrArray *ptrarray;
96 		gint number;
97 		gchar *string;
98 		gint boolean;
99 		time_t time;
100 	} value;
101 	gboolean time_generator;
102 	time_t occuring_start;
103 	time_t occuring_end;
104 };
105 
106 /**
107  * CamelSExpFunc:
108  * @sexp: a #CamelSExp
109  * @argc: count of arguments
110  * @argv: (in) (array length=argc): array of values of the arguments
111  * @user_data: user data as passed to camel_sexp_add_function()
112  *
113  * Callback type for function symbols used with camel_sexp_add_function().
114  *
115  * Returns: Result of the function call, allocated by camel_sexp_result_new().
116  *
117  * Since: 3.4
118  **/
119 typedef CamelSExpResult *
120 			(*CamelSExpFunc)	(CamelSExp *sexp,
121 						 gint argc,
122 						 CamelSExpResult **argv,
123 						 gpointer user_data);
124 
125 /**
126  * CamelSExpIFunc:
127  * @sexp: a #CamelSExp
128  * @argc: count of arguments
129  * @argv: (in) (array length=argc): array of values of the arguments
130  * @user_data: user data as passed to camel_sexp_add_ifunction()
131  *
132  * Callback type for function symbols used with camel_sexp_add_ifunction().
133  *
134  * Returns: Result of the function call, allocated by camel_sexp_result_new().
135  *
136  * Since: 3.4
137  **/
138 typedef CamelSExpResult *
139 			(*CamelSExpIFunc)	(CamelSExp *sexp,
140 						 gint argc,
141 						 CamelSExpTerm **argv,
142 						 gpointer user_data);
143 
144 /**
145  * CamelSExpTermType:
146  * @CAMEL_SEXP_TERM_INT: integer literal
147  * @CAMEL_SEXP_TERM_BOOL: boolean literal
148  * @CAMEL_SEXP_TERM_STRING: string literal
149  * @CAMEL_SEXP_TERM_TIME: time_t literal (number of seconds past the epoch)
150  * @CAMEL_SEXP_TERM_FUNC: normal function, arguments are evaluated before calling
151  * @CAMEL_SEXP_TERM_IFUNC: immediate function, raw terms are arguments
152  * @CAMEL_SEXP_TERM_VAR: variable reference
153  *
154  * Defines type of a #CamelSExpTerm and partly also #CamelSExpSymbol
155  *
156  * Since: 3.4
157  **/
158 typedef enum {
159 	CAMEL_SEXP_TERM_INT,	/* integer literal */
160 	CAMEL_SEXP_TERM_BOOL,	/* boolean literal */
161 	CAMEL_SEXP_TERM_STRING,	/* string literal */
162 	CAMEL_SEXP_TERM_TIME,	/* time_t literal (number of seconds past the epoch) */
163 	CAMEL_SEXP_TERM_FUNC,	/* normal function, arguments are evaluated before calling */
164 	CAMEL_SEXP_TERM_IFUNC,	/* immediate function, raw terms are arguments */
165 	CAMEL_SEXP_TERM_VAR	/* variable reference */
166 } CamelSExpTermType;
167 
168 /**
169  * CamelSExpSymbol:
170  * @type: a type of the symbol, either CAMEL_SEXP_TERM_FUNC or CAMEL_SEXP_TERM_VAR
171  * @name: name of the symbol
172  * @data: user data for the callback
173  * @f.func: a #CamelSExpFunc callback
174  * @f.ifunc: a #CamelSExpIFunc callback
175  *
176  * Describes a function or a variable symbol
177  *
178  * Since: 3.4
179  **/
180 struct _CamelSExpSymbol {
181 	gint type;		/* TERM_FUNC or TERM_VAR */
182 	gchar *name;
183 	gpointer data;
184 	union {
185 		CamelSExpFunc func;
186 		CamelSExpIFunc ifunc;
187 	} f;
188 };
189 
190 /**
191  * CamelSExpTerm:
192  * @type: a type of the term; one of #CamelSExpTermType
193  * @value: value of the term
194  *
195  * Since: 3.4
196  **/
197 struct _CamelSExpTerm {
198 	CamelSExpTermType type;
199 	union {
200 		gchar *string;
201 		gint number;
202 		gint boolean;
203 		time_t time;
204 		struct {
205 			CamelSExpSymbol *sym;
206 			CamelSExpTerm **terms;
207 			gint termcount;
208 		} func;
209 		CamelSExpSymbol *var;
210 	} value;
211 };
212 
213 /**
214  * CamelSExp:
215  *
216  * Since: 3.4
217  **/
218 struct _CamelSExp {
219 	/*< private >*/
220 	GObject parent;
221 	CamelSExpPrivate *priv;
222 };
223 
224 struct _CamelSExpClass {
225 	GObjectClass parent_class;
226 
227 	/* Padding for future expansion */
228 	gpointer reserved[20];
229 };
230 
231 GType		camel_sexp_get_type		(void) G_GNUC_CONST;
232 CamelSExp *	camel_sexp_new			(void);
233 void		camel_sexp_add_function		(CamelSExp *sexp,
234 						 guint scope,
235 						 const gchar *name,
236 						 CamelSExpFunc func,
237 						 gpointer user_data);
238 void		camel_sexp_add_ifunction	(CamelSExp *sexp,
239 						 guint scope,
240 						 const gchar *name,
241 						 CamelSExpIFunc ifunc,
242 						 gpointer user_data);
243 void		camel_sexp_add_variable		(CamelSExp *sexp,
244 						 guint scope,
245 						 const gchar *name,
246 						 CamelSExpTerm *value);
247 void		camel_sexp_remove_symbol	(CamelSExp *sexp,
248 						 guint scope,
249 						 const gchar *name);
250 gint		camel_sexp_set_scope		(CamelSExp *sexp,
251 						 guint scope);
252 void		camel_sexp_input_text		(CamelSExp *sexp,
253 						 const gchar *text,
254 						 gint len);
255 void		camel_sexp_input_file		(CamelSExp *sexp,
256 						 gint fd);
257 gint		camel_sexp_parse		(CamelSExp *sexp);
258 CamelSExpResult *
259 		camel_sexp_eval			(CamelSExp *sexp);
260 CamelSExpResult *
261 		camel_sexp_term_eval		(CamelSExp *sexp,
262 						 CamelSExpTerm *term);
263 CamelSExpResult *
264 		camel_sexp_result_new		(CamelSExp *sexp,
265 						 gint type);
266 void		camel_sexp_result_free		(CamelSExp *sexp,
267 						 CamelSExpResult *result);
268 
269 /* used in normal functions if they have to abort, to free their arguments */
270 void		camel_sexp_resultv_free		(CamelSExp *sexp,
271 						 gint argc,
272 						 CamelSExpResult **argv);
273 
274 /* utility functions for creating s-exp strings. */
275 void		camel_sexp_encode_bool		(GString *string,
276 						 gboolean v_bool);
277 void		camel_sexp_encode_string	(GString *string,
278 						 const gchar *v_string);
279 
280 /* only to be called from inside a callback to signal a fatal execution error */
281 void		camel_sexp_fatal_error		(CamelSExp *sexp,
282 						 const gchar *why,
283 						 ...) G_GNUC_NORETURN;
284 
285 /* return the error string */
286 const gchar *	camel_sexp_error		(CamelSExp *sexp);
287 
288 CamelSExpTerm *	camel_sexp_parse_value		(CamelSExp *sexp);
289 
290 gboolean	camel_sexp_evaluate_occur_times	(CamelSExp *sexp,
291 						 time_t *start,
292 						 time_t *end);
293 
294 G_END_DECLS
295 
296 #endif /* CAMEL_SEXP_H */
297