iscc: add "source" operation
[barvinok.git] / iscc.c
blob6fd09cc97e3f642ea4da6cae1c5a8a05dca839f0
1 #include <assert.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <isl_obj.h>
5 #include <isl_stream.h>
6 #include <isl_vertices.h>
7 #include <isl_obj_list.h>
8 #include <isl_obj_str.h>
9 #include <barvinok/barvinok.h>
11 #include "config.h"
13 #ifdef HAVE_CLOOG
14 #include <cloog/isl/cloog.h>
15 #endif
17 static int isl_bool_false = 0;
18 static int isl_bool_true = 1;
19 static int isl_bool_error = -1;
21 static enum isl_token_type read_op;
22 static enum isl_token_type source_op;
23 static enum isl_token_type vertices_op;
25 struct isl_arg_choice iscc_format[] = {
26 {"isl", ISL_FORMAT_ISL},
27 {"omega", ISL_FORMAT_OMEGA},
28 {"polylib", ISL_FORMAT_POLYLIB},
29 {"latex", ISL_FORMAT_LATEX},
30 {"C", ISL_FORMAT_C},
31 {0}
34 struct iscc_options {
35 struct barvinok_options *barvinok;
36 unsigned format;
39 struct isl_arg iscc_options_arg[] = {
40 ISL_ARG_CHILD(struct iscc_options, barvinok, "barvinok", barvinok_options_arg,
41 "barvinok options")
42 ISL_ARG_CHOICE(struct iscc_options, format, 0, "format", \
43 iscc_format, ISL_FORMAT_ISL, "output format")
44 ISL_ARG_END
47 ISL_ARG_DEF(iscc_options, struct iscc_options, iscc_options_arg)
49 static void *isl_obj_bool_copy(void *v)
51 return v;
54 static void isl_obj_bool_free(void *v)
58 static __isl_give isl_printer *isl_obj_bool_print(__isl_take isl_printer *p,
59 void *v)
61 if (v == &isl_bool_true)
62 return isl_printer_print_str(p, "True");
63 else if (v == &isl_bool_false)
64 return isl_printer_print_str(p, "False");
65 else
66 return isl_printer_print_str(p, "Error");
69 static void *isl_obj_bool_add(void *v1, void *v2)
71 return v1;
74 struct isl_obj_vtable isl_obj_bool_vtable = {
75 isl_obj_bool_copy,
76 isl_obj_bool_add,
77 isl_obj_bool_print,
78 isl_obj_bool_free
80 #define isl_obj_bool (&isl_obj_bool_vtable)
82 int *isl_bool_from_int(int res)
84 return res < 0 ? &isl_bool_error : res ? &isl_bool_true : &isl_bool_false;
87 int *union_map_is_equal(__isl_take isl_union_map *map1,
88 __isl_take isl_union_map *map2)
90 int res = isl_union_map_is_equal(map1, map2);
91 isl_union_map_free(map1);
92 isl_union_map_free(map2);
93 return isl_bool_from_int(res);
95 int *union_set_is_equal(__isl_take isl_union_set *set1,
96 __isl_take isl_union_set *set2)
98 return union_map_is_equal((isl_union_map *)set1, (isl_union_map *)set2);
101 int *union_map_is_subset(__isl_take isl_union_map *map1,
102 __isl_take isl_union_map *map2)
104 int res = isl_union_map_is_subset(map1, map2);
105 isl_union_map_free(map1);
106 isl_union_map_free(map2);
107 return isl_bool_from_int(res);
109 int *union_set_is_subset(__isl_take isl_union_set *set1,
110 __isl_take isl_union_set *set2)
112 return union_map_is_subset((isl_union_map *)set1, (isl_union_map *)set2);
115 int *union_map_is_strict_subset(__isl_take isl_union_map *map1,
116 __isl_take isl_union_map *map2)
118 int res = isl_union_map_is_strict_subset(map1, map2);
119 isl_union_map_free(map1);
120 isl_union_map_free(map2);
121 return isl_bool_from_int(res);
123 int *union_set_is_strict_subset(__isl_take isl_union_set *set1,
124 __isl_take isl_union_set *set2)
126 return union_map_is_strict_subset((isl_union_map *)set1,
127 (isl_union_map *)set2);
130 int *union_map_is_superset(__isl_take isl_union_map *map1,
131 __isl_take isl_union_map *map2)
133 return union_map_is_subset(map2, map1);
135 int *union_set_is_superset(__isl_take isl_union_set *set1,
136 __isl_take isl_union_set *set2)
138 return union_set_is_subset(set2, set1);
141 int *union_map_is_strict_superset(__isl_take isl_union_map *map1,
142 __isl_take isl_union_map *map2)
144 return union_map_is_strict_subset(map2, map1);
146 int *union_set_is_strict_superset(__isl_take isl_union_set *set1,
147 __isl_take isl_union_set *set2)
149 return union_set_is_strict_subset(set2, set1);
152 extern struct isl_obj_vtable isl_obj_list_vtable;
153 #define isl_obj_list (&isl_obj_list_vtable)
155 typedef void *(*isc_bin_op_fn)(void *lhs, void *rhs);
156 struct isc_bin_op {
157 enum isl_token_type op;
158 isl_obj_type lhs;
159 isl_obj_type rhs;
160 isl_obj_type res;
161 isc_bin_op_fn fn;
163 struct isc_named_bin_op {
164 char *name;
165 struct isc_bin_op op;
168 struct iscc_at {
169 isl_union_pw_qpolynomial *upwqp;
170 isl_union_pw_qpolynomial *res;
173 static int eval_at(__isl_take isl_point *pnt, void *user)
175 struct iscc_at *at = (struct iscc_at *) user;
176 isl_qpolynomial *qp;
177 isl_set *set;
179 set = isl_set_from_point(isl_point_copy(pnt));
180 qp = isl_union_pw_qpolynomial_eval(
181 isl_union_pw_qpolynomial_copy(at->upwqp), pnt);
183 at->res = isl_union_pw_qpolynomial_add(at->res,
184 isl_union_pw_qpolynomial_from_pw_qpolynomial(
185 isl_pw_qpolynomial_alloc(set, qp)));
187 return 0;
190 __isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_at(
191 __isl_take isl_union_pw_qpolynomial *upwqp,
192 __isl_take isl_union_set *uset)
194 struct iscc_at at;
196 at.upwqp = upwqp;
197 at.res = isl_union_pw_qpolynomial_zero(isl_union_set_get_dim(uset));
199 isl_union_set_foreach_point(uset, eval_at, &at);
201 isl_union_pw_qpolynomial_free(upwqp);
202 isl_union_set_free(uset);
204 return at.res;
207 struct iscc_fold_at {
208 isl_union_pw_qpolynomial_fold *upwf;
209 isl_union_pw_qpolynomial *res;
212 static int eval_fold_at(__isl_take isl_point *pnt, void *user)
214 struct iscc_fold_at *at = (struct iscc_fold_at *) user;
215 isl_qpolynomial *qp;
216 isl_set *set;
218 set = isl_set_from_point(isl_point_copy(pnt));
219 qp = isl_union_pw_qpolynomial_fold_eval(
220 isl_union_pw_qpolynomial_fold_copy(at->upwf), pnt);
222 at->res = isl_union_pw_qpolynomial_add(at->res,
223 isl_union_pw_qpolynomial_from_pw_qpolynomial(
224 isl_pw_qpolynomial_alloc(set, qp)));
226 return 0;
229 __isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_fold_at(
230 __isl_take isl_union_pw_qpolynomial_fold *upwf,
231 __isl_take isl_union_set *uset)
233 struct iscc_fold_at at;
235 at.upwf = upwf;
236 at.res = isl_union_pw_qpolynomial_zero(isl_union_set_get_dim(uset));
238 isl_union_set_foreach_point(uset, eval_fold_at, &at);
240 isl_union_pw_qpolynomial_fold_free(upwf);
241 isl_union_set_free(uset);
243 return at.res;
246 static __isl_give isl_union_pw_qpolynomial_fold *union_pw_qpolynomial_add_union_pw_qpolynomial_fold(
247 __isl_take isl_union_pw_qpolynomial *upwqp,
248 __isl_take isl_union_pw_qpolynomial_fold *upwf)
250 return isl_union_pw_qpolynomial_fold_add_union_pw_qpolynomial(upwf,
251 upwqp);
254 static __isl_give struct isl_list *union_map_apply_union_pw_qpolynomial_fold(
255 __isl_take isl_union_map *umap,
256 __isl_take isl_union_pw_qpolynomial_fold *upwf)
258 isl_ctx *ctx;
259 struct isl_list *list;
260 int tight;
262 ctx = isl_union_map_get_ctx(umap);
263 list = isl_list_alloc(ctx, 2);
264 if (!list)
265 goto error2;
267 list->obj[0].type = isl_obj_union_pw_qpolynomial_fold;
268 list->obj[0].v = isl_union_map_apply_union_pw_qpolynomial_fold(umap,
269 upwf, &tight);
270 list->obj[1].type = isl_obj_bool;
271 list->obj[1].v = tight ? &isl_bool_true : &isl_bool_false;
272 if (tight < 0 || !list->obj[0].v)
273 goto error;
275 return list;
276 error2:
277 isl_union_map_free(umap);
278 isl_union_pw_qpolynomial_fold_free(upwf);
279 error:
280 isl_list_free(list);
281 return NULL;
284 struct isc_bin_op bin_ops[] = {
285 { '+', isl_obj_union_set, isl_obj_union_set,
286 isl_obj_union_set,
287 (isc_bin_op_fn) &isl_union_set_union },
288 { '+', isl_obj_union_map, isl_obj_union_map,
289 isl_obj_union_map,
290 (isc_bin_op_fn) &isl_union_map_union },
291 { '-', isl_obj_union_set, isl_obj_union_set,
292 isl_obj_union_set,
293 (isc_bin_op_fn) &isl_union_set_subtract },
294 { '-', isl_obj_union_map, isl_obj_union_map,
295 isl_obj_union_map,
296 (isc_bin_op_fn) &isl_union_map_subtract },
297 { '*', isl_obj_union_set, isl_obj_union_set,
298 isl_obj_union_set,
299 (isc_bin_op_fn) &isl_union_set_intersect },
300 { '*', isl_obj_union_map, isl_obj_union_map,
301 isl_obj_union_map,
302 (isc_bin_op_fn) &isl_union_map_intersect },
303 { '*', isl_obj_union_map, isl_obj_union_set,
304 isl_obj_union_map,
305 (isc_bin_op_fn) &isl_union_map_intersect_domain },
306 { '.', isl_obj_union_map, isl_obj_union_map,
307 isl_obj_union_map,
308 (isc_bin_op_fn) &isl_union_map_apply_range },
309 { '.', isl_obj_union_map, isl_obj_union_pw_qpolynomial,
310 isl_obj_union_pw_qpolynomial,
311 (isc_bin_op_fn) &isl_union_map_apply_union_pw_qpolynomial },
312 { '.', isl_obj_union_map, isl_obj_union_pw_qpolynomial_fold,
313 isl_obj_list,
314 (isc_bin_op_fn) &union_map_apply_union_pw_qpolynomial_fold },
315 { ISL_TOKEN_TO, isl_obj_union_set, isl_obj_union_set,
316 isl_obj_union_map,
317 (isc_bin_op_fn) &isl_union_map_from_domain_and_range },
318 { '=', isl_obj_union_set, isl_obj_union_set, isl_obj_bool,
319 (isc_bin_op_fn) &union_set_is_equal },
320 { '=', isl_obj_union_map, isl_obj_union_map, isl_obj_bool,
321 (isc_bin_op_fn) &union_map_is_equal },
322 { ISL_TOKEN_LE, isl_obj_union_set, isl_obj_union_set,
323 isl_obj_bool, (isc_bin_op_fn) &union_set_is_subset },
324 { ISL_TOKEN_LE, isl_obj_union_map, isl_obj_union_map,
325 isl_obj_bool, (isc_bin_op_fn) &union_map_is_subset },
326 { ISL_TOKEN_LT, isl_obj_union_set, isl_obj_union_set,
327 isl_obj_bool, (isc_bin_op_fn) &union_set_is_strict_subset },
328 { ISL_TOKEN_LT, isl_obj_union_map, isl_obj_union_map,
329 isl_obj_bool, (isc_bin_op_fn) &union_map_is_strict_subset },
330 { ISL_TOKEN_GE, isl_obj_union_set, isl_obj_union_set,
331 isl_obj_bool, (isc_bin_op_fn) &union_set_is_superset },
332 { ISL_TOKEN_GE, isl_obj_union_map, isl_obj_union_map,
333 isl_obj_bool, (isc_bin_op_fn) &union_map_is_superset },
334 { ISL_TOKEN_GT, isl_obj_union_set, isl_obj_union_set,
335 isl_obj_bool, (isc_bin_op_fn) &union_set_is_strict_superset },
336 { ISL_TOKEN_GT, isl_obj_union_map, isl_obj_union_map,
337 isl_obj_bool, (isc_bin_op_fn) &union_map_is_strict_superset },
338 { '.', isl_obj_union_pw_qpolynomial_fold,
339 isl_obj_union_pw_qpolynomial_fold,
340 isl_obj_union_pw_qpolynomial_fold,
341 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_fold },
342 { '+', isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
343 isl_obj_union_pw_qpolynomial,
344 (isc_bin_op_fn) &isl_union_pw_qpolynomial_add },
345 { '+', isl_obj_union_pw_qpolynomial,
346 isl_obj_union_pw_qpolynomial_fold,
347 isl_obj_union_pw_qpolynomial_fold,
348 (isc_bin_op_fn) &union_pw_qpolynomial_add_union_pw_qpolynomial_fold },
349 { '+', isl_obj_union_pw_qpolynomial_fold,
350 isl_obj_union_pw_qpolynomial,
351 isl_obj_union_pw_qpolynomial_fold,
352 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_add_union_pw_qpolynomial },
353 { '-', isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
354 isl_obj_union_pw_qpolynomial,
355 (isc_bin_op_fn) &isl_union_pw_qpolynomial_sub },
356 { '*', isl_obj_union_pw_qpolynomial, isl_obj_union_pw_qpolynomial,
357 isl_obj_union_pw_qpolynomial,
358 (isc_bin_op_fn) &isl_union_pw_qpolynomial_mul },
359 { '*', isl_obj_union_pw_qpolynomial, isl_obj_union_set,
360 isl_obj_union_pw_qpolynomial,
361 (isc_bin_op_fn) &isl_union_pw_qpolynomial_intersect_domain },
362 { '*', isl_obj_union_pw_qpolynomial_fold, isl_obj_union_set,
363 isl_obj_union_pw_qpolynomial_fold,
364 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_intersect_domain },
365 { '@', isl_obj_union_pw_qpolynomial, isl_obj_union_set,
366 isl_obj_union_pw_qpolynomial,
367 (isc_bin_op_fn) &isl_union_pw_qpolynomial_at },
368 { '@', isl_obj_union_pw_qpolynomial_fold, isl_obj_union_set,
369 isl_obj_union_pw_qpolynomial,
370 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_at },
371 { '%', isl_obj_union_set, isl_obj_union_set,
372 isl_obj_union_set,
373 (isc_bin_op_fn) &isl_union_set_gist },
374 { '%', isl_obj_union_map, isl_obj_union_map,
375 isl_obj_union_map,
376 (isc_bin_op_fn) &isl_union_map_gist },
377 { '%', isl_obj_union_pw_qpolynomial, isl_obj_union_set,
378 isl_obj_union_pw_qpolynomial,
379 (isc_bin_op_fn) &isl_union_pw_qpolynomial_gist },
380 { '%', isl_obj_union_pw_qpolynomial_fold, isl_obj_union_set,
381 isl_obj_union_pw_qpolynomial_fold,
382 (isc_bin_op_fn) &isl_union_pw_qpolynomial_fold_gist },
383 { '+', isl_obj_str, isl_obj_str, isl_obj_str,
384 (isc_bin_op_fn) &isl_str_concat },
387 struct isc_named_bin_op named_bin_ops[] = {
388 { "cross", { -1, isl_obj_union_set, isl_obj_union_set,
389 isl_obj_union_set,
390 (isc_bin_op_fn) &isl_union_set_product } },
391 { "cross", { -1, isl_obj_union_map, isl_obj_union_map,
392 isl_obj_union_map,
393 (isc_bin_op_fn) &isl_union_map_product } },
394 NULL
397 __isl_give isl_set *union_set_sample(__isl_take isl_union_set *uset)
399 return isl_set_from_basic_set(isl_union_set_sample(uset));
402 __isl_give isl_map *union_map_sample(__isl_take isl_union_map *umap)
404 return isl_map_from_basic_map(isl_union_map_sample(umap));
407 static __isl_give struct isl_list *union_pw_qpolynomial_upper_bound(
408 __isl_take isl_union_pw_qpolynomial *upwqp)
410 isl_ctx *ctx;
411 struct isl_list *list;
412 int tight;
414 ctx = isl_union_pw_qpolynomial_get_ctx(upwqp);
415 list = isl_list_alloc(ctx, 2);
416 if (!list)
417 goto error2;
419 list->obj[0].type = isl_obj_union_pw_qpolynomial_fold;
420 list->obj[0].v = isl_union_pw_qpolynomial_bound(upwqp,
421 isl_fold_max, &tight);
422 list->obj[1].type = isl_obj_bool;
423 list->obj[1].v = tight ? &isl_bool_true : &isl_bool_false;
424 if (tight < 0 || !list->obj[0].v)
425 goto error;
427 return list;
428 error2:
429 isl_union_pw_qpolynomial_free(upwqp);
430 error:
431 isl_list_free(list);
432 return NULL;
435 #ifdef HAVE_CLOOG
436 void *map_codegen(void *arg)
438 isl_dim *dim;
439 isl_union_map *umap = (isl_union_map *)arg;
440 isl_ctx *ctx = isl_union_map_get_ctx(umap);
441 CloogState *state;
442 CloogOptions *options;
443 CloogDomain *context;
444 CloogUnionDomain *ud;
445 CloogInput *input;
446 struct clast_stmt *stmt;
448 state = cloog_isl_state_malloc(ctx);
449 options = cloog_options_malloc(state);
450 options->language = LANGUAGE_C;
451 options->strides = 1;
453 ud = cloog_union_domain_from_isl_union_map(isl_union_map_copy(umap));
455 dim = isl_union_map_get_dim(umap);
456 context = cloog_domain_from_isl_set(isl_set_universe(dim));
458 input = cloog_input_alloc(context, ud);
460 stmt = cloog_clast_create_from_input(input, options);
461 clast_pprint(stdout, stmt, 0, options);
462 cloog_clast_free(stmt);
464 error:
465 cloog_options_free(options);
466 cloog_state_free(state);
467 isl_union_map_free(umap);
468 return NULL;
471 void *set_codegen(void *arg)
473 isl_dim *dim;
474 isl_union_set *uset = (isl_union_set *)arg;
475 isl_ctx *ctx = isl_union_set_get_ctx(uset);
476 CloogState *state;
477 CloogOptions *options;
478 CloogDomain *context;
479 CloogUnionDomain *ud;
480 CloogInput *input;
481 struct clast_stmt *stmt;
483 state = cloog_isl_state_malloc(ctx);
484 options = cloog_options_malloc(state);
485 options->language = LANGUAGE_C;
486 options->strides = 1;
488 ud = cloog_union_domain_from_isl_union_set(isl_union_set_copy(uset));
490 dim = isl_union_set_get_dim(uset);
491 context = cloog_domain_from_isl_set(isl_set_universe(dim));
493 input = cloog_input_alloc(context, ud);
495 stmt = cloog_clast_create_from_input(input, options);
496 clast_pprint(stdout, stmt, 0, options);
497 cloog_clast_free(stmt);
499 error:
500 cloog_options_free(options);
501 cloog_state_free(state);
502 isl_union_set_free(uset);
503 return NULL;
505 #endif
507 typedef void *(*isc_un_op_fn)(void *arg);
508 struct isc_un_op {
509 enum isl_token_type op;
510 isl_obj_type arg;
511 isl_obj_type res;
512 isc_un_op_fn fn;
514 struct isc_named_un_op {
515 char *name;
516 struct isc_un_op op;
518 struct isc_named_un_op named_un_ops[] = {
519 {"aff", { -1, isl_obj_union_map, isl_obj_union_map,
520 (isc_un_op_fn) &isl_union_map_affine_hull } },
521 {"aff", { -1, isl_obj_union_set, isl_obj_union_set,
522 (isc_un_op_fn) &isl_union_set_affine_hull } },
523 {"card", { -1, isl_obj_union_set,
524 isl_obj_union_pw_qpolynomial,
525 (isc_un_op_fn) &isl_union_set_card } },
526 {"card", { -1, isl_obj_union_map,
527 isl_obj_union_pw_qpolynomial,
528 (isc_un_op_fn) &isl_union_map_card } },
529 {"coalesce", { -1, isl_obj_union_set, isl_obj_union_set,
530 (isc_un_op_fn) &isl_union_set_coalesce } },
531 {"coalesce", { -1, isl_obj_union_map, isl_obj_union_map,
532 (isc_un_op_fn) &isl_union_map_coalesce } },
533 {"coalesce", { -1, isl_obj_union_pw_qpolynomial,
534 isl_obj_union_pw_qpolynomial,
535 (isc_un_op_fn) &isl_union_pw_qpolynomial_coalesce } },
536 {"coalesce", { -1, isl_obj_union_pw_qpolynomial_fold,
537 isl_obj_union_pw_qpolynomial_fold,
538 (isc_un_op_fn) &isl_union_pw_qpolynomial_fold_coalesce } },
539 #ifdef HAVE_CLOOG
540 {"codegen", { -1, isl_obj_union_set, isl_obj_none,
541 &set_codegen } },
542 {"codegen", { -1, isl_obj_union_map, isl_obj_none,
543 &map_codegen } },
544 #endif
545 {"deltas", { -1, isl_obj_union_map, isl_obj_union_set,
546 (isc_un_op_fn) &isl_union_map_deltas } },
547 {"dom", { -1, isl_obj_union_map, isl_obj_union_set,
548 (isc_un_op_fn) &isl_union_map_domain } },
549 {"dom", { -1, isl_obj_union_pw_qpolynomial, isl_obj_union_set,
550 (isc_un_op_fn) &isl_union_pw_qpolynomial_domain } },
551 {"dom", { -1, isl_obj_union_pw_qpolynomial_fold,
552 isl_obj_union_set,
553 (isc_un_op_fn) &isl_union_pw_qpolynomial_fold_domain } },
554 {"ran", { -1, isl_obj_union_map, isl_obj_union_set,
555 (isc_un_op_fn) &isl_union_map_range } },
556 {"lexmin", { -1, isl_obj_union_map, isl_obj_union_map,
557 (isc_un_op_fn) &isl_union_map_lexmin } },
558 {"lexmax", { -1, isl_obj_union_map, isl_obj_union_map,
559 (isc_un_op_fn) &isl_union_map_lexmax } },
560 {"lexmin", { -1, isl_obj_union_set, isl_obj_union_set,
561 (isc_un_op_fn) &isl_union_set_lexmin } },
562 {"lexmax", { -1, isl_obj_union_set, isl_obj_union_set,
563 (isc_un_op_fn) &isl_union_set_lexmax } },
564 {"sample", { -1, isl_obj_union_set, isl_obj_set,
565 (isc_un_op_fn) &union_set_sample } },
566 {"sample", { -1, isl_obj_union_map, isl_obj_map,
567 (isc_un_op_fn) &union_map_sample } },
568 {"sum", { -1, isl_obj_union_pw_qpolynomial,
569 isl_obj_union_pw_qpolynomial,
570 (isc_un_op_fn) &isl_union_pw_qpolynomial_sum } },
571 {"ub", { -1, isl_obj_union_pw_qpolynomial, isl_obj_list,
572 (isc_un_op_fn) &union_pw_qpolynomial_upper_bound } },
573 {"unwrap", { -1, isl_obj_union_set, isl_obj_union_map,
574 (isc_un_op_fn) &isl_union_set_unwrap } },
575 {"wrap", { -1, isl_obj_union_map, isl_obj_union_set,
576 (isc_un_op_fn) &isl_union_map_wrap } },
577 NULL
580 struct isl_named_obj {
581 char *name;
582 struct isl_obj obj;
585 static void free_obj(struct isl_obj obj)
587 obj.type->free(obj.v);
590 static int same_name(const void *entry, const void *val)
592 const struct isl_named_obj *named = (const struct isl_named_obj *)entry;
594 return !strcmp(named->name, val);
597 static int do_assign(struct isl_ctx *ctx, struct isl_hash_table *table,
598 char *name, struct isl_obj obj)
600 struct isl_hash_table_entry *entry;
601 uint32_t name_hash;
602 struct isl_named_obj *named;
604 name_hash = isl_hash_string(isl_hash_init(), name);
605 entry = isl_hash_table_find(ctx, table, name_hash, same_name, name, 1);
606 if (!entry)
607 goto error;
608 if (entry->data) {
609 named = entry->data;
610 free_obj(named->obj);
611 free(name);
612 } else {
613 named = isl_alloc_type(ctx, struct isl_named_obj);
614 if (!named)
615 goto error;
616 named->name = name;
617 entry->data = named;
619 named->obj = obj;
621 return 0;
622 error:
623 free_obj(obj);
624 free(name);
625 return -1;
628 static struct isl_obj stored_obj(struct isl_ctx *ctx,
629 struct isl_hash_table *table, char *name)
631 struct isl_obj obj = { isl_obj_none, NULL };
632 struct isl_hash_table_entry *entry;
633 uint32_t name_hash;
635 name_hash = isl_hash_string(isl_hash_init(), name);
636 entry = isl_hash_table_find(ctx, table, name_hash, same_name, name, 0);
637 if (entry) {
638 struct isl_named_obj *named;
639 named = entry->data;
640 obj = named->obj;
641 } else
642 fprintf(stderr, "unknown identifier '%s'\n", name);
644 free(name);
645 obj.v = obj.type->copy(obj.v);
646 return obj;
649 static int is_subtype(struct isl_obj obj, isl_obj_type super)
651 if (obj.type == super)
652 return 1;
653 if (obj.type == isl_obj_map && super == isl_obj_union_map)
654 return 1;
655 if (obj.type == isl_obj_set && super == isl_obj_union_set)
656 return 1;
657 if (obj.type == isl_obj_pw_qpolynomial &&
658 super == isl_obj_union_pw_qpolynomial)
659 return 1;
660 if (obj.type == isl_obj_pw_qpolynomial_fold &&
661 super == isl_obj_union_pw_qpolynomial_fold)
662 return 1;
663 if (obj.type == isl_obj_union_set && isl_union_set_is_empty(obj.v))
664 return 1;
665 if (obj.type == isl_obj_list) {
666 struct isl_list *list = obj.v;
667 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
668 return is_subtype(list->obj[0], super);
670 if (super == isl_obj_str)
671 return 1;
672 return 0;
675 static struct isl_obj obj_at(struct isl_obj obj, int i)
677 struct isl_list *list = obj.v;
679 obj = list->obj[i];
680 obj.v = obj.type->copy(obj.v);
682 isl_list_free(list);
684 return obj;
687 static struct isl_obj convert(isl_ctx *ctx, struct isl_obj obj,
688 isl_obj_type type)
690 if (obj.type == type)
691 return obj;
692 if (obj.type == isl_obj_map && type == isl_obj_union_map) {
693 obj.type = isl_obj_union_map;
694 obj.v = isl_union_map_from_map(obj.v);
695 return obj;
697 if (obj.type == isl_obj_set && type == isl_obj_union_set) {
698 obj.type = isl_obj_union_set;
699 obj.v = isl_union_set_from_set(obj.v);
700 return obj;
702 if (obj.type == isl_obj_pw_qpolynomial &&
703 type == isl_obj_union_pw_qpolynomial) {
704 obj.type = isl_obj_union_pw_qpolynomial;
705 obj.v = isl_union_pw_qpolynomial_from_pw_qpolynomial(obj.v);
706 return obj;
708 if (obj.type == isl_obj_pw_qpolynomial_fold &&
709 type == isl_obj_union_pw_qpolynomial_fold) {
710 obj.type = isl_obj_union_pw_qpolynomial_fold;
711 obj.v = isl_union_pw_qpolynomial_fold_from_pw_qpolynomial_fold(obj.v);
712 return obj;
714 if (obj.type == isl_obj_union_set && isl_union_set_is_empty(obj.v)) {
715 if (type == isl_obj_union_map) {
716 obj.type = isl_obj_union_map;
717 return obj;
719 if (type == isl_obj_union_pw_qpolynomial) {
720 isl_dim *dim = isl_union_set_get_dim(obj.v);
721 isl_union_set_free(obj.v);
722 obj.v = isl_union_pw_qpolynomial_zero(dim);
723 obj.type = isl_obj_union_pw_qpolynomial;
724 return obj;
726 if (type == isl_obj_union_pw_qpolynomial_fold) {
727 isl_dim *dim = isl_union_set_get_dim(obj.v);
728 isl_union_set_free(obj.v);
729 obj.v = isl_union_pw_qpolynomial_fold_zero(dim,
730 isl_fold_list);
731 obj.type = isl_obj_union_pw_qpolynomial_fold;
732 return obj;
735 if (obj.type == isl_obj_list) {
736 struct isl_list *list = obj.v;
737 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
738 return convert(ctx, obj_at(obj, 0), type);
740 if (type == isl_obj_str) {
741 isl_str *str;
742 isl_printer *p;
743 char *s;
745 p = isl_printer_to_str(ctx);
746 if (!p)
747 goto error;
748 p = obj.type->print(p, obj.v);
749 s = isl_printer_get_str(p);
750 isl_printer_free(p);
752 str = isl_str_alloc(ctx);
753 if (!str) {
754 free(s);
755 goto error;
757 str->s = s;
758 free_obj(obj);
759 obj.v = str;
760 obj.type = isl_obj_str;
761 return obj;
764 error:
765 free_obj(obj);
766 obj.type = isl_obj_none;
767 obj.v = NULL;
768 return obj;
771 static struct isc_bin_op *read_bin_op_if_available(struct isl_stream *s,
772 struct isl_obj lhs)
774 int i;
775 struct isl_token *tok;
777 tok = isl_stream_next_token(s);
778 if (!tok)
779 return NULL;
781 for (i = 0; ; ++i) {
782 if (!bin_ops[i].op)
783 break;
784 if (bin_ops[i].op != tok->type)
785 continue;
786 if (!is_subtype(lhs, bin_ops[i].lhs))
787 continue;
789 isl_token_free(tok);
790 return &bin_ops[i];
793 for (i = 0; ; ++i) {
794 if (!named_bin_ops[i].name)
795 break;
796 if (named_bin_ops[i].op.op != tok->type)
797 continue;
798 if (!is_subtype(lhs, named_bin_ops[i].op.lhs))
799 continue;
801 isl_token_free(tok);
802 return &named_bin_ops[i].op;
805 isl_stream_push_token(s, tok);
807 return NULL;
810 static struct isc_un_op *read_prefix_un_op_if_available(struct isl_stream *s)
812 int i;
813 struct isl_token *tok;
815 tok = isl_stream_next_token(s);
816 if (!tok)
817 return NULL;
819 for (i = 0; ; ++i) {
820 if (!named_un_ops[i].name)
821 break;
822 if (named_un_ops[i].op.op != tok->type)
823 continue;
825 isl_token_free(tok);
826 return &named_un_ops[i].op;
829 isl_stream_push_token(s, tok);
831 return NULL;
834 static struct isc_un_op *find_matching_un_op(struct isc_un_op *like,
835 struct isl_obj arg)
837 int i;
839 for (i = 0; ; ++i) {
840 if (!named_un_ops[i].name)
841 break;
842 if (named_un_ops[i].op.op != like->op)
843 continue;
844 if (!is_subtype(arg, named_un_ops[i].op.arg))
845 continue;
847 return &named_un_ops[i].op;
850 return NULL;
853 static int is_assign(struct isl_stream *s)
855 struct isl_token *tok;
856 struct isl_token *tok2;
857 int assign;
859 tok = isl_stream_next_token(s);
860 if (!tok)
861 return 0;
862 if (tok->type != ISL_TOKEN_IDENT) {
863 isl_stream_push_token(s, tok);
864 return 0;
867 tok2 = isl_stream_next_token(s);
868 if (!tok2) {
869 isl_stream_push_token(s, tok);
870 return 0;
872 assign = tok2->type == ISL_TOKEN_DEF;
873 isl_stream_push_token(s, tok2);
874 isl_stream_push_token(s, tok);
876 return assign;
879 static struct isl_obj read_obj(struct isl_stream *s,
880 struct isl_hash_table *table);
881 static struct isl_obj read_expr(struct isl_stream *s,
882 struct isl_hash_table *table);
884 static struct isl_obj read_un_op_expr(struct isl_stream *s,
885 struct isl_hash_table *table, struct isc_un_op *op)
887 struct isl_obj obj = { isl_obj_none, NULL };
889 obj = read_obj(s, table);
890 if (!obj.v)
891 goto error;
893 op = find_matching_un_op(op, obj);
895 isl_assert(s->ctx, op, goto error);
896 obj = convert(s->ctx, obj, op->arg);
897 obj.v = op->fn(obj.v);
898 obj.type = op->res;
900 return obj;
901 error:
902 free_obj(obj);
903 obj.type = isl_obj_none;
904 obj.v = NULL;
905 return obj;
908 static struct isl_obj transitive_closure(struct isl_ctx *ctx, struct isl_obj obj)
910 struct isl_list *list;
911 int exact;
913 if (obj.type != isl_obj_union_map)
914 obj = convert(ctx, obj, isl_obj_union_map);
915 isl_assert(ctx, obj.type == isl_obj_union_map, goto error);
916 list = isl_list_alloc(ctx, 2);
917 if (!list)
918 goto error;
920 list->obj[0].type = isl_obj_union_map;
921 list->obj[0].v = isl_union_map_transitive_closure(obj.v, &exact);
922 list->obj[1].type = isl_obj_bool;
923 list->obj[1].v = exact ? &isl_bool_true : &isl_bool_false;
924 obj.v = list;
925 obj.type = isl_obj_list;
926 if (exact < 0 || !list->obj[0].v)
927 goto error;
929 return obj;
930 error:
931 free_obj(obj);
932 obj.type = isl_obj_none;
933 obj.v = NULL;
934 return obj;
937 static struct isl_obj obj_at_index(struct isl_stream *s, struct isl_obj obj)
939 struct isl_list *list = obj.v;
940 struct isl_token *tok;
941 int i;
943 tok = isl_stream_next_token(s);
944 if (!tok || tok->type != ISL_TOKEN_VALUE) {
945 isl_stream_error(s, tok, "expecting index");
946 if (tok)
947 isl_stream_push_token(s, tok);
948 goto error;
950 i = isl_int_get_si(tok->u.v);
951 isl_token_free(tok);
952 isl_assert(s->ctx, i < list->n, goto error);
953 if (isl_stream_eat(s, ']'))
954 goto error;
956 return obj_at(obj, i);
957 error:
958 free_obj(obj);
959 obj.type = isl_obj_none;
960 obj.v = NULL;
961 return obj;
964 static struct isl_obj apply(struct isl_stream *s, __isl_take isl_union_map *umap,
965 struct isl_hash_table *table)
967 struct isl_obj obj;
969 obj = read_expr(s, table);
970 isl_assert(s->ctx, is_subtype(obj, isl_obj_union_set) ||
971 is_subtype(obj, isl_obj_union_map), goto error);
973 if (obj.type == isl_obj_list) {
974 struct isl_list *list = obj.v;
975 if (list->n == 2 && list->obj[1].type == isl_obj_bool)
976 obj = obj_at(obj, 0);
978 if (obj.type == isl_obj_set)
979 obj = convert(s->ctx, obj, isl_obj_union_set);
980 else if (obj.type == isl_obj_map)
981 obj = convert(s->ctx, obj, isl_obj_union_map);
982 if (obj.type == isl_obj_union_set) {
983 obj.v = isl_union_set_apply(obj.v, umap);
984 } else
985 obj.v = isl_union_map_apply_range(obj.v, umap);
986 if (!obj.v)
987 goto error2;
989 if (isl_stream_eat(s, ')'))
990 goto error2;
992 return obj;
993 error:
994 isl_union_map_free(umap);
995 error2:
996 free_obj(obj);
997 obj.type = isl_obj_none;
998 obj.v = NULL;
999 return obj;
1002 struct add_vertex_data {
1003 struct isl_list *list;
1004 int i;
1007 static int add_vertex(__isl_take isl_vertex *vertex, void *user)
1009 struct add_vertex_data *data = (struct add_vertex_data *)user;
1010 isl_basic_set *expr;
1012 expr = isl_vertex_get_expr(vertex);
1014 data->list->obj[data->i].type = isl_obj_set;
1015 data->list->obj[data->i].v = isl_set_from_basic_set(expr);
1016 data->i++;
1018 isl_vertex_free(vertex);
1020 return 0;
1023 static int set_vertices(__isl_take isl_set *set, void *user)
1025 isl_ctx *ctx;
1026 isl_basic_set *hull;
1027 isl_vertices *vertices = NULL;
1028 struct isl_list *list = NULL;
1029 int r;
1030 struct add_vertex_data *data = (struct add_vertex_data *)user;
1032 set = isl_set_remove_divs(set);
1033 hull = isl_set_convex_hull(set);
1034 vertices = isl_basic_set_compute_vertices(hull);
1035 isl_basic_set_free(hull);
1037 list = data->list;
1039 ctx = isl_vertices_get_ctx(vertices);
1040 data->list = isl_list_alloc(ctx, isl_vertices_get_n_vertices(vertices));
1041 if (!data->list)
1042 goto error;
1044 data->i = 0;
1045 r = isl_vertices_foreach_vertex(vertices, &add_vertex, user);
1047 data->list = isl_list_concat(list, data->list);
1049 isl_vertices_free(vertices);
1051 return r;
1052 error:
1053 data->list = list;
1054 isl_vertices_free(vertices);
1055 return -1;
1058 static struct isl_obj vertices(struct isl_stream *s,
1059 struct isl_hash_table *table)
1061 isl_ctx *ctx;
1062 struct isl_obj obj;
1063 struct isl_list *list = NULL;
1064 isl_union_set *uset;
1065 struct add_vertex_data data = { NULL };
1067 obj = read_expr(s, table);
1068 obj = convert(s->ctx, obj, isl_obj_union_set);
1069 isl_assert(s->ctx, obj.type == isl_obj_union_set, goto error);
1070 uset = obj.v;
1071 obj.v = NULL;
1073 ctx = isl_union_set_get_ctx(uset);
1074 list = isl_list_alloc(ctx, 0);
1075 if (!list)
1076 goto error;
1078 data.list = list;
1080 if (isl_union_set_foreach_set(uset, &set_vertices, &data) < 0)
1081 goto error;
1083 isl_union_set_free(uset);
1085 obj.type = isl_obj_list;
1086 obj.v = data.list;
1088 return obj;
1089 error:
1090 isl_union_set_free(uset);
1091 isl_list_free(data.list);
1092 free_obj(obj);
1093 obj.type = isl_obj_none;
1094 obj.v = NULL;
1095 return obj;
1098 static struct isl_obj power(struct isl_stream *s, struct isl_obj obj)
1100 struct isl_token *tok;
1102 if (isl_stream_eat_if_available(s, '+'))
1103 return transitive_closure(s->ctx, obj);
1105 tok = isl_stream_next_token(s);
1106 if (!tok || tok->type != ISL_TOKEN_VALUE || isl_int_cmp_si(tok->u.v, -1)) {
1107 isl_stream_error(s, tok, "expecting -1");
1108 if (tok)
1109 isl_stream_push_token(s, tok);
1110 goto error;
1112 isl_token_free(tok);
1113 isl_assert(s->ctx, is_subtype(obj, isl_obj_union_map), goto error);
1114 if (obj.type != isl_obj_union_map)
1115 obj = convert(s->ctx, obj, isl_obj_union_map);
1117 obj.v = isl_union_map_reverse(obj.v);
1118 if (!obj.v)
1119 goto error;
1121 return obj;
1122 error:
1123 free_obj(obj);
1124 obj.type = isl_obj_none;
1125 obj.v = NULL;
1126 return obj;
1129 static struct isl_obj read_from_file(struct isl_stream *s)
1131 struct isl_obj obj;
1132 struct isl_token *tok;
1133 struct isl_stream *s_file;
1134 FILE *file;
1136 tok = isl_stream_next_token(s);
1137 if (!tok || tok->type != ISL_TOKEN_STRING) {
1138 isl_stream_error(s, tok, "expecting filename");
1139 isl_token_free(tok);
1140 goto error;
1143 file = fopen(tok->u.s, "r");
1144 isl_token_free(tok);
1145 isl_assert(s->ctx, file, goto error);
1147 s_file = isl_stream_new_file(s->ctx, file);
1148 if (!s_file) {
1149 fclose(file);
1150 goto error;
1153 obj = isl_stream_read_obj(s_file);
1155 isl_stream_free(s_file);
1156 fclose(file);
1158 return obj;
1159 error:
1160 obj.type = isl_obj_none;
1161 obj.v = NULL;
1162 return obj;
1165 static struct isl_obj read_string_if_available(struct isl_stream *s)
1167 struct isl_token *tok;
1168 struct isl_obj obj = { isl_obj_none, NULL };
1170 tok = isl_stream_next_token(s);
1171 if (!tok)
1172 return obj;
1173 if (tok->type == ISL_TOKEN_STRING) {
1174 isl_str *str;
1175 str = isl_str_alloc(s->ctx);
1176 if (!str)
1177 goto error;
1178 str->s = strdup(tok->u.s);
1179 isl_token_free(tok);
1180 obj.v = str;
1181 obj.type = isl_obj_str;
1182 } else
1183 isl_stream_push_token(s, tok);
1184 return obj;
1185 error:
1186 isl_token_free(tok);
1187 return obj;
1190 static struct isl_obj read_obj(struct isl_stream *s,
1191 struct isl_hash_table *table)
1193 struct isl_obj obj = { isl_obj_none, NULL };
1194 char *name = NULL;
1195 struct isc_un_op *op = NULL;
1197 obj = read_string_if_available(s);
1198 if (obj.v)
1199 return obj;
1200 if (isl_stream_eat_if_available(s, '(')) {
1201 obj = read_expr(s, table);
1202 if (!obj.v || isl_stream_eat(s, ')'))
1203 goto error;
1204 } else {
1205 op = read_prefix_un_op_if_available(s);
1206 if (op)
1207 return read_un_op_expr(s, table, op);
1209 if (isl_stream_eat_if_available(s, read_op))
1210 return read_from_file(s);
1211 if (isl_stream_eat_if_available(s, vertices_op))
1212 return vertices(s, table);
1214 name = isl_stream_read_ident_if_available(s);
1215 if (name)
1216 obj = stored_obj(s->ctx, table, name);
1217 else
1218 obj = isl_stream_read_obj(s);
1219 if (!obj.v)
1220 goto error;
1223 if (isl_stream_eat_if_available(s, '^'))
1224 obj = power(s, obj);
1225 else if (obj.type == isl_obj_list && isl_stream_eat_if_available(s, '['))
1226 obj = obj_at_index(s, obj);
1227 else if (is_subtype(obj, isl_obj_union_map) &&
1228 isl_stream_eat_if_available(s, '(')) {
1229 obj = convert(s->ctx, obj, isl_obj_union_map);
1230 obj = apply(s, obj.v, table);
1233 return obj;
1234 error:
1235 free_obj(obj);
1236 obj.type = isl_obj_none;
1237 obj.v = NULL;
1238 return obj;
1241 static struct isc_bin_op *find_matching_bin_op(struct isc_bin_op *like,
1242 struct isl_obj lhs, struct isl_obj rhs)
1244 int i;
1246 for (i = 0; ; ++i) {
1247 if (!bin_ops[i].op)
1248 break;
1249 if (bin_ops[i].op != like->op)
1250 continue;
1251 if (!is_subtype(lhs, bin_ops[i].lhs))
1252 continue;
1253 if (!is_subtype(rhs, bin_ops[i].rhs))
1254 continue;
1256 return &bin_ops[i];
1259 for (i = 0; ; ++i) {
1260 if (!named_bin_ops[i].name)
1261 break;
1262 if (named_bin_ops[i].op.op != like->op)
1263 continue;
1264 if (!is_subtype(lhs, named_bin_ops[i].op.lhs))
1265 continue;
1266 if (!is_subtype(rhs, named_bin_ops[i].op.rhs))
1267 continue;
1269 return &named_bin_ops[i].op;
1272 return NULL;
1275 static struct isl_obj read_expr(struct isl_stream *s,
1276 struct isl_hash_table *table)
1278 struct isl_obj obj = { isl_obj_none, NULL };
1279 struct isl_obj right_obj = { isl_obj_none, NULL };
1281 obj = read_obj(s, table);
1282 for (; obj.v;) {
1283 struct isc_bin_op *op = NULL;
1285 op = read_bin_op_if_available(s, obj);
1286 if (!op)
1287 break;
1289 right_obj = read_obj(s, table);
1291 op = find_matching_bin_op(op, obj, right_obj);
1293 isl_assert(s->ctx, op, goto error);
1294 obj = convert(s->ctx, obj, op->lhs);
1295 right_obj = convert(s->ctx, right_obj, op->rhs);
1296 obj.v = op->fn(obj.v, right_obj.v);
1297 obj.type = op->res;
1300 return obj;
1301 error:
1302 free_obj(right_obj);
1303 free_obj(obj);
1304 obj.type = isl_obj_none;
1305 obj.v = NULL;
1306 return obj;
1309 static __isl_give isl_printer *source_file(struct isl_stream *s,
1310 struct isl_hash_table *table, __isl_take isl_printer *p);
1312 static __isl_give isl_printer *read_line(struct isl_stream *s,
1313 struct isl_hash_table *table, __isl_take isl_printer *p)
1315 struct isl_obj obj = { isl_obj_none, NULL };
1316 char *lhs = NULL;
1317 int assign = 0;
1318 struct isc_bin_op *op = NULL;
1320 if (!p)
1321 return NULL;
1322 if (isl_stream_is_empty(s))
1323 return p;
1325 if (isl_stream_eat_if_available(s, source_op))
1326 return source_file(s, table, p);
1328 assign = is_assign(s);
1329 if (assign) {
1330 lhs = isl_stream_read_ident_if_available(s);
1331 if (isl_stream_eat(s, ISL_TOKEN_DEF))
1332 goto error;
1335 obj = read_expr(s, table);
1336 if (obj.type == isl_obj_none || obj.v == NULL)
1337 goto error;
1338 if (isl_stream_eat(s, ';'))
1339 goto error;
1341 if (assign) {
1342 if (do_assign(s->ctx, table, lhs, obj))
1343 return;
1344 } else {
1345 p = obj.type->print(p, obj.v);
1346 p = isl_printer_end_line(p);
1347 free_obj(obj);
1350 return p;
1351 error:
1352 isl_stream_flush_tokens(s);
1353 isl_stream_skip_line(s);
1354 free(lhs);
1355 free_obj(obj);
1356 return p;
1359 int free_cb(void **entry, void *user)
1361 struct isl_named_obj *named = *entry;
1363 free_obj(named->obj);
1364 free(named->name);
1365 free(named);
1367 return 0;
1370 static void register_named_ops(struct isl_stream *s)
1372 int i;
1374 read_op = isl_stream_register_keyword(s, "read");
1375 assert(read_op != ISL_TOKEN_ERROR);
1376 source_op = isl_stream_register_keyword(s, "source");
1377 assert(source_op != ISL_TOKEN_ERROR);
1378 vertices_op = isl_stream_register_keyword(s, "vertices");
1379 assert(vertices_op != ISL_TOKEN_ERROR);
1381 for (i = 0; ; ++i) {
1382 if (!named_un_ops[i].name)
1383 break;
1384 named_un_ops[i].op.op = isl_stream_register_keyword(s,
1385 named_un_ops[i].name);
1386 assert(named_un_ops[i].op.op != ISL_TOKEN_ERROR);
1389 for (i = 0; ; ++i) {
1390 if (!named_bin_ops[i].name)
1391 break;
1392 named_bin_ops[i].op.op = isl_stream_register_keyword(s,
1393 named_bin_ops[i].name);
1394 assert(named_bin_ops[i].op.op != ISL_TOKEN_ERROR);
1398 static __isl_give isl_printer *source_file(struct isl_stream *s,
1399 struct isl_hash_table *table, __isl_take isl_printer *p)
1401 struct isl_token *tok;
1402 struct isl_stream *s_file;
1403 FILE *file;
1405 tok = isl_stream_next_token(s);
1406 if (!tok || tok->type != ISL_TOKEN_STRING) {
1407 isl_stream_error(s, tok, "expecting filename");
1408 isl_token_free(tok);
1409 return p;
1412 file = fopen(tok->u.s, "r");
1413 isl_token_free(tok);
1414 isl_assert(s->ctx, file, return p);
1416 s_file = isl_stream_new_file(s->ctx, file);
1417 if (!s_file) {
1418 fclose(file);
1419 return p;
1422 register_named_ops(s_file);
1424 while (!s_file->eof)
1425 p = read_line(s_file, table, p);
1427 isl_stream_free(s_file);
1428 fclose(file);
1430 isl_stream_eat(s, ';');
1432 return p;
1435 int main(int argc, char **argv)
1437 struct isl_ctx *ctx;
1438 struct isl_stream *s;
1439 struct isl_hash_table *table;
1440 struct iscc_options *options;
1441 isl_printer *p;
1443 options = iscc_options_new_with_defaults();
1444 assert(options);
1445 argc = iscc_options_parse(options, argc, argv, ISL_ARG_ALL);
1447 ctx = isl_ctx_alloc_with_options(iscc_options_arg, options);
1448 s = isl_stream_new_file(ctx, stdin);
1449 assert(s);
1450 table = isl_hash_table_alloc(ctx, 10);
1451 assert(table);
1452 p = isl_printer_to_file(ctx, stdout);
1453 p = isl_printer_set_output_format(p, options->format);
1454 assert(p);
1456 register_named_ops(s);
1458 while (!s->eof) {
1459 p = read_line(s, table, p);
1462 isl_printer_free(p);
1463 isl_hash_table_foreach(ctx, table, free_cb, NULL);
1464 isl_hash_table_free(ctx, table);
1465 isl_stream_free(s);
1466 isl_ctx_free(ctx);
1468 return 0;