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