add isl_set_fix_si
[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_stream.h"
20 #include "isl_map_private.h"
21
22 struct variable {
23         char                    *name;
24         int                      pos;
25         struct variable         *next;
26 };
27
28 struct vars {
29         struct isl_ctx  *ctx;
30         int              n;
31         struct variable *v;
32 };
33
34 static struct vars *vars_new(struct isl_ctx *ctx)
35 {
36         struct vars *v;
37         v = isl_alloc_type(ctx, struct vars);
38         if (!v)
39                 return NULL;
40         v->ctx = ctx;
41         v->n = 0;
42         v->v = NULL;
43         return v;
44 }
45
46 static void variable_free(struct variable *var)
47 {
48         while (var) {
49                 struct variable *next = var->next;
50                 free(var->name);
51                 free(var);
52                 var = next;
53         }
54 }
55
56 static void vars_free(struct vars *v)
57 {
58         if (!v)
59                 return;
60         variable_free(v->v);
61         free(v);
62 }
63
64 static void vars_drop(struct vars *v, int n)
65 {
66         struct variable *var;
67
68         if (!v)
69                 return;
70
71         v->n -= n;
72
73         var = v->v;
74         while (--n >= 0) {
75                 struct variable *next = var->next;
76                 free(var->name);
77                 free(var);
78                 var = next;
79         }
80         v->v = var;
81 }
82
83 static struct variable *variable_new(struct vars *v, const char *name, int len,
84                                 int pos)
85 {
86         struct variable *var;
87         var = isl_alloc_type(v->ctx, struct variable);
88         if (!var)
89                 goto error;
90         var->name = strdup(name);
91         var->name[len] = '\0';
92         var->pos = pos;
93         var->next = v->v;
94         return var;
95 error:
96         variable_free(v->v);
97         return NULL;
98 }
99
100 static int vars_pos(struct vars *v, const char *s, int len)
101 {
102         int pos;
103         struct variable *q;
104
105         if (len == -1)
106                 len = strlen(s);
107         for (q = v->v; q; q = q->next) {
108                 if (strncmp(q->name, s, len) == 0 && q->name[len] == '\0')
109                         break;
110         }
111         if (q)
112                 pos = q->pos;
113         else {
114                 pos = v->n;
115                 v->v = variable_new(v, s, len, v->n);
116                 if (!v->v)
117                         return -1;
118                 v->n++;
119         }
120         return pos;
121 }
122
123 static struct vars *read_var_list(struct isl_stream *s, struct vars *v)
124 {
125         struct isl_token *tok;
126
127         while ((tok = isl_stream_next_token(s)) != NULL) {
128                 int p;
129                 int n = v->n;
130
131                 if (tok->type != ISL_TOKEN_IDENT)
132                         break;
133
134                 p = vars_pos(v, tok->u.s, -1);
135                 if (p < 0)
136                         goto error;
137                 if (p < n) {
138                         isl_stream_error(s, tok, "expecting unique identifier");
139                         goto error;
140                 }
141                 isl_token_free(tok);
142                 tok = isl_stream_next_token(s);
143                 if (!tok || tok->type != ',')
144                         break;
145
146                 isl_token_free(tok);
147         }
148         if (tok)
149                 isl_stream_push_token(s, tok);
150
151         return v;
152 error:
153         isl_token_free(tok);
154         vars_free(v);
155         return NULL;
156 }
157
158 static struct isl_vec *accept_affine(struct isl_stream *s, struct vars *v)
159 {
160         struct isl_token *tok = NULL;
161         struct isl_vec *aff;
162         int sign = 1;
163
164         aff = isl_vec_alloc(v->ctx, 1 + v->n);
165         isl_seq_clr(aff->el, aff->size);
166         if (!aff)
167                 return NULL;
168
169         for (;;) {
170                 tok = isl_stream_next_token(s);
171                 if (!tok) {
172                         isl_stream_error(s, NULL, "unexpected EOF");
173                         goto error;
174                 }
175                 if (tok->type == ISL_TOKEN_IDENT) {
176                         int n = v->n;
177                         int pos = vars_pos(v, tok->u.s, -1);
178                         if (pos < 0)
179                                 goto error;
180                         if (pos >= n) {
181                                 isl_stream_error(s, tok, "unknown identifier");
182                                 goto error;
183                         }
184                         if (sign > 0)
185                                 isl_int_add_ui(aff->el[1 + pos],
186                                                aff->el[1 + pos], 1);
187                         else
188                                 isl_int_sub_ui(aff->el[1 + pos],
189                                                aff->el[1 + pos], 1);
190                         sign = 1;
191                 } else if (tok->type == ISL_TOKEN_VALUE) {
192                         struct isl_token *tok2;
193                         int n = v->n;
194                         int pos = -1;
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(tok2);
204                                         goto error;
205                                 }
206                                 isl_token_free(tok2);
207                         } else if (tok2)
208                                 isl_stream_push_token(s, tok2);
209                         if (sign < 0)
210                                 isl_int_neg(tok->u.v, tok->u.v);
211                         isl_int_add(aff->el[1 + pos],
212                                         aff->el[1 + pos], tok->u.v);
213                         sign = 1;
214                 } else if (tok->type == '-') {
215                         sign = -sign;
216                 } else if (tok->type == '+') {
217                         /* nothing */
218                 } else {
219                         isl_stream_push_token(s, tok);
220                         break;
221                 }
222                 isl_token_free(tok);
223         }
224
225         return aff;
226 error:
227         isl_vec_free(aff);
228         return NULL;
229 }
230
231 static __isl_give isl_mat *accept_affine_list(struct isl_stream *s,
232         struct vars *v)
233 {
234         struct isl_vec *vec;
235         struct isl_mat *mat;
236         struct isl_token *tok = NULL;
237
238         vec = accept_affine(s, v);
239         mat = isl_mat_from_row_vec(vec);
240         if (!mat)
241                 return NULL;
242
243         for (;;) {
244                 tok = isl_stream_next_token(s);
245                 if (!tok) {
246                         isl_stream_error(s, NULL, "unexpected EOF");
247                         goto error;
248                 }
249                 if (tok->type != ',') {
250                         isl_stream_push_token(s, tok);
251                         break;
252                 }
253                 isl_token_free(tok);
254
255                 vec = accept_affine(s, v);
256                 mat = isl_mat_vec_concat(mat, vec);
257                 if (!mat)
258                         return NULL;
259         }
260
261         return mat;
262 error:
263         isl_mat_free(mat);
264         return NULL;
265 }
266
267 static struct isl_basic_map *add_div_definition(struct isl_stream *s,
268         struct vars *v, struct isl_basic_map *bmap, int k)
269 {
270         struct isl_token *tok;
271         int seen_paren = 0;
272         struct isl_vec *aff;
273
274         if (isl_stream_eat(s, '['))
275                 goto error;
276
277         tok = isl_stream_next_token(s);
278         if (!tok)
279                 goto error;
280         if (tok->type == '(') {
281                 seen_paren = 1;
282                 isl_token_free(tok);
283         } else
284                 isl_stream_push_token(s, tok);
285
286         aff = accept_affine(s, v);
287         if (!aff)
288                 goto error;
289
290         isl_seq_cpy(bmap->div[k] + 1, aff->el, aff->size);
291
292         isl_vec_free(aff);
293
294         if (seen_paren && isl_stream_eat(s, ')'))
295                 goto error;
296         if (isl_stream_eat(s, '/'))
297                 goto error;
298
299         tok = isl_stream_next_token(s);
300         if (!tok)
301                 goto error;
302         if (tok->type != ISL_TOKEN_VALUE) {
303                 isl_stream_error(s, tok, "expected denominator");
304                 isl_stream_push_token(s, tok);
305                 goto error;
306         }
307         isl_int_set(bmap->div[k][0], tok->u.v);
308         isl_token_free(tok);
309
310         if (isl_stream_eat(s, ']'))
311                 goto error;
312
313         if (isl_basic_map_add_div_constraints(bmap, k) < 0)
314                 goto error;
315
316         return bmap;
317 error:
318         isl_basic_map_free(bmap);
319         return NULL;
320 }
321
322 static struct isl_basic_map *read_defined_var_list(struct isl_stream *s,
323         struct vars *v, struct isl_basic_map *bmap)
324 {
325         struct isl_token *tok;
326
327         while ((tok = isl_stream_next_token(s)) != NULL) {
328                 int k;
329                 int p;
330                 int n = v->n;
331                 unsigned total = isl_basic_map_total_dim(bmap);
332
333                 if (tok->type != ISL_TOKEN_IDENT)
334                         break;
335
336                 p = vars_pos(v, tok->u.s, -1);
337                 if (p < 0)
338                         goto error;
339                 if (p < n) {
340                         isl_stream_error(s, tok, "expecting unique identifier");
341                         goto error;
342                 }
343                 isl_token_free(tok);
344
345                 bmap = isl_basic_map_cow(bmap);
346                 bmap = isl_basic_map_extend_dim(bmap, isl_dim_copy(bmap->dim),
347                                                 1, 0, 2);
348
349                 if ((k = isl_basic_map_alloc_div(bmap)) < 0)
350                         goto error;
351                 isl_seq_clr(bmap->div[k], 1 + 1 + total);
352
353                 tok = isl_stream_next_token(s);
354                 if (tok && tok->type == '=') {
355                         isl_token_free(tok);
356                         bmap = add_div_definition(s, v, bmap, k);
357                         tok = isl_stream_next_token(s);
358                 }
359
360                 if (!tok || tok->type != ',')
361                         break;
362
363                 isl_token_free(tok);
364         }
365         if (tok)
366                 isl_stream_push_token(s, tok);
367
368         return bmap;
369 error:
370         isl_token_free(tok);
371         isl_basic_map_free(bmap);
372         return NULL;
373 }
374
375 static struct vars *read_tuple(struct isl_stream *s, struct vars *v)
376 {
377         struct isl_token *tok;
378
379         tok = isl_stream_next_token(s);
380         if (!tok || tok->type != '[') {
381                 isl_stream_error(s, tok, "expecting '['");
382                 goto error;
383         }
384         isl_token_free(tok);
385         v = read_var_list(s, v);
386         tok = isl_stream_next_token(s);
387         if (!tok || tok->type != ']') {
388                 isl_stream_error(s, tok, "expecting ']'");
389                 goto error;
390         }
391         isl_token_free(tok);
392
393         return v;
394 error:
395         if (tok)
396                 isl_token_free(tok);
397         vars_free(v);
398         return NULL;
399 }
400
401 static struct isl_basic_map *add_constraints(struct isl_stream *s,
402         struct vars *v, struct isl_basic_map *bmap);
403
404 static struct isl_basic_map *add_exists(struct isl_stream *s,
405         struct vars *v, struct isl_basic_map *bmap)
406 {
407         struct isl_token *tok;
408         int n = v->n;
409         int extra;
410         int seen_paren = 0;
411         int i;
412         unsigned total;
413
414         tok = isl_stream_next_token(s);
415         if (!tok)
416                 goto error;
417         if (tok->type == '(') {
418                 seen_paren = 1;
419                 isl_token_free(tok);
420         } else
421                 isl_stream_push_token(s, tok);
422
423         bmap = read_defined_var_list(s, v, bmap);
424         if (!bmap)
425                 goto error;
426
427         if (isl_stream_eat(s, ':'))
428                 goto error;
429         bmap = add_constraints(s, v, bmap);
430         if (seen_paren && isl_stream_eat(s, ')'))
431                 goto error;
432         return bmap;
433 error:
434         isl_basic_map_free(bmap);
435         return NULL;
436 }
437
438 static __isl_give isl_basic_map *construct_constraint(
439         __isl_take isl_basic_map *bmap, enum isl_token_type type,
440         isl_int *left, isl_int *right)
441 {
442         int k;
443         unsigned len;
444         struct isl_ctx *ctx;
445
446         if (!bmap)
447                 return NULL;
448         len = 1 + isl_basic_map_total_dim(bmap);
449         ctx = bmap->ctx;
450
451         k = isl_basic_map_alloc_inequality(bmap);
452         if (k < 0)
453                 goto error;
454         if (type == ISL_TOKEN_LE)
455                 isl_seq_combine(bmap->ineq[k], ctx->negone, left,
456                                                ctx->one, right,
457                                                len);
458         else if (type == ISL_TOKEN_GE)
459                 isl_seq_combine(bmap->ineq[k], ctx->one, left,
460                                                ctx->negone, right,
461                                                len);
462         else if (type == ISL_TOKEN_LT) {
463                 isl_seq_combine(bmap->ineq[k], ctx->negone, left,
464                                                ctx->one, right,
465                                                len);
466                 isl_int_sub_ui(bmap->ineq[k][0], bmap->ineq[k][0], 1);
467         } else if (type == ISL_TOKEN_GT) {
468                 isl_seq_combine(bmap->ineq[k], ctx->one, left,
469                                                ctx->negone, right,
470                                                len);
471                 isl_int_sub_ui(bmap->ineq[k][0], bmap->ineq[k][0], 1);
472         } else {
473                 isl_seq_combine(bmap->ineq[k], ctx->one, left,
474                                                ctx->negone, right,
475                                                len);
476                 isl_basic_map_inequality_to_equality(bmap, k);
477         }
478
479         return bmap;
480 error:
481         isl_basic_map_free(bmap);
482         return NULL;
483 }
484
485 static int is_comparator(struct isl_token *tok)
486 {
487         if (!tok)
488                 return 0;
489
490         switch (tok->type) {
491         case ISL_TOKEN_LT:
492         case ISL_TOKEN_GT:
493         case ISL_TOKEN_LE:
494         case ISL_TOKEN_GE:
495         case '=':
496                 return 1;
497         default:
498                 return 0;
499         }
500 }
501
502 static struct isl_basic_map *add_constraint(struct isl_stream *s,
503         struct vars *v, struct isl_basic_map *bmap)
504 {
505         int i, j;
506         unsigned total = isl_basic_map_total_dim(bmap);
507         struct isl_token *tok = NULL;
508         struct isl_mat *aff1 = NULL, *aff2 = NULL;
509
510         tok = isl_stream_next_token(s);
511         if (!tok)
512                 goto error;
513         if (tok->type == ISL_TOKEN_EXISTS) {
514                 isl_token_free(tok);
515                 return add_exists(s, v, bmap);
516         }
517         isl_stream_push_token(s, tok);
518         tok = NULL;
519
520         bmap = isl_basic_map_cow(bmap);
521
522         aff1 = accept_affine_list(s, v);
523         if (!aff1)
524                 goto error;
525         tok = isl_stream_next_token(s);
526         if (!is_comparator(tok)) {
527                 isl_stream_error(s, tok, "missing operator");
528                 if (tok)
529                         isl_stream_push_token(s, tok);
530                 tok = NULL;
531                 goto error;
532         }
533         isl_assert(aff1->ctx, aff1->n_col == 1 + total, goto error);
534         for (;;) {
535                 aff2 = accept_affine_list(s, v);
536                 if (!aff2)
537                         goto error;
538                 isl_assert(aff2->ctx, aff2->n_col == 1 + total, goto error);
539
540                 bmap = isl_basic_map_extend_constraints(bmap, 0,
541                                                 aff1->n_row * aff2->n_row);
542                 for (i = 0; i < aff1->n_row; ++i)
543                         for (j = 0; j < aff2->n_row; ++j)
544                                 bmap = construct_constraint(bmap, tok->type,
545                                                     aff1->row[i], aff2->row[j]);
546                 isl_token_free(tok);
547                 isl_mat_free(aff1);
548                 aff1 = aff2;
549
550                 tok = isl_stream_next_token(s);
551                 if (!is_comparator(tok)) {
552                         if (tok)
553                                 isl_stream_push_token(s, tok);
554                         break;
555                 }
556         }
557         isl_mat_free(aff1);
558
559         return bmap;
560 error:
561         if (tok)
562                 isl_token_free(tok);
563         isl_mat_free(aff1);
564         isl_mat_free(aff2);
565         isl_basic_map_free(bmap);
566         return NULL;
567 }
568
569 static struct isl_basic_map *add_constraints(struct isl_stream *s,
570         struct vars *v, struct isl_basic_map *bmap)
571 {
572         struct isl_token *tok;
573
574         for (;;) {
575                 bmap = add_constraint(s, v, bmap);
576                 if (!bmap)
577                         return NULL;
578                 tok = isl_stream_next_token(s);
579                 if (!tok) {
580                         isl_stream_error(s, NULL, "unexpected EOF");
581                         goto error;
582                 }
583                 if (tok->type != ISL_TOKEN_AND)
584                         break;
585                 isl_token_free(tok);
586         }
587         isl_stream_push_token(s, tok);
588
589         return bmap;
590 error:
591         if (tok)
592                 isl_token_free(tok);
593         isl_basic_map_free(bmap);
594         return NULL;
595 }
596
597 static struct isl_basic_map *read_disjunct(struct isl_stream *s,
598         struct vars *v, __isl_take isl_dim *dim)
599 {
600         struct isl_basic_map *bmap;
601
602         bmap = isl_basic_map_alloc_dim(dim, 0, 0, 0);
603         if (!bmap)
604                 return NULL;
605
606         bmap = add_constraints(s, v, bmap);
607         bmap = isl_basic_map_simplify(bmap);
608         bmap = isl_basic_map_finalize(bmap);
609         return bmap;
610 }
611
612 static struct isl_map *read_disjuncts(struct isl_stream *s,
613         struct vars *v, __isl_take isl_dim *dim)
614 {
615         struct isl_token *tok;
616         struct isl_map *map;
617
618         tok = isl_stream_next_token(s);
619         if (!tok) {
620                 isl_stream_error(s, NULL, "unexpected EOF");
621                 goto error;
622         }
623         if (tok->type == '}') {
624                 isl_stream_push_token(s, tok);
625                 return isl_map_universe(dim);
626         }
627         isl_stream_push_token(s, tok);
628
629         map = isl_map_empty(isl_dim_copy(dim));
630         for (;;) {
631                 struct isl_basic_map *bmap;
632                 int n = v->n;
633
634                 bmap = read_disjunct(s, v, isl_dim_copy(dim));
635                 map = isl_map_union(map, isl_map_from_basic_map(bmap));
636
637                 vars_drop(v, v->n - n);
638
639                 tok = isl_stream_next_token(s);
640                 if (!tok || tok->type != ISL_TOKEN_OR)
641                         break;
642                 isl_token_free(tok);
643         }
644         if (tok)
645                 isl_stream_push_token(s, tok);
646
647         isl_dim_free(dim);
648         return map;
649 error:
650         isl_dim_free(dim);
651         return NULL;
652 }
653
654 static int polylib_pos_to_isl_pos(__isl_keep isl_basic_map *bmap, int pos)
655 {
656         if (pos < isl_basic_map_dim(bmap, isl_dim_out))
657                 return 1 + isl_basic_map_dim(bmap, isl_dim_param) +
658                            isl_basic_map_dim(bmap, isl_dim_in) + pos;
659         pos -= isl_basic_map_dim(bmap, isl_dim_out);
660
661         if (pos < isl_basic_map_dim(bmap, isl_dim_in))
662                 return 1 + isl_basic_map_dim(bmap, isl_dim_param) + pos;
663         pos -= isl_basic_map_dim(bmap, isl_dim_in);
664
665         if (pos < isl_basic_map_dim(bmap, isl_dim_div))
666                 return 1 + isl_basic_map_dim(bmap, isl_dim_param) +
667                            isl_basic_map_dim(bmap, isl_dim_in) +
668                            isl_basic_map_dim(bmap, isl_dim_out) + pos;
669         pos -= isl_basic_map_dim(bmap, isl_dim_div);
670
671         if (pos < isl_basic_map_dim(bmap, isl_dim_param))
672                 return 1 + pos;
673
674         return 0;
675 }
676
677 static __isl_give isl_basic_map *basic_map_read_polylib_constraint(
678         struct isl_stream *s, __isl_take isl_basic_map *bmap)
679 {
680         int j;
681         struct isl_token *tok;
682         int type;
683         int k;
684         isl_int *c;
685         unsigned nparam;
686         unsigned dim;
687
688         if (!bmap)
689                 return NULL;
690
691         nparam = isl_basic_map_dim(bmap, isl_dim_param);
692         dim = isl_basic_map_dim(bmap, isl_dim_out);
693
694         tok = isl_stream_next_token(s);
695         if (!tok || tok->type != ISL_TOKEN_VALUE) {
696                 isl_stream_error(s, tok, "expecting coefficient");
697                 if (tok)
698                         isl_stream_push_token(s, tok);
699                 goto error;
700         }
701         if (!tok->on_new_line) {
702                 isl_stream_error(s, tok, "coefficient should appear on new line");
703                 isl_stream_push_token(s, tok);
704                 goto error;
705         }
706
707         type = isl_int_get_si(tok->u.v);
708         isl_token_free(tok);
709
710         isl_assert(s->ctx, type == 0 || type == 1, goto error);
711         if (type == 0) {
712                 k = isl_basic_map_alloc_equality(bmap);
713                 c = bmap->eq[k];
714         } else {
715                 k = isl_basic_map_alloc_inequality(bmap);
716                 c = bmap->ineq[k];
717         }
718         if (k < 0)
719                 goto error;
720
721         for (j = 0; j < 1 + isl_basic_map_total_dim(bmap); ++j) {
722                 int pos;
723                 tok = isl_stream_next_token(s);
724                 if (!tok || tok->type != ISL_TOKEN_VALUE) {
725                         isl_stream_error(s, tok, "expecting coefficient");
726                         if (tok)
727                                 isl_stream_push_token(s, tok);
728                         goto error;
729                 }
730                 if (tok->on_new_line) {
731                         isl_stream_error(s, tok,
732                                 "coefficient should not appear on new line");
733                         isl_stream_push_token(s, tok);
734                         goto error;
735                 }
736                 pos = polylib_pos_to_isl_pos(bmap, j);
737                 isl_int_set(c[pos], tok->u.v);
738                 isl_token_free(tok);
739         }
740
741         return bmap;
742 error:
743         isl_basic_map_free(bmap);
744         return NULL;
745 }
746
747 static __isl_give isl_basic_map *basic_map_read_polylib(struct isl_stream *s,
748         int nparam)
749 {
750         int i;
751         struct isl_token *tok;
752         struct isl_token *tok2;
753         int n_row, n_col;
754         int on_new_line;
755         unsigned in = 0, out, local = 0;
756         struct isl_basic_map *bmap = NULL;
757
758         if (nparam < 0)
759                 nparam = 0;
760
761         tok = isl_stream_next_token(s);
762         if (!tok) {
763                 isl_stream_error(s, NULL, "unexpected EOF");
764                 return NULL;
765         }
766         tok2 = isl_stream_next_token(s);
767         if (!tok2) {
768                 isl_token_free(tok);
769                 isl_stream_error(s, NULL, "unexpected EOF");
770                 return NULL;
771         }
772         n_row = isl_int_get_si(tok->u.v);
773         n_col = isl_int_get_si(tok2->u.v);
774         on_new_line = tok2->on_new_line;
775         isl_token_free(tok2);
776         isl_token_free(tok);
777         isl_assert(s->ctx, !on_new_line, return NULL);
778         isl_assert(s->ctx, n_row >= 0, return NULL);
779         isl_assert(s->ctx, n_col >= 2 + nparam, return NULL);
780         tok = isl_stream_next_token_on_same_line(s);
781         if (tok) {
782                 if (tok->type != ISL_TOKEN_VALUE) {
783                         isl_stream_error(s, tok,
784                                     "expecting number of output dimensions");
785                         isl_stream_push_token(s, tok);
786                         goto error;
787                 }
788                 out = isl_int_get_si(tok->u.v);
789                 isl_token_free(tok);
790
791                 tok = isl_stream_next_token_on_same_line(s);
792                 if (!tok || tok->type != ISL_TOKEN_VALUE) {
793                         isl_stream_error(s, tok,
794                                     "expecting number of input dimensions");
795                         if (tok)
796                                 isl_stream_push_token(s, tok);
797                         goto error;
798                 }
799                 in = isl_int_get_si(tok->u.v);
800                 isl_token_free(tok);
801
802                 tok = isl_stream_next_token_on_same_line(s);
803                 if (!tok || tok->type != ISL_TOKEN_VALUE) {
804                         isl_stream_error(s, tok,
805                                     "expecting number of existentials");
806                         if (tok)
807                                 isl_stream_push_token(s, tok);
808                         goto error;
809                 }
810                 local = isl_int_get_si(tok->u.v);
811                 isl_token_free(tok);
812
813                 tok = isl_stream_next_token_on_same_line(s);
814                 if (!tok || tok->type != ISL_TOKEN_VALUE) {
815                         isl_stream_error(s, tok,
816                                     "expecting number of parameters");
817                         if (tok)
818                                 isl_stream_push_token(s, tok);
819                         goto error;
820                 }
821                 nparam = isl_int_get_si(tok->u.v);
822                 isl_token_free(tok);
823                 if (n_col != 1 + out + in + local + nparam + 1) {
824                         isl_stream_error(s, NULL,
825                                     "dimensions don't match");
826                         goto error;
827                 }
828         } else
829                 out = n_col - 2 - nparam;
830         bmap = isl_basic_map_alloc(s->ctx, nparam, in, out, local, n_row, n_row);
831         if (!bmap)
832                 return NULL;
833
834         for (i = 0; i < local; ++i) {
835                 int k = isl_basic_map_alloc_div(bmap);
836                 if (k < 0)
837                         goto error;
838         }
839
840         for (i = 0; i < n_row; ++i)
841                 bmap = basic_map_read_polylib_constraint(s, bmap);
842
843         bmap = isl_basic_map_simplify(bmap);
844         bmap = isl_basic_map_finalize(bmap);
845         return bmap;
846 error:
847         isl_basic_map_free(bmap);
848         return NULL;
849 }
850
851 static struct isl_map *map_read_polylib(struct isl_stream *s, int nparam)
852 {
853         struct isl_token *tok;
854         struct isl_token *tok2;
855         int i, n;
856         struct isl_map *map;
857
858         tok = isl_stream_next_token(s);
859         if (!tok) {
860                 isl_stream_error(s, NULL, "unexpected EOF");
861                 return NULL;
862         }
863         tok2 = isl_stream_next_token(s);
864         if (!tok2) {
865                 isl_token_free(tok);
866                 isl_stream_error(s, NULL, "unexpected EOF");
867                 return NULL;
868         }
869         if (!tok2->on_new_line) {
870                 isl_stream_push_token(s, tok2);
871                 isl_stream_push_token(s, tok);
872                 return isl_map_from_basic_map(basic_map_read_polylib(s, nparam));
873         }
874         isl_stream_push_token(s, tok2);
875         n = isl_int_get_si(tok->u.v);
876         isl_token_free(tok);
877
878         isl_assert(s->ctx, n >= 1, return NULL);
879
880         map = isl_map_from_basic_map(basic_map_read_polylib(s, nparam));
881
882         for (i = 1; i < n; ++i)
883                 map = isl_map_union(map,
884                         isl_map_from_basic_map(basic_map_read_polylib(s, nparam)));
885
886         return map;
887 }
888
889 static struct isl_dim *set_names(struct isl_dim *dim, struct vars *vars,
890         enum isl_dim_type type, int offset, int n)
891 {
892         int i;
893         struct variable *v;
894
895         for (i = 0, v = vars->v; i < offset; ++i, v = v->next)
896                 ;
897         for (i = n - 1; i >= 0; --i, v = v->next)
898                 dim = isl_dim_set_name(dim, type, i, v->name);
899
900         return dim;
901 }
902
903 static struct isl_dim *dim_from_vars(struct vars *vars,
904         int nparam, int n_in, int n_out)
905 {
906         struct isl_dim *dim;
907
908         dim = isl_dim_alloc(vars->ctx, nparam, n_in, n_out);
909         dim = set_names(dim, vars, isl_dim_param, n_out + n_in, nparam);
910         dim = set_names(dim, vars, isl_dim_in, n_out, n_in);
911         dim = set_names(dim, vars, isl_dim_out, 0, n_out);
912
913         return dim;
914 }
915
916 static struct isl_map *map_read(struct isl_stream *s, int nparam)
917 {
918         struct isl_dim *dim = NULL;
919         struct isl_map *map = NULL;
920         struct isl_token *tok;
921         struct vars *v = NULL;
922         int n1;
923         int n2;
924
925         tok = isl_stream_next_token(s);
926         if (!tok) {
927                 isl_stream_error(s, NULL, "unexpected EOF");
928                 goto error;
929         }
930         if (tok->type == ISL_TOKEN_VALUE) {
931                 isl_stream_push_token(s, tok);
932                 return map_read_polylib(s, nparam);
933         }
934         v = vars_new(s->ctx);
935         if (tok->type == '[') {
936                 isl_stream_push_token(s, tok);
937                 v = read_tuple(s, v);
938                 if (!v)
939                         return NULL;
940                 if (nparam >= 0)
941                         isl_assert(s->ctx, nparam == v->n, goto error);
942                 nparam = v->n;
943                 tok = isl_stream_next_token(s);
944                 if (!tok || tok->type != ISL_TOKEN_TO) {
945                         isl_stream_error(s, tok, "expecting '->'");
946                         if (tok)
947                                 isl_stream_push_token(s, tok);
948                         goto error;
949                 }
950                 isl_token_free(tok);
951                 tok = isl_stream_next_token(s);
952         }
953         if (nparam < 0)
954                 nparam = 0;
955         if (!tok || tok->type != '{') {
956                 isl_stream_error(s, tok, "expecting '{'");
957                 if (tok)
958                         isl_stream_push_token(s, tok);
959                 goto error;
960         }
961         isl_token_free(tok);
962         v = read_tuple(s, v);
963         if (!v)
964                 return NULL;
965         n1 = v->n - nparam;
966         tok = isl_stream_next_token(s);
967         if (tok && tok->type == ISL_TOKEN_TO) {
968                 isl_token_free(tok);
969                 v = read_tuple(s, v);
970                 if (!v)
971                         return NULL;
972                 n2 = v->n - n1 - nparam;
973         } else {
974                 if (tok)
975                         isl_stream_push_token(s, tok);
976                 n2 = n1;
977                 n1 = 0;
978         }
979         dim = dim_from_vars(v, nparam, n1, n2);
980         tok = isl_stream_next_token(s);
981         if (!tok) {
982                 isl_stream_error(s, NULL, "unexpected EOF");
983                 goto error;
984         }
985         if (tok->type == ':') {
986                 isl_token_free(tok);
987                 map = read_disjuncts(s, v, isl_dim_copy(dim));
988                 tok = isl_stream_next_token(s);
989         } else
990                 map = isl_map_universe(isl_dim_copy(dim));
991         if (tok && tok->type == '}') {
992                 isl_token_free(tok);
993         } else {
994                 isl_stream_error(s, tok, "unexpected isl_token");
995                 if (tok)
996                         isl_token_free(tok);
997                 goto error;
998         }
999         vars_free(v);
1000         isl_dim_free(dim);
1001
1002         return map;
1003 error:
1004         isl_dim_free(dim);
1005         isl_map_free(map);
1006         if (v)
1007                 vars_free(v);
1008         return NULL;
1009 }
1010
1011 static struct isl_basic_map *basic_map_read(struct isl_stream *s, int nparam)
1012 {
1013         struct isl_map *map;
1014         struct isl_basic_map *bmap;
1015
1016         map = map_read(s, nparam);
1017         if (!map)
1018                 return NULL;
1019
1020         isl_assert(map->ctx, map->n <= 1, goto error);
1021
1022         if (map->n == 0)
1023                 bmap = isl_basic_map_empty_like_map(map);
1024         else
1025                 bmap = isl_basic_map_copy(map->p[0]);
1026
1027         isl_map_free(map);
1028
1029         return bmap;
1030 error:
1031         isl_map_free(map);
1032         return NULL;
1033 }
1034
1035 __isl_give isl_basic_map *isl_basic_map_read_from_file(isl_ctx *ctx,
1036                 FILE *input, int nparam)
1037 {
1038         struct isl_basic_map *bmap;
1039         struct isl_stream *s = isl_stream_new_file(ctx, input);
1040         if (!s)
1041                 return NULL;
1042         bmap = basic_map_read(s, nparam);
1043         isl_stream_free(s);
1044         return bmap;
1045 }
1046
1047 __isl_give isl_basic_set *isl_basic_set_read_from_file(isl_ctx *ctx,
1048                 FILE *input, int nparam)
1049 {
1050         struct isl_basic_map *bmap;
1051         bmap = isl_basic_map_read_from_file(ctx, input, nparam);
1052         if (!bmap)
1053                 return NULL;
1054         isl_assert(ctx, isl_basic_map_n_in(bmap) == 0, goto error);
1055         return (struct isl_basic_set *)bmap;
1056 error:
1057         isl_basic_map_free(bmap);
1058         return NULL;
1059 }
1060
1061 struct isl_basic_map *isl_basic_map_read_from_str(struct isl_ctx *ctx,
1062                 const char *str, int nparam)
1063 {
1064         struct isl_basic_map *bmap;
1065         struct isl_stream *s = isl_stream_new_str(ctx, str);
1066         if (!s)
1067                 return NULL;
1068         bmap = basic_map_read(s, nparam);
1069         isl_stream_free(s);
1070         return bmap;
1071 }
1072
1073 struct isl_basic_set *isl_basic_set_read_from_str(struct isl_ctx *ctx,
1074                 const char *str, int nparam)
1075 {
1076         struct isl_basic_map *bmap;
1077         bmap = isl_basic_map_read_from_str(ctx, str, nparam);
1078         if (!bmap)
1079                 return NULL;
1080         isl_assert(ctx, isl_basic_map_n_in(bmap) == 0, goto error);
1081         return (struct isl_basic_set *)bmap;
1082 error:
1083         isl_basic_map_free(bmap);
1084         return NULL;
1085 }
1086
1087 __isl_give isl_map *isl_map_read_from_file(struct isl_ctx *ctx,
1088                 FILE *input, int nparam)
1089 {
1090         struct isl_map *map;
1091         struct isl_stream *s = isl_stream_new_file(ctx, input);
1092         if (!s)
1093                 return NULL;
1094         map = map_read(s, nparam);
1095         isl_stream_free(s);
1096         return map;
1097 }
1098
1099 __isl_give isl_map *isl_map_read_from_str(struct isl_ctx *ctx,
1100                 const char *str, int nparam)
1101 {
1102         struct isl_map *map;
1103         struct isl_stream *s = isl_stream_new_str(ctx, str);
1104         if (!s)
1105                 return NULL;
1106         map = map_read(s, nparam);
1107         isl_stream_free(s);
1108         return map;
1109 }
1110
1111 __isl_give isl_set *isl_set_read_from_file(struct isl_ctx *ctx,
1112                 FILE *input, int nparam)
1113 {
1114         struct isl_map *map;
1115         map = isl_map_read_from_file(ctx, input, nparam);
1116         if (!map)
1117                 return NULL;
1118         isl_assert(ctx, isl_map_n_in(map) == 0, goto error);
1119         return (struct isl_set *)map;
1120 error:
1121         isl_map_free(map);
1122         return NULL;
1123 }
1124
1125 struct isl_set *isl_set_read_from_str(struct isl_ctx *ctx,
1126                 const char *str, int nparam)
1127 {
1128         struct isl_map *map;
1129         map = isl_map_read_from_str(ctx, str, nparam);
1130         if (!map)
1131                 return NULL;
1132         isl_assert(ctx, isl_map_n_in(map) == 0, goto error);
1133         return (struct isl_set *)map;
1134 error:
1135         isl_map_free(map);
1136         return NULL;
1137 }
1138
1139 static char *next_line(FILE *input, char *line, unsigned len)
1140 {
1141         char *p;
1142
1143         do {
1144                 if (!(p = fgets(line, len, input)))
1145                         return NULL;
1146                 while (isspace(*p) && *p != '\n')
1147                         ++p;
1148         } while (*p == '#' || *p == '\n');
1149
1150         return p;
1151 }
1152
1153 static struct isl_vec *isl_vec_read_from_file_polylib(struct isl_ctx *ctx,
1154                 FILE *input)
1155 {
1156         struct isl_vec *vec = NULL;
1157         char line[1024];
1158         char val[1024];
1159         char *p;
1160         unsigned size;
1161         int j;
1162         int n;
1163         int offset;
1164
1165         isl_assert(ctx, next_line(input, line, sizeof(line)), return NULL);
1166         isl_assert(ctx, sscanf(line, "%u", &size) == 1, return NULL);
1167
1168         vec = isl_vec_alloc(ctx, size);
1169
1170         p = next_line(input, line, sizeof(line));
1171         isl_assert(ctx, p, goto error);
1172
1173         for (j = 0; j < size; ++j) {
1174                 n = sscanf(p, "%s%n", val, &offset);
1175                 isl_assert(ctx, n != 0, goto error);
1176                 isl_int_read(vec->el[j], val);
1177                 p += offset;
1178         }
1179
1180         return vec;
1181 error:
1182         isl_vec_free(vec);
1183         return NULL;
1184 }
1185
1186 struct isl_vec *isl_vec_read_from_file(struct isl_ctx *ctx,
1187                 FILE *input, unsigned input_format)
1188 {
1189         if (input_format == ISL_FORMAT_POLYLIB)
1190                 return isl_vec_read_from_file_polylib(ctx, input);
1191         else
1192                 isl_assert(ctx, 0, return NULL);
1193 }