doc: fix typo
[platform/upstream/isl.git] / isl_stream.c
1 /*
2  * Copyright 2008-2009 Katholieke Universiteit Leuven
3  *
4  * Use of this software is governed by the MIT license
5  *
6  * Written by Sven Verdoolaege, K.U.Leuven, Departement
7  * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
8  */
9
10 #include <ctype.h>
11 #include <string.h>
12 #include <strings.h>
13 #include <isl/ctx.h>
14 #include <isl_stream_private.h>
15 #include <isl/map.h>
16 #include <isl/aff.h>
17 #include <isl_val_private.h>
18
19 struct isl_keyword {
20         char                    *name;
21         enum isl_token_type     type;
22 };
23
24 static int same_name(const void *entry, const void *val)
25 {
26         const struct isl_keyword *keyword = (const struct isl_keyword *)entry;
27
28         return !strcmp(keyword->name, val);
29 }
30
31 enum isl_token_type isl_stream_register_keyword(struct isl_stream *s,
32         const char *name)
33 {
34         struct isl_hash_table_entry *entry;
35         struct isl_keyword *keyword;
36         uint32_t name_hash;
37
38         if (!s->keywords) {
39                 s->keywords = isl_hash_table_alloc(s->ctx, 10);
40                 if (!s->keywords)
41                         return ISL_TOKEN_ERROR;
42                 s->next_type = ISL_TOKEN_LAST;
43         }
44
45         name_hash = isl_hash_string(isl_hash_init(), name);
46
47         entry = isl_hash_table_find(s->ctx, s->keywords, name_hash,
48                                         same_name, name, 1);
49         if (!entry)
50                 return ISL_TOKEN_ERROR;
51         if (entry->data) {
52                 keyword = entry->data;
53                 return keyword->type;
54         }
55
56         keyword = isl_calloc_type(s->ctx, struct isl_keyword);
57         if (!keyword)
58                 return ISL_TOKEN_ERROR;
59         keyword->type = s->next_type++;
60         keyword->name = strdup(name);
61         if (!keyword->name) {
62                 free(keyword);
63                 return ISL_TOKEN_ERROR;
64         }
65         entry->data = keyword;
66
67         return keyword->type;
68 }
69
70 struct isl_token *isl_token_new(isl_ctx *ctx,
71         int line, int col, unsigned on_new_line)
72 {
73         struct isl_token *tok = isl_alloc_type(ctx, struct isl_token);
74         if (!tok)
75                 return NULL;
76         tok->line = line;
77         tok->col = col;
78         tok->on_new_line = on_new_line;
79         tok->is_keyword = 0;
80         tok->u.s = NULL;
81         return tok;
82 }
83
84 /* Return the type of "tok".
85  */
86 int isl_token_get_type(struct isl_token *tok)
87 {
88         return tok ? tok->type : ISL_TOKEN_ERROR;
89 }
90
91 /* Given a token of type ISL_TOKEN_VALUE, return the value it represents.
92  */
93 __isl_give isl_val *isl_token_get_val(isl_ctx *ctx, struct isl_token *tok)
94 {
95         if (!tok)
96                 return NULL;
97         if (tok->type != ISL_TOKEN_VALUE)
98                 isl_die(ctx, isl_error_invalid, "not a value token",
99                         return NULL);
100
101         return isl_val_int_from_isl_int(ctx, tok->u.v);
102 }
103
104 /* Given a token of type ISL_TOKEN_STRING, return the string it represents.
105  */
106 __isl_give char *isl_token_get_str(isl_ctx *ctx, struct isl_token *tok)
107 {
108         if (!tok)
109                 return NULL;
110         if (tok->type != ISL_TOKEN_STRING)
111                 isl_die(ctx, isl_error_invalid, "not a string token",
112                         return NULL);
113
114         return strdup(tok->u.s);
115 }
116
117 void isl_token_free(struct isl_token *tok)
118 {
119         if (!tok)
120                 return;
121         if (tok->type == ISL_TOKEN_VALUE)
122                 isl_int_clear(tok->u.v);
123         else if (tok->type == ISL_TOKEN_MAP)
124                 isl_map_free(tok->u.map);
125         else if (tok->type == ISL_TOKEN_AFF)
126                 isl_pw_aff_free(tok->u.pwaff);
127         else
128                 free(tok->u.s);
129         free(tok);
130 }
131
132 void isl_stream_error(struct isl_stream *s, struct isl_token *tok, char *msg)
133 {
134         int line = tok ? tok->line : s->line;
135         int col = tok ? tok->col : s->col;
136         fprintf(stderr, "syntax error (%d, %d): %s\n", line, col, msg);
137         if (tok) {
138                 if (tok->type < 256)
139                         fprintf(stderr, "got '%c'\n", tok->type);
140                 else if (tok->type == ISL_TOKEN_IDENT)
141                         fprintf(stderr, "got ident '%s'\n", tok->u.s);
142                 else if (tok->is_keyword)
143                         fprintf(stderr, "got keyword '%s'\n", tok->u.s);
144                 else if (tok->type == ISL_TOKEN_VALUE) {
145                         fprintf(stderr, "got value '");
146                         isl_int_print(stderr, tok->u.v, 0);
147                         fprintf(stderr, "'\n");
148                 } else if (tok->type == ISL_TOKEN_MAP) {
149                         isl_printer *p;
150                         fprintf(stderr, "got map '");
151                         p = isl_printer_to_file(s->ctx, stderr);
152                         p = isl_printer_print_map(p, tok->u.map);
153                         isl_printer_free(p);
154                         fprintf(stderr, "'\n");
155                 } else if (tok->type == ISL_TOKEN_AFF) {
156                         isl_printer *p;
157                         fprintf(stderr, "got affine expression '");
158                         p = isl_printer_to_file(s->ctx, stderr);
159                         p = isl_printer_print_pw_aff(p, tok->u.pwaff);
160                         isl_printer_free(p);
161                         fprintf(stderr, "'\n");
162                 } else if (tok->u.s)
163                         fprintf(stderr, "got token '%s'\n", tok->u.s);
164                 else
165                         fprintf(stderr, "got token type %d\n", tok->type);
166         }
167 }
168
169 static struct isl_stream* isl_stream_new(struct isl_ctx *ctx)
170 {
171         int i;
172         struct isl_stream *s = isl_alloc_type(ctx, struct isl_stream);
173         if (!s)
174                 return NULL;
175         s->ctx = ctx;
176         isl_ctx_ref(s->ctx);
177         s->file = NULL;
178         s->str = NULL;
179         s->len = 0;
180         s->line = 1;
181         s->col = 0;
182         s->eof = 0;
183         s->c = -1;
184         s->n_un = 0;
185         for (i = 0; i < 5; ++i)
186                 s->tokens[i] = NULL;
187         s->n_token = 0;
188         s->keywords = NULL;
189         s->size = 256;
190         s->buffer = isl_alloc_array(ctx, char, s->size);
191         if (!s->buffer)
192                 goto error;
193         return s;
194 error:
195         isl_stream_free(s);
196         return NULL;
197 }
198
199 struct isl_stream* isl_stream_new_file(struct isl_ctx *ctx, FILE *file)
200 {
201         struct isl_stream *s = isl_stream_new(ctx);
202         if (!s)
203                 return NULL;
204         s->file = file;
205         return s;
206 }
207
208 struct isl_stream* isl_stream_new_str(struct isl_ctx *ctx, const char *str)
209 {
210         struct isl_stream *s;
211         if (!str)
212                 return NULL;
213         s = isl_stream_new(ctx);
214         if (!s)
215                 return NULL;
216         s->str = str;
217         return s;
218 }
219
220 static int stream_getc(struct isl_stream *s)
221 {
222         int c;
223         if (s->eof)
224                 return -1;
225         if (s->n_un)
226                 return s->c = s->un[--s->n_un];
227         if (s->file)
228                 c = fgetc(s->file);
229         else {
230                 c = *s->str++;
231                 if (c == '\0')
232                         c = -1;
233         }
234         if (c == -1)
235                 s->eof = 1;
236         if (!s->eof) {
237                 if (s->c == '\n') {
238                         s->line++;
239                         s->col = 0;
240                 } else
241                         s->col++;
242         }
243         s->c = c;
244         return c;
245 }
246
247 static void isl_stream_ungetc(struct isl_stream *s, int c)
248 {
249         isl_assert(s->ctx, s->n_un < 5, return);
250         s->un[s->n_un++] = c;
251         s->c = -1;
252 }
253
254 static int isl_stream_getc(struct isl_stream *s)
255 {
256         int c;
257
258         do {
259                 c = stream_getc(s);
260                 if (c != '\\')
261                         return c;
262                 c = stream_getc(s);
263         } while (c == '\n');
264
265         isl_stream_ungetc(s, c);
266
267         return '\\';
268 }
269
270 static int isl_stream_push_char(struct isl_stream *s, int c)
271 {
272         if (s->len >= s->size) {
273                 char *buffer;
274                 s->size = (3*s->size)/2;
275                 buffer = isl_realloc_array(s->ctx, s->buffer, char, s->size);
276                 if (!buffer)
277                         return -1;
278                 s->buffer = buffer;
279         }
280         s->buffer[s->len++] = c;
281         return 0;
282 }
283
284 void isl_stream_push_token(struct isl_stream *s, struct isl_token *tok)
285 {
286         isl_assert(s->ctx, s->n_token < 5, return);
287         s->tokens[s->n_token++] = tok;
288 }
289
290 static enum isl_token_type check_keywords(struct isl_stream *s)
291 {
292         struct isl_hash_table_entry *entry;
293         struct isl_keyword *keyword;
294         uint32_t name_hash;
295
296         if (!strcasecmp(s->buffer, "exists"))
297                 return ISL_TOKEN_EXISTS;
298         if (!strcasecmp(s->buffer, "and"))
299                 return ISL_TOKEN_AND;
300         if (!strcasecmp(s->buffer, "or"))
301                 return ISL_TOKEN_OR;
302         if (!strcasecmp(s->buffer, "implies"))
303                 return ISL_TOKEN_IMPLIES;
304         if (!strcasecmp(s->buffer, "not"))
305                 return ISL_TOKEN_NOT;
306         if (!strcasecmp(s->buffer, "infty"))
307                 return ISL_TOKEN_INFTY;
308         if (!strcasecmp(s->buffer, "infinity"))
309                 return ISL_TOKEN_INFTY;
310         if (!strcasecmp(s->buffer, "NaN"))
311                 return ISL_TOKEN_NAN;
312         if (!strcasecmp(s->buffer, "min"))
313                 return ISL_TOKEN_MIN;
314         if (!strcasecmp(s->buffer, "max"))
315                 return ISL_TOKEN_MAX;
316         if (!strcasecmp(s->buffer, "rat"))
317                 return ISL_TOKEN_RAT;
318         if (!strcasecmp(s->buffer, "true"))
319                 return ISL_TOKEN_TRUE;
320         if (!strcasecmp(s->buffer, "false"))
321                 return ISL_TOKEN_FALSE;
322         if (!strcasecmp(s->buffer, "ceild"))
323                 return ISL_TOKEN_CEILD;
324         if (!strcasecmp(s->buffer, "floord"))
325                 return ISL_TOKEN_FLOORD;
326         if (!strcasecmp(s->buffer, "mod"))
327                 return ISL_TOKEN_MOD;
328         if (!strcasecmp(s->buffer, "ceil"))
329                 return ISL_TOKEN_CEIL;
330         if (!strcasecmp(s->buffer, "floor"))
331                 return ISL_TOKEN_FLOOR;
332
333         if (!s->keywords)
334                 return ISL_TOKEN_IDENT;
335
336         name_hash = isl_hash_string(isl_hash_init(), s->buffer);
337         entry = isl_hash_table_find(s->ctx, s->keywords, name_hash, same_name,
338                                         s->buffer, 0);
339         if (entry) {
340                 keyword = entry->data;
341                 return keyword->type;
342         }
343
344         return ISL_TOKEN_IDENT;
345 }
346
347 int isl_stream_skip_line(struct isl_stream *s)
348 {
349         int c;
350
351         while ((c = isl_stream_getc(s)) != -1 && c != '\n')
352                 /* nothing */
353                 ;
354
355         return c == -1 ? -1 : 0;
356 }
357
358 static struct isl_token *next_token(struct isl_stream *s, int same_line)
359 {
360         int c;
361         struct isl_token *tok = NULL;
362         int line, col;
363         int old_line = s->line;
364
365         if (s->n_token) {
366                 if (same_line && s->tokens[s->n_token - 1]->on_new_line)
367                         return NULL;
368                 return s->tokens[--s->n_token];
369         }
370
371         if (same_line && s->c == '\n')
372                 return NULL;
373
374         s->len = 0;
375
376         /* skip spaces and comment lines */
377         while ((c = isl_stream_getc(s)) != -1) {
378                 if (c == '#') {
379                         if (isl_stream_skip_line(s) < 0)
380                                 break;
381                         c = '\n';
382                         if (same_line)
383                                 break;
384                 } else if (!isspace(c) || (same_line && c == '\n'))
385                         break;
386         }
387
388         line = s->line;
389         col = s->col;
390
391         if (c == -1 || (same_line && c == '\n'))
392                 return NULL;
393         if (c == '(' ||
394             c == ')' ||
395             c == '+' ||
396             c == '*' ||
397             c == '%' ||
398             c == '?' ||
399             c == '^' ||
400             c == '@' ||
401             c == '$' ||
402             c == ',' ||
403             c == '.' ||
404             c == ';' ||
405             c == '[' ||
406             c == ']' ||
407             c == '{' ||
408             c == '}') {
409                 tok = isl_token_new(s->ctx, line, col, old_line != line);
410                 if (!tok)
411                         return NULL;
412                 tok->type = (enum isl_token_type)c;
413                 return tok;
414         }
415         if (c == '-') {
416                 int c;
417                 if ((c = isl_stream_getc(s)) == '>') {
418                         tok = isl_token_new(s->ctx, line, col, old_line != line);
419                         if (!tok)
420                                 return NULL;
421                         tok->u.s = strdup("->");
422                         tok->type = ISL_TOKEN_TO;
423                         return tok;
424                 }
425                 if (c != -1)
426                         isl_stream_ungetc(s, c);
427                 if (!isdigit(c)) {
428                         tok = isl_token_new(s->ctx, line, col, old_line != line);
429                         if (!tok)
430                                 return NULL;
431                         tok->type = (enum isl_token_type) '-';
432                         return tok;
433                 }
434         }
435         if (c == '-' || isdigit(c)) {
436                 int minus = c == '-';
437                 tok = isl_token_new(s->ctx, line, col, old_line != line);
438                 if (!tok)
439                         return NULL;
440                 tok->type = ISL_TOKEN_VALUE;
441                 isl_int_init(tok->u.v);
442                 if (isl_stream_push_char(s, c))
443                         goto error;
444                 while ((c = isl_stream_getc(s)) != -1 && isdigit(c))
445                         if (isl_stream_push_char(s, c))
446                                 goto error;
447                 if (c != -1)
448                         isl_stream_ungetc(s, c);
449                 isl_stream_push_char(s, '\0');
450                 isl_int_read(tok->u.v, s->buffer);
451                 if (minus && isl_int_is_zero(tok->u.v)) {
452                         tok->col++;
453                         tok->on_new_line = 0;
454                         isl_stream_push_token(s, tok);
455                         tok = isl_token_new(s->ctx, line, col, old_line != line);
456                         if (!tok)
457                                 return NULL;
458                         tok->type = (enum isl_token_type) '-';
459                 }
460                 return tok;
461         }
462         if (isalpha(c) || c == '_') {
463                 tok = isl_token_new(s->ctx, line, col, old_line != line);
464                 if (!tok)
465                         return NULL;
466                 isl_stream_push_char(s, c);
467                 while ((c = isl_stream_getc(s)) != -1 &&
468                                 (isalnum(c) || c == '_'))
469                         isl_stream_push_char(s, c);
470                 if (c != -1)
471                         isl_stream_ungetc(s, c);
472                 while ((c = isl_stream_getc(s)) != -1 && c == '\'')
473                         isl_stream_push_char(s, c);
474                 if (c != -1)
475                         isl_stream_ungetc(s, c);
476                 isl_stream_push_char(s, '\0');
477                 tok->type = check_keywords(s);
478                 if (tok->type != ISL_TOKEN_IDENT)
479                         tok->is_keyword = 1;
480                 tok->u.s = strdup(s->buffer);
481                 if (!tok->u.s)
482                         goto error;
483                 return tok;
484         }
485         if (c == '"') {
486                 tok = isl_token_new(s->ctx, line, col, old_line != line);
487                 if (!tok)
488                         return NULL;
489                 tok->type = ISL_TOKEN_STRING;
490                 tok->u.s = NULL;
491                 while ((c = isl_stream_getc(s)) != -1 && c != '"' && c != '\n')
492                         isl_stream_push_char(s, c);
493                 if (c != '"') {
494                         isl_stream_error(s, NULL, "unterminated string");
495                         goto error;
496                 }
497                 isl_stream_push_char(s, '\0');
498                 tok->u.s = strdup(s->buffer);
499                 return tok;
500         }
501         if (c == '=') {
502                 int c;
503                 tok = isl_token_new(s->ctx, line, col, old_line != line);
504                 if (!tok)
505                         return NULL;
506                 if ((c = isl_stream_getc(s)) == '=') {
507                         tok->u.s = strdup("==");
508                         tok->type = ISL_TOKEN_EQ_EQ;
509                         return tok;
510                 }
511                 if (c != -1)
512                         isl_stream_ungetc(s, c);
513                 tok->type = (enum isl_token_type) '=';
514                 return tok;
515         }
516         if (c == ':') {
517                 int c;
518                 tok = isl_token_new(s->ctx, line, col, old_line != line);
519                 if (!tok)
520                         return NULL;
521                 if ((c = isl_stream_getc(s)) == '=') {
522                         tok->u.s = strdup(":=");
523                         tok->type = ISL_TOKEN_DEF;
524                         return tok;
525                 }
526                 if (c != -1)
527                         isl_stream_ungetc(s, c);
528                 tok->type = (enum isl_token_type) ':';
529                 return tok;
530         }
531         if (c == '>') {
532                 int c;
533                 tok = isl_token_new(s->ctx, line, col, old_line != line);
534                 if (!tok)
535                         return NULL;
536                 if ((c = isl_stream_getc(s)) == '=') {
537                         tok->u.s = strdup(">=");
538                         tok->type = ISL_TOKEN_GE;
539                         return tok;
540                 } else if (c == '>') {
541                         if ((c = isl_stream_getc(s)) == '=') {
542                                 tok->u.s = strdup(">>=");
543                                 tok->type = ISL_TOKEN_LEX_GE;
544                                 return tok;
545                         }
546                         tok->u.s = strdup(">>");
547                         tok->type = ISL_TOKEN_LEX_GT;
548                 } else {
549                         tok->u.s = strdup(">");
550                         tok->type = ISL_TOKEN_GT;
551                 }
552                 if (c != -1)
553                         isl_stream_ungetc(s, c);
554                 return tok;
555         }
556         if (c == '<') {
557                 int c;
558                 tok = isl_token_new(s->ctx, line, col, old_line != line);
559                 if (!tok)
560                         return NULL;
561                 if ((c = isl_stream_getc(s)) == '=') {
562                         tok->u.s = strdup("<=");
563                         tok->type = ISL_TOKEN_LE;
564                         return tok;
565                 } else if (c == '<') {
566                         if ((c = isl_stream_getc(s)) == '=') {
567                                 tok->u.s = strdup("<<=");
568                                 tok->type = ISL_TOKEN_LEX_LE;
569                                 return tok;
570                         }
571                         tok->u.s = strdup("<<");
572                         tok->type = ISL_TOKEN_LEX_LT;
573                 } else {
574                         tok->u.s = strdup("<");
575                         tok->type = ISL_TOKEN_LT;
576                 }
577                 if (c != -1)
578                         isl_stream_ungetc(s, c);
579                 return tok;
580         }
581         if (c == '&') {
582                 tok = isl_token_new(s->ctx, line, col, old_line != line);
583                 if (!tok)
584                         return NULL;
585                 tok->type = ISL_TOKEN_AND;
586                 if ((c = isl_stream_getc(s)) != '&' && c != -1) {
587                         tok->u.s = strdup("&");
588                         isl_stream_ungetc(s, c);
589                 } else
590                         tok->u.s = strdup("&&");
591                 return tok;
592         }
593         if (c == '|') {
594                 tok = isl_token_new(s->ctx, line, col, old_line != line);
595                 if (!tok)
596                         return NULL;
597                 tok->type = ISL_TOKEN_OR;
598                 if ((c = isl_stream_getc(s)) != '|' && c != -1) {
599                         tok->u.s = strdup("|");
600                         isl_stream_ungetc(s, c);
601                 } else
602                         tok->u.s = strdup("||");
603                 return tok;
604         }
605         if (c == '/') {
606                 tok = isl_token_new(s->ctx, line, col, old_line != line);
607                 if (!tok)
608                         return NULL;
609                 if ((c = isl_stream_getc(s)) != '\\' && c != -1) {
610                         tok->type = (enum isl_token_type) '/';
611                         isl_stream_ungetc(s, c);
612                 } else {
613                         tok->u.s = strdup("/\\");
614                         tok->type = ISL_TOKEN_AND;
615                 }
616                 return tok;
617         }
618         if (c == '\\') {
619                 tok = isl_token_new(s->ctx, line, col, old_line != line);
620                 if (!tok)
621                         return NULL;
622                 if ((c = isl_stream_getc(s)) != '/' && c != -1) {
623                         tok->type = (enum isl_token_type) '\\';
624                         isl_stream_ungetc(s, c);
625                 } else {
626                         tok->u.s = strdup("\\/");
627                         tok->type = ISL_TOKEN_OR;
628                 }
629                 return tok;
630         }
631         if (c == '!') {
632                 tok = isl_token_new(s->ctx, line, col, old_line != line);
633                 if (!tok)
634                         return NULL;
635                 if ((c = isl_stream_getc(s)) == '=') {
636                         tok->u.s = strdup("!=");
637                         tok->type = ISL_TOKEN_NE;
638                         return tok;
639                 } else {
640                         tok->type = ISL_TOKEN_NOT;
641                         tok->u.s = strdup("!");
642                 }
643                 if (c != -1)
644                         isl_stream_ungetc(s, c);
645                 return tok;
646         }
647
648         tok = isl_token_new(s->ctx, line, col, old_line != line);
649         if (!tok)
650                 return NULL;
651         tok->type = ISL_TOKEN_UNKNOWN;
652         return tok;
653 error:
654         isl_token_free(tok);
655         return NULL;
656 }
657
658 struct isl_token *isl_stream_next_token(struct isl_stream *s)
659 {
660         return next_token(s, 0);
661 }
662
663 struct isl_token *isl_stream_next_token_on_same_line(struct isl_stream *s)
664 {
665         return next_token(s, 1);
666 }
667
668 int isl_stream_eat_if_available(struct isl_stream *s, int type)
669 {
670         struct isl_token *tok;
671
672         tok = isl_stream_next_token(s);
673         if (!tok)
674                 return 0;
675         if (tok->type == type) {
676                 isl_token_free(tok);
677                 return 1;
678         }
679         isl_stream_push_token(s, tok);
680         return 0;
681 }
682
683 int isl_stream_next_token_is(struct isl_stream *s, int type)
684 {
685         struct isl_token *tok;
686         int r;
687
688         tok = isl_stream_next_token(s);
689         if (!tok)
690                 return 0;
691         r = tok->type == type;
692         isl_stream_push_token(s, tok);
693         return r;
694 }
695
696 char *isl_stream_read_ident_if_available(struct isl_stream *s)
697 {
698         struct isl_token *tok;
699
700         tok = isl_stream_next_token(s);
701         if (!tok)
702                 return NULL;
703         if (tok->type == ISL_TOKEN_IDENT) {
704                 char *ident = strdup(tok->u.s);
705                 isl_token_free(tok);
706                 return ident;
707         }
708         isl_stream_push_token(s, tok);
709         return NULL;
710 }
711
712 int isl_stream_eat(struct isl_stream *s, int type)
713 {
714         struct isl_token *tok;
715
716         tok = isl_stream_next_token(s);
717         if (!tok)
718                 return -1;
719         if (tok->type == type) {
720                 isl_token_free(tok);
721                 return 0;
722         }
723         isl_stream_error(s, tok, "expecting other token");
724         isl_stream_push_token(s, tok);
725         return -1;
726 }
727
728 int isl_stream_is_empty(struct isl_stream *s)
729 {
730         struct isl_token *tok;
731
732         tok = isl_stream_next_token(s);
733
734         if (!tok)
735                 return 1;
736
737         isl_stream_push_token(s, tok);
738         return 0;
739 }
740
741 static int free_keyword(void **p, void *user)
742 {
743         struct isl_keyword *keyword = *p;
744
745         free(keyword->name);
746         free(keyword);
747
748         return 0;
749 }
750
751 void isl_stream_flush_tokens(struct isl_stream *s)
752 {
753         int i;
754
755         if (!s)
756                 return;
757         for (i = 0; i < s->n_token; ++i)
758                 isl_token_free(s->tokens[i]);
759         s->n_token = 0;
760 }
761
762 void isl_stream_free(struct isl_stream *s)
763 {
764         if (!s)
765                 return;
766         free(s->buffer);
767         if (s->n_token != 0) {
768                 struct isl_token *tok = isl_stream_next_token(s);
769                 isl_stream_error(s, tok, "unexpected token");
770                 isl_token_free(tok);
771         }
772         if (s->keywords) {
773                 isl_hash_table_foreach(s->ctx, s->keywords, &free_keyword, NULL);
774                 isl_hash_table_free(s->ctx, s->keywords);
775         }
776         isl_ctx_deref(s->ctx);
777         free(s);
778 }