isl_stream: accept "@" token
[platform/upstream/isl.git] / isl_input.c
1 /*
2  * Copyright 2008-2009 Katholieke Universiteit Leuven
3  * Copyright 2010      INRIA Saclay
4  *
5  * Use of this software is governed by the GNU LGPLv2.1 license
6  *
7  * Written by Sven Verdoolaege, K.U.Leuven, Departement
8  * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
9  * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
10  * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France 
11  */
12
13 #include <ctype.h>
14 #include <stdio.h>
15 #include <string.h>
16 #include <strings.h>
17 #include <isl_set.h>
18 #include <isl_seq.h>
19 #include <isl_div.h>
20 #include "isl_stream.h"
21 #include "isl_map_private.h"
22 #include "isl_obj.h"
23 #include "isl_polynomial_private.h"
24
25 struct variable {
26         char                    *name;
27         int                      pos;
28         struct variable         *next;
29 };
30
31 struct vars {
32         struct isl_ctx  *ctx;
33         int              n;
34         struct variable *v;
35 };
36
37 static struct vars *vars_new(struct isl_ctx *ctx)
38 {
39         struct vars *v;
40         v = isl_alloc_type(ctx, struct vars);
41         if (!v)
42                 return NULL;
43         v->ctx = ctx;
44         v->n = 0;
45         v->v = NULL;
46         return v;
47 }
48
49 static void variable_free(struct variable *var)
50 {
51         while (var) {
52                 struct variable *next = var->next;
53                 free(var->name);
54                 free(var);
55                 var = next;
56         }
57 }
58
59 static void vars_free(struct vars *v)
60 {
61         if (!v)
62                 return;
63         variable_free(v->v);
64         free(v);
65 }
66
67 static void vars_drop(struct vars *v, int n)
68 {
69         struct variable *var;
70
71         if (!v)
72                 return;
73
74         v->n -= n;
75
76         var = v->v;
77         while (--n >= 0) {
78                 struct variable *next = var->next;
79                 free(var->name);
80                 free(var);
81                 var = next;
82         }
83         v->v = var;
84 }
85
86 static struct variable *variable_new(struct vars *v, const char *name, int len,
87                                 int pos)
88 {
89         struct variable *var;
90         var = isl_alloc_type(v->ctx, struct variable);
91         if (!var)
92                 goto error;
93         var->name = strdup(name);
94         var->name[len] = '\0';
95         var->pos = pos;
96         var->next = v->v;
97         return var;
98 error:
99         variable_free(v->v);
100         return NULL;
101 }
102
103 static int vars_pos(struct vars *v, const char *s, int len)
104 {
105         int pos;
106         struct variable *q;
107
108         if (len == -1)
109                 len = strlen(s);
110         for (q = v->v; q; q = q->next) {
111                 if (strncmp(q->name, s, len) == 0 && q->name[len] == '\0')
112                         break;
113         }
114         if (q)
115                 pos = q->pos;
116         else {
117                 pos = v->n;
118                 v->v = variable_new(v, s, len, v->n);
119                 if (!v->v)
120                         return -1;
121                 v->n++;
122         }
123         return pos;
124 }
125
126 static __isl_give isl_basic_map *set_name(__isl_take isl_basic_map *bmap,
127         enum isl_dim_type type, unsigned pos, char *name)
128 {
129         char *prime;
130
131         if (!bmap)
132                 return NULL;
133         if (!name)
134                 return bmap;
135
136         prime = strchr(name, '\'');
137         if (prime)
138                 *prime = '\0';
139         bmap->dim = isl_dim_set_name(bmap->dim, type, pos, name);
140         if (prime)
141                 *prime = '\'';
142
143         if (!bmap->dim)
144                 goto error;
145
146         return bmap;
147 error:
148         isl_basic_map_free(bmap);
149         return NULL;
150 }
151
152 static struct isl_vec *accept_affine(struct isl_stream *s, struct vars *v)
153 {
154         struct isl_token *tok = NULL;
155         struct isl_vec *aff;
156         int sign = 1;
157
158         aff = isl_vec_alloc(v->ctx, 1 + v->n);
159         isl_seq_clr(aff->el, aff->size);
160         if (!aff)
161                 return NULL;
162
163         for (;;) {
164                 tok = isl_stream_next_token(s);
165                 if (!tok) {
166                         isl_stream_error(s, NULL, "unexpected EOF");
167                         goto error;
168                 }
169                 if (tok->type == ISL_TOKEN_IDENT) {
170                         int n = v->n;
171                         int pos = vars_pos(v, tok->u.s, -1);
172                         if (pos < 0)
173                                 goto error;
174                         if (pos >= n) {
175                                 isl_stream_error(s, tok, "unknown identifier");
176                                 isl_token_free(tok);
177                                 goto error;
178                         }
179                         if (sign > 0)
180                                 isl_int_add_ui(aff->el[1 + pos],
181                                                aff->el[1 + pos], 1);
182                         else
183                                 isl_int_sub_ui(aff->el[1 + pos],
184                                                aff->el[1 + pos], 1);
185                         sign = 1;
186                 } else if (tok->type == ISL_TOKEN_VALUE) {
187                         struct isl_token *tok2;
188                         int n = v->n;
189                         int pos = -1;
190                         if (isl_stream_eat_if_available(s, '*') &&
191                             !isl_stream_next_token_is(s, ISL_TOKEN_IDENT)) {
192                                 isl_stream_error(s, NULL, "missing identifier");
193                                 goto error;
194                         }
195                         tok2 = isl_stream_next_token(s);
196                         if (tok2 && tok2->type == ISL_TOKEN_IDENT) {
197                                 pos = vars_pos(v, tok2->u.s, -1);
198                                 if (pos < 0)
199                                         goto error;
200                                 if (pos >= n) {
201                                         isl_stream_error(s, tok2,
202                                                 "unknown identifier");
203                                         isl_token_free(tok);
204                                         isl_token_free(tok2);
205                                         goto error;
206                                 }
207                                 isl_token_free(tok2);
208                         } else if (tok2)
209                                 isl_stream_push_token(s, tok2);
210                         if (sign < 0)
211                                 isl_int_neg(tok->u.v, tok->u.v);
212                         isl_int_add(aff->el[1 + pos],
213                                         aff->el[1 + pos], tok->u.v);
214                         sign = 1;
215                 } else if (tok->type == '-') {
216                         sign = -sign;
217                 } else if (tok->type == '+') {
218                         /* nothing */
219                 } else {
220                         isl_stream_push_token(s, tok);
221                         break;
222                 }
223                 isl_token_free(tok);
224         }
225
226         return aff;
227 error:
228         isl_vec_free(aff);
229         return NULL;
230 }
231
232 static __isl_give isl_basic_map *read_var_list(struct isl_stream *s,
233         __isl_take isl_basic_map *bmap, enum isl_dim_type type, struct vars *v)
234 {
235         int i = 0;
236         struct isl_token *tok;
237
238         while ((tok = isl_stream_next_token(s)) != NULL) {
239                 int new_name = 0;
240
241                 if (tok->type == ISL_TOKEN_IDENT) {
242                         int n = v->n;
243                         int p = vars_pos(v, tok->u.s, -1);
244                         if (p < 0)
245                                 goto error;
246                         new_name = p >= n;
247                 }
248
249                 if (new_name) {
250                         bmap = isl_basic_map_add(bmap, type, 1);
251                         bmap = set_name(bmap, type, i, v->v->name);
252                         isl_token_free(tok);
253                 } else if (tok->type == ISL_TOKEN_IDENT ||
254                            tok->type == ISL_TOKEN_VALUE) {
255                         struct isl_vec *vec;
256                         int k;
257                         if (type == isl_dim_param) {
258                                 isl_stream_error(s, tok,
259                                                 "expecting unique identifier");
260                                 goto error;
261                         }
262                         isl_stream_push_token(s, tok);
263                         tok = NULL;
264                         vec = accept_affine(s, v);
265                         if (!vec)
266                                 goto error;
267                         v->v = variable_new(v, "", 0, v->n);
268                         if (!v->v)
269                                 goto error;
270                         v->n++;
271                         bmap = isl_basic_map_add(bmap, type, 1);
272                         bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
273                         k = isl_basic_map_alloc_equality(bmap);
274                         if (k >= 0) {
275                                 isl_seq_cpy(bmap->eq[k], vec->el, vec->size);
276                                 isl_int_set_si(bmap->eq[k][vec->size], -1);
277                         }
278                         isl_vec_free(vec);
279                         if (k < 0)
280                                 goto error;
281                 } else
282                         break;
283
284                 tok = isl_stream_next_token(s);
285                 if (!tok || tok->type != ',')
286                         break;
287
288                 isl_token_free(tok);
289                 i++;
290         }
291         if (tok)
292                 isl_stream_push_token(s, tok);
293
294         return bmap;
295 error:
296         isl_token_free(tok);
297         isl_basic_map_free(bmap);
298         return NULL;
299 }
300
301 static __isl_give isl_mat *accept_affine_list(struct isl_stream *s,
302         struct vars *v)
303 {
304         struct isl_vec *vec;
305         struct isl_mat *mat;
306         struct isl_token *tok = NULL;
307
308         vec = accept_affine(s, v);
309         mat = isl_mat_from_row_vec(vec);
310         if (!mat)
311                 return NULL;
312
313         for (;;) {
314                 tok = isl_stream_next_token(s);
315                 if (!tok) {
316                         isl_stream_error(s, NULL, "unexpected EOF");
317                         goto error;
318                 }
319                 if (tok->type != ',') {
320                         isl_stream_push_token(s, tok);
321                         break;
322                 }
323                 isl_token_free(tok);
324
325                 vec = accept_affine(s, v);
326                 mat = isl_mat_vec_concat(mat, vec);
327                 if (!mat)
328                         return NULL;
329         }
330
331         return mat;
332 error:
333         isl_mat_free(mat);
334         return NULL;
335 }
336
337 static struct isl_basic_map *add_div_definition(struct isl_stream *s,
338         struct vars *v, struct isl_basic_map *bmap, int k)
339 {
340         struct isl_token *tok;
341         int seen_paren = 0;
342         struct isl_vec *aff;
343
344         if (isl_stream_eat(s, '['))
345                 goto error;
346
347         tok = isl_stream_next_token(s);
348         if (!tok)
349                 goto error;
350         if (tok->type == '(') {
351                 seen_paren = 1;
352                 isl_token_free(tok);
353         } else
354                 isl_stream_push_token(s, tok);
355
356         aff = accept_affine(s, v);
357         if (!aff)
358                 goto error;
359
360         isl_seq_cpy(bmap->div[k] + 1, aff->el, aff->size);
361
362         isl_vec_free(aff);
363
364         if (seen_paren && isl_stream_eat(s, ')'))
365                 goto error;
366         if (isl_stream_eat(s, '/'))
367                 goto error;
368
369         tok = isl_stream_next_token(s);
370         if (!tok)
371                 goto error;
372         if (tok->type != ISL_TOKEN_VALUE) {
373                 isl_stream_error(s, tok, "expected denominator");
374                 isl_stream_push_token(s, tok);
375                 goto error;
376         }
377         isl_int_set(bmap->div[k][0], tok->u.v);
378         isl_token_free(tok);
379
380         if (isl_stream_eat(s, ']'))
381                 goto error;
382
383         if (isl_basic_map_add_div_constraints(bmap, k) < 0)
384                 goto error;
385
386         return bmap;
387 error:
388         isl_basic_map_free(bmap);
389         return NULL;
390 }
391
392 static struct isl_basic_map *read_defined_var_list(struct isl_stream *s,
393         struct vars *v, struct isl_basic_map *bmap)
394 {
395         struct isl_token *tok;
396
397         while ((tok = isl_stream_next_token(s)) != NULL) {
398                 int k;
399                 int p;
400                 int n = v->n;
401                 unsigned total = isl_basic_map_total_dim(bmap);
402
403                 if (tok->type != ISL_TOKEN_IDENT)
404                         break;
405
406                 p = vars_pos(v, tok->u.s, -1);
407                 if (p < 0)
408                         goto error;
409                 if (p < n) {
410                         isl_stream_error(s, tok, "expecting unique identifier");
411                         goto error;
412                 }
413                 isl_token_free(tok);
414
415                 bmap = isl_basic_map_cow(bmap);
416                 bmap = isl_basic_map_extend_dim(bmap, isl_dim_copy(bmap->dim),
417                                                 1, 0, 2);
418
419                 if ((k = isl_basic_map_alloc_div(bmap)) < 0)
420                         goto error;
421                 isl_seq_clr(bmap->div[k], 1 + 1 + total);
422
423                 tok = isl_stream_next_token(s);
424                 if (tok && tok->type == '=') {
425                         isl_token_free(tok);
426                         bmap = add_div_definition(s, v, bmap, k);
427                         tok = isl_stream_next_token(s);
428                 }
429
430                 if (!tok || tok->type != ',')
431                         break;
432
433                 isl_token_free(tok);
434         }
435         if (tok)
436                 isl_stream_push_token(s, tok);
437
438         return bmap;
439 error:
440         isl_token_free(tok);
441         isl_basic_map_free(bmap);
442         return NULL;
443 }
444
445 static __isl_give isl_basic_map *read_tuple(struct isl_stream *s,
446         __isl_take isl_basic_map *bmap, enum isl_dim_type type, struct vars *v)
447 {
448         struct isl_token *tok;
449
450         tok = isl_stream_next_token(s);
451         if (!tok || tok->type != '[') {
452                 isl_stream_error(s, tok, "expecting '['");
453                 goto error;
454         }
455         isl_token_free(tok);
456         bmap = read_var_list(s, bmap, type, v);
457         tok = isl_stream_next_token(s);
458         if (!tok || tok->type != ']') {
459                 isl_stream_error(s, tok, "expecting ']'");
460                 goto error;
461         }
462         isl_token_free(tok);
463
464         return bmap;
465 error:
466         if (tok)
467                 isl_token_free(tok);
468         isl_basic_map_free(bmap);
469         return NULL;
470 }
471
472 static struct isl_basic_map *add_constraints(struct isl_stream *s,
473         struct vars *v, struct isl_basic_map *bmap);
474
475 static struct isl_basic_map *add_exists(struct isl_stream *s,
476         struct vars *v, struct isl_basic_map *bmap)
477 {
478         struct isl_token *tok;
479         int n = v->n;
480         int extra;
481         int seen_paren = 0;
482         int i;
483         unsigned total;
484
485         tok = isl_stream_next_token(s);
486         if (!tok)
487                 goto error;
488         if (tok->type == '(') {
489                 seen_paren = 1;
490                 isl_token_free(tok);
491         } else
492                 isl_stream_push_token(s, tok);
493
494         bmap = read_defined_var_list(s, v, bmap);
495         if (!bmap)
496                 goto error;
497
498         if (isl_stream_eat(s, ':'))
499                 goto error;
500         bmap = add_constraints(s, v, bmap);
501         if (seen_paren && isl_stream_eat(s, ')'))
502                 goto error;
503         return bmap;
504 error:
505         isl_basic_map_free(bmap);
506         return NULL;
507 }
508
509 static __isl_give isl_basic_map *construct_constraint(
510         __isl_take isl_basic_map *bmap, enum isl_token_type type,
511         isl_int *left, isl_int *right)
512 {
513         int k;
514         unsigned len;
515         struct isl_ctx *ctx;
516
517         if (!bmap)
518                 return NULL;
519         len = 1 + isl_basic_map_total_dim(bmap);
520         ctx = bmap->ctx;
521
522         k = isl_basic_map_alloc_inequality(bmap);
523         if (k < 0)
524                 goto error;
525         if (type == ISL_TOKEN_LE)
526                 isl_seq_combine(bmap->ineq[k], ctx->negone, left,
527                                                ctx->one, right,
528                                                len);
529         else if (type == ISL_TOKEN_GE)
530                 isl_seq_combine(bmap->ineq[k], ctx->one, left,
531                                                ctx->negone, right,
532                                                len);
533         else if (type == ISL_TOKEN_LT) {
534                 isl_seq_combine(bmap->ineq[k], ctx->negone, left,
535                                                ctx->one, right,
536                                                len);
537                 isl_int_sub_ui(bmap->ineq[k][0], bmap->ineq[k][0], 1);
538         } else if (type == ISL_TOKEN_GT) {
539                 isl_seq_combine(bmap->ineq[k], ctx->one, left,
540                                                ctx->negone, right,
541                                                len);
542                 isl_int_sub_ui(bmap->ineq[k][0], bmap->ineq[k][0], 1);
543         } else {
544                 isl_seq_combine(bmap->ineq[k], ctx->one, left,
545                                                ctx->negone, right,
546                                                len);
547                 isl_basic_map_inequality_to_equality(bmap, k);
548         }
549
550         return bmap;
551 error:
552         isl_basic_map_free(bmap);
553         return NULL;
554 }
555
556 static int is_comparator(struct isl_token *tok)
557 {
558         if (!tok)
559                 return 0;
560
561         switch (tok->type) {
562         case ISL_TOKEN_LT:
563         case ISL_TOKEN_GT:
564         case ISL_TOKEN_LE:
565         case ISL_TOKEN_GE:
566         case '=':
567                 return 1;
568         default:
569                 return 0;
570         }
571 }
572
573 static struct isl_basic_map *add_constraint(struct isl_stream *s,
574         struct vars *v, struct isl_basic_map *bmap)
575 {
576         int i, j;
577         unsigned total = isl_basic_map_total_dim(bmap);
578         struct isl_token *tok = NULL;
579         struct isl_mat *aff1 = NULL, *aff2 = NULL;
580
581         tok = isl_stream_next_token(s);
582         if (!tok)
583                 goto error;
584         if (tok->type == ISL_TOKEN_EXISTS) {
585                 isl_token_free(tok);
586                 return add_exists(s, v, bmap);
587         }
588         isl_stream_push_token(s, tok);
589         tok = NULL;
590
591         bmap = isl_basic_map_cow(bmap);
592
593         aff1 = accept_affine_list(s, v);
594         if (!aff1)
595                 goto error;
596         tok = isl_stream_next_token(s);
597         if (!is_comparator(tok)) {
598                 isl_stream_error(s, tok, "missing operator");
599                 if (tok)
600                         isl_stream_push_token(s, tok);
601                 tok = NULL;
602                 goto error;
603         }
604         isl_assert(aff1->ctx, aff1->n_col == 1 + total, goto error);
605         for (;;) {
606                 aff2 = accept_affine_list(s, v);
607                 if (!aff2)
608                         goto error;
609                 isl_assert(aff2->ctx, aff2->n_col == 1 + total, goto error);
610
611                 bmap = isl_basic_map_extend_constraints(bmap, 0,
612                                                 aff1->n_row * aff2->n_row);
613                 for (i = 0; i < aff1->n_row; ++i)
614                         for (j = 0; j < aff2->n_row; ++j)
615                                 bmap = construct_constraint(bmap, tok->type,
616                                                     aff1->row[i], aff2->row[j]);
617                 isl_token_free(tok);
618                 isl_mat_free(aff1);
619                 aff1 = aff2;
620
621                 tok = isl_stream_next_token(s);
622                 if (!is_comparator(tok)) {
623                         if (tok)
624                                 isl_stream_push_token(s, tok);
625                         break;
626                 }
627         }
628         isl_mat_free(aff1);
629
630         return bmap;
631 error:
632         if (tok)
633                 isl_token_free(tok);
634         isl_mat_free(aff1);
635         isl_mat_free(aff2);
636         isl_basic_map_free(bmap);
637         return NULL;
638 }
639
640 static struct isl_basic_map *add_constraints(struct isl_stream *s,
641         struct vars *v, struct isl_basic_map *bmap)
642 {
643         struct isl_token *tok;
644
645         for (;;) {
646                 bmap = add_constraint(s, v, bmap);
647                 if (!bmap)
648                         return NULL;
649                 tok = isl_stream_next_token(s);
650                 if (!tok) {
651                         isl_stream_error(s, NULL, "unexpected EOF");
652                         goto error;
653                 }
654                 if (tok->type != ISL_TOKEN_AND)
655                         break;
656                 isl_token_free(tok);
657         }
658         isl_stream_push_token(s, tok);
659
660         return bmap;
661 error:
662         if (tok)
663                 isl_token_free(tok);
664         isl_basic_map_free(bmap);
665         return NULL;
666 }
667
668 static struct isl_basic_map *read_disjunct(struct isl_stream *s,
669         struct vars *v, __isl_take isl_dim *dim)
670 {
671         int seen_paren = 0;
672         struct isl_token *tok;
673         struct isl_basic_map *bmap;
674
675         bmap = isl_basic_map_alloc_dim(dim, 0, 0, 0);
676         if (!bmap)
677                 return NULL;
678
679         tok = isl_stream_next_token(s);
680         if (!tok)
681                 goto error;
682         if (tok->type == '(') {
683                 seen_paren = 1;
684                 isl_token_free(tok);
685         } else
686                 isl_stream_push_token(s, tok);
687
688         bmap = add_constraints(s, v, bmap);
689         bmap = isl_basic_map_simplify(bmap);
690         bmap = isl_basic_map_finalize(bmap);
691
692         if (seen_paren && isl_stream_eat(s, ')'))
693                 goto error;
694
695         return bmap;
696 error:
697         isl_basic_map_free(bmap);
698         return NULL;
699 }
700
701 static struct isl_map *read_disjuncts(struct isl_stream *s,
702         struct vars *v, __isl_take isl_dim *dim)
703 {
704         struct isl_token *tok;
705         struct isl_map *map;
706
707         tok = isl_stream_next_token(s);
708         if (!tok) {
709                 isl_stream_error(s, NULL, "unexpected EOF");
710                 goto error;
711         }
712         if (tok->type == '}') {
713                 isl_stream_push_token(s, tok);
714                 return isl_map_universe(dim);
715         }
716         isl_stream_push_token(s, tok);
717
718         map = isl_map_empty(isl_dim_copy(dim));
719         for (;;) {
720                 struct isl_basic_map *bmap;
721                 int n = v->n;
722
723                 bmap = read_disjunct(s, v, isl_dim_copy(dim));
724                 map = isl_map_union(map, isl_map_from_basic_map(bmap));
725
726                 vars_drop(v, v->n - n);
727
728                 tok = isl_stream_next_token(s);
729                 if (!tok || tok->type != ISL_TOKEN_OR)
730                         break;
731                 isl_token_free(tok);
732         }
733         if (tok)
734                 isl_stream_push_token(s, tok);
735
736         isl_dim_free(dim);
737         return map;
738 error:
739         isl_dim_free(dim);
740         return NULL;
741 }
742
743 static int polylib_pos_to_isl_pos(__isl_keep isl_basic_map *bmap, int pos)
744 {
745         if (pos < isl_basic_map_dim(bmap, isl_dim_out))
746                 return 1 + isl_basic_map_dim(bmap, isl_dim_param) +
747                            isl_basic_map_dim(bmap, isl_dim_in) + pos;
748         pos -= isl_basic_map_dim(bmap, isl_dim_out);
749
750         if (pos < isl_basic_map_dim(bmap, isl_dim_in))
751                 return 1 + isl_basic_map_dim(bmap, isl_dim_param) + pos;
752         pos -= isl_basic_map_dim(bmap, isl_dim_in);
753
754         if (pos < isl_basic_map_dim(bmap, isl_dim_div))
755                 return 1 + isl_basic_map_dim(bmap, isl_dim_param) +
756                            isl_basic_map_dim(bmap, isl_dim_in) +
757                            isl_basic_map_dim(bmap, isl_dim_out) + pos;
758         pos -= isl_basic_map_dim(bmap, isl_dim_div);
759
760         if (pos < isl_basic_map_dim(bmap, isl_dim_param))
761                 return 1 + pos;
762
763         return 0;
764 }
765
766 static __isl_give isl_basic_map *basic_map_read_polylib_constraint(
767         struct isl_stream *s, __isl_take isl_basic_map *bmap)
768 {
769         int j;
770         struct isl_token *tok;
771         int type;
772         int k;
773         isl_int *c;
774         unsigned nparam;
775         unsigned dim;
776
777         if (!bmap)
778                 return NULL;
779
780         nparam = isl_basic_map_dim(bmap, isl_dim_param);
781         dim = isl_basic_map_dim(bmap, isl_dim_out);
782
783         tok = isl_stream_next_token(s);
784         if (!tok || tok->type != ISL_TOKEN_VALUE) {
785                 isl_stream_error(s, tok, "expecting coefficient");
786                 if (tok)
787                         isl_stream_push_token(s, tok);
788                 goto error;
789         }
790         if (!tok->on_new_line) {
791                 isl_stream_error(s, tok, "coefficient should appear on new line");
792                 isl_stream_push_token(s, tok);
793                 goto error;
794         }
795
796         type = isl_int_get_si(tok->u.v);
797         isl_token_free(tok);
798
799         isl_assert(s->ctx, type == 0 || type == 1, goto error);
800         if (type == 0) {
801                 k = isl_basic_map_alloc_equality(bmap);
802                 c = bmap->eq[k];
803         } else {
804                 k = isl_basic_map_alloc_inequality(bmap);
805                 c = bmap->ineq[k];
806         }
807         if (k < 0)
808                 goto error;
809
810         for (j = 0; j < 1 + isl_basic_map_total_dim(bmap); ++j) {
811                 int pos;
812                 tok = isl_stream_next_token(s);
813                 if (!tok || tok->type != ISL_TOKEN_VALUE) {
814                         isl_stream_error(s, tok, "expecting coefficient");
815                         if (tok)
816                                 isl_stream_push_token(s, tok);
817                         goto error;
818                 }
819                 if (tok->on_new_line) {
820                         isl_stream_error(s, tok,
821                                 "coefficient should not appear on new line");
822                         isl_stream_push_token(s, tok);
823                         goto error;
824                 }
825                 pos = polylib_pos_to_isl_pos(bmap, j);
826                 isl_int_set(c[pos], tok->u.v);
827                 isl_token_free(tok);
828         }
829
830         return bmap;
831 error:
832         isl_basic_map_free(bmap);
833         return NULL;
834 }
835
836 static __isl_give isl_basic_map *basic_map_read_polylib(struct isl_stream *s,
837         int nparam)
838 {
839         int i;
840         struct isl_token *tok;
841         struct isl_token *tok2;
842         int n_row, n_col;
843         int on_new_line;
844         unsigned in = 0, out, local = 0;
845         struct isl_basic_map *bmap = NULL;
846
847         if (nparam < 0)
848                 nparam = 0;
849
850         tok = isl_stream_next_token(s);
851         if (!tok) {
852                 isl_stream_error(s, NULL, "unexpected EOF");
853                 return NULL;
854         }
855         tok2 = isl_stream_next_token(s);
856         if (!tok2) {
857                 isl_token_free(tok);
858                 isl_stream_error(s, NULL, "unexpected EOF");
859                 return NULL;
860         }
861         n_row = isl_int_get_si(tok->u.v);
862         n_col = isl_int_get_si(tok2->u.v);
863         on_new_line = tok2->on_new_line;
864         isl_token_free(tok2);
865         isl_token_free(tok);
866         isl_assert(s->ctx, !on_new_line, return NULL);
867         isl_assert(s->ctx, n_row >= 0, return NULL);
868         isl_assert(s->ctx, n_col >= 2 + nparam, return NULL);
869         tok = isl_stream_next_token_on_same_line(s);
870         if (tok) {
871                 if (tok->type != ISL_TOKEN_VALUE) {
872                         isl_stream_error(s, tok,
873                                     "expecting number of output dimensions");
874                         isl_stream_push_token(s, tok);
875                         goto error;
876                 }
877                 out = isl_int_get_si(tok->u.v);
878                 isl_token_free(tok);
879
880                 tok = isl_stream_next_token_on_same_line(s);
881                 if (!tok || tok->type != ISL_TOKEN_VALUE) {
882                         isl_stream_error(s, tok,
883                                     "expecting number of input dimensions");
884                         if (tok)
885                                 isl_stream_push_token(s, tok);
886                         goto error;
887                 }
888                 in = isl_int_get_si(tok->u.v);
889                 isl_token_free(tok);
890
891                 tok = isl_stream_next_token_on_same_line(s);
892                 if (!tok || tok->type != ISL_TOKEN_VALUE) {
893                         isl_stream_error(s, tok,
894                                     "expecting number of existentials");
895                         if (tok)
896                                 isl_stream_push_token(s, tok);
897                         goto error;
898                 }
899                 local = isl_int_get_si(tok->u.v);
900                 isl_token_free(tok);
901
902                 tok = isl_stream_next_token_on_same_line(s);
903                 if (!tok || tok->type != ISL_TOKEN_VALUE) {
904                         isl_stream_error(s, tok,
905                                     "expecting number of parameters");
906                         if (tok)
907                                 isl_stream_push_token(s, tok);
908                         goto error;
909                 }
910                 nparam = isl_int_get_si(tok->u.v);
911                 isl_token_free(tok);
912                 if (n_col != 1 + out + in + local + nparam + 1) {
913                         isl_stream_error(s, NULL,
914                                     "dimensions don't match");
915                         goto error;
916                 }
917         } else
918                 out = n_col - 2 - nparam;
919         bmap = isl_basic_map_alloc(s->ctx, nparam, in, out, local, n_row, n_row);
920         if (!bmap)
921                 return NULL;
922
923         for (i = 0; i < local; ++i) {
924                 int k = isl_basic_map_alloc_div(bmap);
925                 if (k < 0)
926                         goto error;
927         }
928
929         for (i = 0; i < n_row; ++i)
930                 bmap = basic_map_read_polylib_constraint(s, bmap);
931
932         tok = isl_stream_next_token_on_same_line(s);
933         if (tok) {
934                 isl_stream_error(s, tok, "unexpected extra token on line");
935                 isl_stream_push_token(s, tok);
936                 goto error;
937         }
938
939         bmap = isl_basic_map_simplify(bmap);
940         bmap = isl_basic_map_finalize(bmap);
941         return bmap;
942 error:
943         isl_basic_map_free(bmap);
944         return NULL;
945 }
946
947 static struct isl_map *map_read_polylib(struct isl_stream *s, int nparam)
948 {
949         struct isl_token *tok;
950         struct isl_token *tok2;
951         int i, n;
952         struct isl_map *map;
953
954         tok = isl_stream_next_token(s);
955         if (!tok) {
956                 isl_stream_error(s, NULL, "unexpected EOF");
957                 return NULL;
958         }
959         tok2 = isl_stream_next_token_on_same_line(s);
960         if (tok2) {
961                 isl_stream_push_token(s, tok2);
962                 isl_stream_push_token(s, tok);
963                 return isl_map_from_basic_map(basic_map_read_polylib(s, nparam));
964         }
965         n = isl_int_get_si(tok->u.v);
966         isl_token_free(tok);
967
968         isl_assert(s->ctx, n >= 1, return NULL);
969
970         map = isl_map_from_basic_map(basic_map_read_polylib(s, nparam));
971
972         for (i = 1; i < n; ++i)
973                 map = isl_map_union(map,
974                         isl_map_from_basic_map(basic_map_read_polylib(s, nparam)));
975
976         return map;
977 }
978
979 static int optional_power(struct isl_stream *s)
980 {
981         int pow;
982         struct isl_token *tok;
983
984         tok = isl_stream_next_token(s);
985         if (!tok)
986                 return 1;
987         if (tok->type != '^') {
988                 isl_stream_push_token(s, tok);
989                 return 1;
990         }
991         isl_token_free(tok);
992         tok = isl_stream_next_token(s);
993         if (!tok || tok->type != ISL_TOKEN_VALUE) {
994                 isl_stream_error(s, tok, "expecting exponent");
995                 if (tok)
996                         isl_stream_push_token(s, tok);
997                 return 1;
998         }
999         pow = isl_int_get_si(tok->u.v);
1000         isl_token_free(tok);
1001         return pow;
1002 }
1003
1004 static __isl_give isl_div *read_div(struct isl_stream *s,
1005         __isl_keep isl_basic_map *bmap, struct vars *v)
1006 {
1007         unsigned total = isl_basic_map_total_dim(bmap);
1008         int k;
1009
1010         bmap = isl_basic_map_copy(bmap);
1011         bmap = isl_basic_map_cow(bmap);
1012         bmap = isl_basic_map_extend_dim(bmap, isl_dim_copy(bmap->dim),
1013                                         1, 0, 2);
1014
1015         if ((k = isl_basic_map_alloc_div(bmap)) < 0)
1016                 goto error;
1017         isl_seq_clr(bmap->div[k], 1 + 1 + total);
1018         bmap = add_div_definition(s, v, bmap, k);
1019
1020         return isl_basic_map_div(bmap, k);
1021 error:
1022         isl_basic_map_free(bmap);
1023         return NULL;
1024 }
1025
1026 static __isl_give isl_qpolynomial *read_term(struct isl_stream *s,
1027         __isl_keep isl_basic_map *bmap, struct vars *v);
1028
1029 static __isl_give isl_qpolynomial *read_factor(struct isl_stream *s,
1030         __isl_keep isl_basic_map *bmap, struct vars *v)
1031 {
1032         struct isl_qpolynomial *qp;
1033         struct isl_token *tok;
1034
1035         tok = isl_stream_next_token(s);
1036         if (!tok) {
1037                 isl_stream_error(s, NULL, "unexpected EOF");
1038                 return NULL;
1039         }
1040         if (tok->type == '(') {
1041                 isl_token_free(tok);
1042                 qp = read_term(s, bmap, v);
1043                 if (!qp)
1044                         return NULL;
1045                 if (isl_stream_eat(s, ')'))
1046                         goto error;
1047         } else if (tok->type == ISL_TOKEN_VALUE) {
1048                 struct isl_token *tok2;
1049                 tok2 = isl_stream_next_token(s);
1050                 if (tok2 && tok2->type == '/') {
1051                         isl_token_free(tok2);
1052                         tok2 = isl_stream_next_token(s);
1053                         if (!tok2 || tok2->type != ISL_TOKEN_VALUE) {
1054                                 isl_stream_error(s, tok2, "expected denominator");
1055                                 isl_token_free(tok);
1056                                 isl_token_free(tok2);
1057                                 return NULL;
1058                         }
1059                         qp = isl_qpolynomial_rat_cst(isl_basic_map_get_dim(bmap),
1060                                                     tok->u.v, tok2->u.v);
1061                         isl_token_free(tok2);
1062                 } else {
1063                         isl_stream_push_token(s, tok2);
1064                         qp = isl_qpolynomial_cst(isl_basic_map_get_dim(bmap),
1065                                                 tok->u.v);
1066                 }
1067                 isl_token_free(tok);
1068         } else if (tok->type == ISL_TOKEN_INFTY) {
1069                 isl_token_free(tok);
1070                 qp = isl_qpolynomial_infty(isl_basic_map_get_dim(bmap));
1071         } else if (tok->type == ISL_TOKEN_NAN) {
1072                 isl_token_free(tok);
1073                 qp = isl_qpolynomial_nan(isl_basic_map_get_dim(bmap));
1074         } else if (tok->type == ISL_TOKEN_IDENT) {
1075                 int n = v->n;
1076                 int pos = vars_pos(v, tok->u.s, -1);
1077                 int pow;
1078                 isl_token_free(tok);
1079                 if (pos < 0)
1080                         goto error;
1081                 if (pos >= n) {
1082                         isl_stream_error(s, tok, "unknown identifier");
1083                         return NULL;
1084                 }
1085                 pow = optional_power(s);
1086                 qp = isl_qpolynomial_pow(isl_basic_map_get_dim(bmap), pos, pow);
1087         } else if (tok->type == '[') {
1088                 isl_div *div;
1089                 int pow;
1090
1091                 isl_stream_push_token(s, tok);
1092                 div = read_div(s, bmap, v);
1093                 pow = optional_power(s);
1094                 qp = isl_qpolynomial_div_pow(div, pow);
1095         } else if (tok->type == '-') {
1096                 struct isl_qpolynomial *qp2;
1097
1098                 isl_token_free(tok);
1099                 qp = isl_qpolynomial_cst(isl_basic_map_get_dim(bmap),
1100                                             s->ctx->negone);
1101                 qp2 = read_factor(s, bmap, v);
1102                 qp = isl_qpolynomial_mul(qp, qp2);
1103         } else {
1104                 isl_stream_error(s, tok, "unexpected isl_token");
1105                 isl_stream_push_token(s, tok);
1106                 return NULL;
1107         }
1108
1109         if (isl_stream_eat_if_available(s, '*') ||
1110             isl_stream_next_token_is(s, ISL_TOKEN_IDENT)) {
1111                 struct isl_qpolynomial *qp2;
1112
1113                 qp2 = read_factor(s, bmap, v);
1114                 qp = isl_qpolynomial_mul(qp, qp2);
1115         }
1116
1117         return qp;
1118 error:
1119         isl_qpolynomial_free(qp);
1120         return NULL;
1121 }
1122
1123 static __isl_give isl_qpolynomial *read_term(struct isl_stream *s,
1124         __isl_keep isl_basic_map *bmap, struct vars *v)
1125 {
1126         struct isl_token *tok;
1127         struct isl_qpolynomial *qp;
1128
1129         qp = read_factor(s, bmap, v);
1130
1131         for (;;) {
1132                 tok = isl_stream_next_token(s);
1133                 if (!tok)
1134                         return qp;
1135
1136                 if (tok->type == '+') {
1137                         struct isl_qpolynomial *qp2;
1138
1139                         isl_token_free(tok);
1140                         qp2 = read_factor(s, bmap, v);
1141                         qp = isl_qpolynomial_add(qp, qp2);
1142                 } else if (tok->type == '-') {
1143                         struct isl_qpolynomial *qp2;
1144
1145                         isl_token_free(tok);
1146                         qp2 = read_factor(s, bmap, v);
1147                         qp = isl_qpolynomial_sub(qp, qp2);
1148                 } else if (tok->type == ISL_TOKEN_VALUE &&
1149                             isl_int_is_neg(tok->u.v)) {
1150                         struct isl_qpolynomial *qp2;
1151
1152                         qp2 = isl_qpolynomial_cst(isl_basic_map_get_dim(bmap),
1153                                                         tok->u.v);
1154                         isl_token_free(tok);
1155                         qp = isl_qpolynomial_add(qp, qp2);
1156                 } else {
1157                         isl_stream_push_token(s, tok);
1158                         break;
1159                 }
1160         }
1161
1162         return qp;
1163 }
1164
1165 static __isl_give isl_map *read_optional_disjuncts(struct isl_stream *s,
1166         __isl_take isl_basic_map *bmap, struct vars *v)
1167 {
1168         struct isl_token *tok;
1169         struct isl_map *map;
1170
1171         tok = isl_stream_next_token(s);
1172         if (!tok) {
1173                 isl_stream_error(s, NULL, "unexpected EOF");
1174                 goto error;
1175         }
1176         map = isl_map_from_basic_map(isl_basic_map_copy(bmap));
1177         if (tok->type == ':') {
1178                 isl_token_free(tok);
1179                 map = isl_map_intersect(map,
1180                             read_disjuncts(s, v, isl_basic_map_get_dim(bmap)));
1181         } else
1182                 isl_stream_push_token(s, tok);
1183
1184         isl_basic_map_free(bmap);
1185
1186         return map;
1187 error:
1188         isl_basic_map_free(bmap);
1189         return NULL;
1190 }
1191
1192 static struct isl_obj obj_read_poly(struct isl_stream *s,
1193         __isl_take isl_basic_map *bmap, struct vars *v, int n)
1194 {
1195         struct isl_obj obj = { isl_obj_pw_qpolynomial, NULL };
1196         struct isl_pw_qpolynomial *pwqp;
1197         struct isl_qpolynomial *qp;
1198         struct isl_map *map;
1199         struct isl_set *set;
1200
1201         bmap = isl_basic_map_reverse(bmap);
1202
1203         qp = read_term(s, bmap, v);
1204         map = read_optional_disjuncts(s, bmap, v);
1205         set = isl_set_from_map(map);
1206
1207         pwqp = isl_pw_qpolynomial_alloc(set, qp);
1208
1209         vars_drop(v, v->n - n);
1210
1211         obj.v = pwqp;
1212         return obj;
1213 }
1214
1215 static struct isl_obj obj_read_body(struct isl_stream *s,
1216         __isl_take isl_basic_map *bmap, struct vars *v, isl_obj_type type)
1217 {
1218         struct isl_map *map = NULL;
1219         struct isl_token *tok;
1220         struct isl_obj obj = { type, NULL };
1221         int n = v->n;
1222
1223         if (!isl_stream_next_token_is(s, '['))
1224                 return obj_read_poly(s, bmap, v, n);
1225
1226         bmap = read_tuple(s, bmap, isl_dim_in, v);
1227         if (!bmap)
1228                 goto error;
1229         tok = isl_stream_next_token(s);
1230         if (tok && tok->type == ISL_TOKEN_TO) {
1231                 obj.type = isl_obj_map;
1232                 isl_token_free(tok);
1233                 tok = isl_stream_next_token(s);
1234                 if (tok && tok->type != '[') {
1235                         isl_stream_push_token(s, tok);
1236                         return obj_read_poly(s, bmap, v, n);
1237                 }
1238                 isl_stream_push_token(s, tok);
1239                 bmap = read_tuple(s, bmap, isl_dim_out, v);
1240                 if (!bmap)
1241                         goto error;
1242         } else {
1243                 bmap = isl_basic_map_reverse(bmap);
1244                 if (tok)
1245                         isl_stream_push_token(s, tok);
1246         }
1247
1248         map = read_optional_disjuncts(s, bmap, v);
1249
1250         vars_drop(v, v->n - n);
1251
1252         obj.v = map;
1253         return obj;
1254 error:
1255         isl_basic_map_free(bmap);
1256         obj.type = isl_obj_none;
1257         return obj;
1258 }
1259
1260 static struct isl_obj obj_add(struct isl_ctx *ctx,
1261         struct isl_obj obj1, struct isl_obj obj2)
1262 {
1263         isl_assert(ctx, obj1.type == obj2.type, goto error);
1264         obj1.v = obj1.type->add(obj1.v, obj2.v);
1265         return obj1;
1266 error:
1267         obj1.type->free(obj1.v);
1268         obj2.type->free(obj2.v);
1269         obj1.type = isl_obj_none;
1270         obj1.v = NULL;
1271         return obj1;
1272 }
1273
1274 static struct isl_obj obj_read(struct isl_stream *s, int nparam)
1275 {
1276         struct isl_basic_map *bmap = NULL;
1277         struct isl_token *tok;
1278         struct vars *v = NULL;
1279         struct isl_obj obj = { isl_obj_set, NULL };
1280
1281         tok = isl_stream_next_token(s);
1282         if (!tok) {
1283                 isl_stream_error(s, NULL, "unexpected EOF");
1284                 goto error;
1285         }
1286         if (tok->type == ISL_TOKEN_VALUE) {
1287                 struct isl_map *map;
1288                 isl_stream_push_token(s, tok);
1289                 map = map_read_polylib(s, nparam);
1290                 if (!map)
1291                         goto error;
1292                 if (isl_map_dim(map, isl_dim_in) > 0)
1293                         obj.type = isl_obj_map;
1294                 obj.v = map;
1295                 return obj;
1296         }
1297         v = vars_new(s->ctx);
1298         bmap = isl_basic_map_alloc(s->ctx, 0, 0, 0, 0, 0, 0);
1299         if (tok->type == '[') {
1300                 isl_stream_push_token(s, tok);
1301                 bmap = read_tuple(s, bmap, isl_dim_param, v);
1302                 if (!bmap)
1303                         goto error;
1304                 if (nparam >= 0)
1305                         isl_assert(s->ctx, nparam == v->n, goto error);
1306                 tok = isl_stream_next_token(s);
1307                 if (!tok || tok->type != ISL_TOKEN_TO) {
1308                         isl_stream_error(s, tok, "expecting '->'");
1309                         if (tok)
1310                                 isl_stream_push_token(s, tok);
1311                         goto error;
1312                 }
1313                 isl_token_free(tok);
1314                 tok = isl_stream_next_token(s);
1315         } if (nparam > 0)
1316                 bmap = isl_basic_map_add(bmap, isl_dim_param, nparam);
1317         if (!tok || tok->type != '{') {
1318                 isl_stream_error(s, tok, "expecting '{'");
1319                 if (tok)
1320                         isl_stream_push_token(s, tok);
1321                 goto error;
1322         }
1323         isl_token_free(tok);
1324
1325         for (;;) {
1326                 struct isl_obj o;
1327                 tok = NULL;
1328                 o = obj_read_body(s, isl_basic_map_copy(bmap), v, obj.type);
1329                 if (o.type == isl_obj_none)
1330                         break;
1331                 if (!obj.v)
1332                         obj = o;
1333                 else {
1334                         obj = obj_add(s->ctx, obj, o);
1335                         if (obj.type == isl_obj_none)
1336                                 break;
1337                 }
1338                 tok = isl_stream_next_token(s);
1339                 if (!tok || tok->type != ';')
1340                         break;
1341                 isl_token_free(tok);
1342         }
1343
1344         if (tok && tok->type == '}') {
1345                 isl_token_free(tok);
1346         } else {
1347                 isl_stream_error(s, tok, "unexpected isl_token");
1348                 if (tok)
1349                         isl_token_free(tok);
1350                 goto error;
1351         }
1352         vars_free(v);
1353         isl_basic_map_free(bmap);
1354
1355         return obj;
1356 error:
1357         isl_basic_map_free(bmap);
1358         obj.type->free(obj.v);
1359         if (v)
1360                 vars_free(v);
1361         obj.v = NULL;
1362         return obj;
1363 }
1364
1365 struct isl_obj isl_stream_read_obj(struct isl_stream *s)
1366 {
1367         return obj_read(s, -1);
1368 }
1369
1370 static struct isl_basic_map *basic_map_read(struct isl_stream *s, int nparam)
1371 {
1372         struct isl_obj obj;
1373         struct isl_map *map;
1374         struct isl_basic_map *bmap;
1375
1376         obj = obj_read(s, nparam);
1377         map = obj.v;
1378         if (!map)
1379                 return NULL;
1380
1381         isl_assert(map->ctx, map->n <= 1, goto error);
1382
1383         if (map->n == 0)
1384                 bmap = isl_basic_map_empty_like_map(map);
1385         else
1386                 bmap = isl_basic_map_copy(map->p[0]);
1387
1388         isl_map_free(map);
1389
1390         return bmap;
1391 error:
1392         isl_map_free(map);
1393         return NULL;
1394 }
1395
1396 __isl_give isl_basic_map *isl_basic_map_read_from_file(isl_ctx *ctx,
1397                 FILE *input, int nparam)
1398 {
1399         struct isl_basic_map *bmap;
1400         struct isl_stream *s = isl_stream_new_file(ctx, input);
1401         if (!s)
1402                 return NULL;
1403         bmap = basic_map_read(s, nparam);
1404         isl_stream_free(s);
1405         return bmap;
1406 }
1407
1408 __isl_give isl_basic_set *isl_basic_set_read_from_file(isl_ctx *ctx,
1409                 FILE *input, int nparam)
1410 {
1411         struct isl_basic_map *bmap;
1412         bmap = isl_basic_map_read_from_file(ctx, input, nparam);
1413         if (!bmap)
1414                 return NULL;
1415         isl_assert(ctx, isl_basic_map_n_in(bmap) == 0, goto error);
1416         return (struct isl_basic_set *)bmap;
1417 error:
1418         isl_basic_map_free(bmap);
1419         return NULL;
1420 }
1421
1422 struct isl_basic_map *isl_basic_map_read_from_str(struct isl_ctx *ctx,
1423                 const char *str, int nparam)
1424 {
1425         struct isl_basic_map *bmap;
1426         struct isl_stream *s = isl_stream_new_str(ctx, str);
1427         if (!s)
1428                 return NULL;
1429         bmap = basic_map_read(s, nparam);
1430         isl_stream_free(s);
1431         return bmap;
1432 }
1433
1434 struct isl_basic_set *isl_basic_set_read_from_str(struct isl_ctx *ctx,
1435                 const char *str, int nparam)
1436 {
1437         struct isl_basic_map *bmap;
1438         bmap = isl_basic_map_read_from_str(ctx, str, nparam);
1439         if (!bmap)
1440                 return NULL;
1441         isl_assert(ctx, isl_basic_map_n_in(bmap) == 0, goto error);
1442         return (struct isl_basic_set *)bmap;
1443 error:
1444         isl_basic_map_free(bmap);
1445         return NULL;
1446 }
1447
1448 __isl_give isl_map *isl_map_read_from_file(struct isl_ctx *ctx,
1449                 FILE *input, int nparam)
1450 {
1451         struct isl_obj obj;
1452         struct isl_map *map;
1453         struct isl_stream *s = isl_stream_new_file(ctx, input);
1454         if (!s)
1455                 return NULL;
1456         obj = obj_read(s, nparam);
1457         isl_stream_free(s);
1458         return obj.v;
1459 }
1460
1461 __isl_give isl_map *isl_map_read_from_str(struct isl_ctx *ctx,
1462                 const char *str, int nparam)
1463 {
1464         struct isl_obj obj;
1465         struct isl_map *map;
1466         struct isl_stream *s = isl_stream_new_str(ctx, str);
1467         if (!s)
1468                 return NULL;
1469         obj = obj_read(s, nparam);
1470         isl_stream_free(s);
1471         return obj.v;
1472 }
1473
1474 __isl_give isl_set *isl_set_read_from_file(struct isl_ctx *ctx,
1475                 FILE *input, int nparam)
1476 {
1477         struct isl_map *map;
1478         map = isl_map_read_from_file(ctx, input, nparam);
1479         if (!map)
1480                 return NULL;
1481         isl_assert(ctx, isl_map_n_in(map) == 0, goto error);
1482         return (struct isl_set *)map;
1483 error:
1484         isl_map_free(map);
1485         return NULL;
1486 }
1487
1488 struct isl_set *isl_set_read_from_str(struct isl_ctx *ctx,
1489                 const char *str, int nparam)
1490 {
1491         struct isl_map *map;
1492         map = isl_map_read_from_str(ctx, str, nparam);
1493         if (!map)
1494                 return NULL;
1495         isl_assert(ctx, isl_map_n_in(map) == 0, goto error);
1496         return (struct isl_set *)map;
1497 error:
1498         isl_map_free(map);
1499         return NULL;
1500 }
1501
1502 static char *next_line(FILE *input, char *line, unsigned len)
1503 {
1504         char *p;
1505
1506         do {
1507                 if (!(p = fgets(line, len, input)))
1508                         return NULL;
1509                 while (isspace(*p) && *p != '\n')
1510                         ++p;
1511         } while (*p == '#' || *p == '\n');
1512
1513         return p;
1514 }
1515
1516 static struct isl_vec *isl_vec_read_from_file_polylib(struct isl_ctx *ctx,
1517                 FILE *input)
1518 {
1519         struct isl_vec *vec = NULL;
1520         char line[1024];
1521         char val[1024];
1522         char *p;
1523         unsigned size;
1524         int j;
1525         int n;
1526         int offset;
1527
1528         isl_assert(ctx, next_line(input, line, sizeof(line)), return NULL);
1529         isl_assert(ctx, sscanf(line, "%u", &size) == 1, return NULL);
1530
1531         vec = isl_vec_alloc(ctx, size);
1532
1533         p = next_line(input, line, sizeof(line));
1534         isl_assert(ctx, p, goto error);
1535
1536         for (j = 0; j < size; ++j) {
1537                 n = sscanf(p, "%s%n", val, &offset);
1538                 isl_assert(ctx, n != 0, goto error);
1539                 isl_int_read(vec->el[j], val);
1540                 p += offset;
1541         }
1542
1543         return vec;
1544 error:
1545         isl_vec_free(vec);
1546         return NULL;
1547 }
1548
1549 struct isl_vec *isl_vec_read_from_file(struct isl_ctx *ctx,
1550                 FILE *input, unsigned input_format)
1551 {
1552         if (input_format == ISL_FORMAT_POLYLIB)
1553                 return isl_vec_read_from_file_polylib(ctx, input);
1554         else
1555                 isl_assert(ctx, 0, return NULL);
1556 }