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