LCOV - code coverage report
Current view: top level - metalib_isl - isl_stream.c (source / functions) Hit Total Coverage
Test: 2018-10-31_point_maint_greina16.lcov Lines: 0 714 0.0 %
Date: 2018-11-01 11:27:00 Functions: 0 41 0.0 %

          Line data    Source code
       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 <isl/ctx.h>
      13             : #include <isl_stream_private.h>
      14             : #include <isl/map.h>
      15             : #include <isl/aff.h>
      16             : #include <isl_val_private.h>
      17             : 
      18             : struct isl_keyword {
      19             :         char                    *name;
      20             :         enum isl_token_type     type;
      21             : };
      22             : 
      23           0 : static int same_name(const void *entry, const void *val)
      24             : {
      25           0 :         const struct isl_keyword *keyword = (const struct isl_keyword *)entry;
      26             : 
      27           0 :         return !strcmp(keyword->name, val);
      28             : }
      29             : 
      30           0 : enum isl_token_type isl_stream_register_keyword(__isl_keep isl_stream *s,
      31             :         const char *name)
      32             : {
      33             :         struct isl_hash_table_entry *entry;
      34             :         struct isl_keyword *keyword;
      35             :         uint32_t name_hash;
      36             : 
      37           0 :         if (!s->keywords) {
      38           0 :                 s->keywords = isl_hash_table_alloc(s->ctx, 10);
      39           0 :                 if (!s->keywords)
      40           0 :                         return ISL_TOKEN_ERROR;
      41           0 :                 s->next_type = ISL_TOKEN_LAST;
      42             :         }
      43             : 
      44           0 :         name_hash = isl_hash_string(isl_hash_init(), name);
      45             : 
      46           0 :         entry = isl_hash_table_find(s->ctx, s->keywords, name_hash,
      47             :                                         same_name, name, 1);
      48           0 :         if (!entry)
      49           0 :                 return ISL_TOKEN_ERROR;
      50           0 :         if (entry->data) {
      51           0 :                 keyword = entry->data;
      52           0 :                 return keyword->type;
      53             :         }
      54             : 
      55           0 :         keyword = isl_calloc_type(s->ctx, struct isl_keyword);
      56           0 :         if (!keyword)
      57           0 :                 return ISL_TOKEN_ERROR;
      58           0 :         keyword->type = s->next_type++;
      59           0 :         keyword->name = strdup(name);
      60           0 :         if (!keyword->name) {
      61           0 :                 free(keyword);
      62           0 :                 return ISL_TOKEN_ERROR;
      63             :         }
      64           0 :         entry->data = keyword;
      65             : 
      66           0 :         return keyword->type;
      67             : }
      68             : 
      69           0 : struct isl_token *isl_token_new(isl_ctx *ctx,
      70             :         int line, int col, unsigned on_new_line)
      71             : {
      72           0 :         struct isl_token *tok = isl_alloc_type(ctx, struct isl_token);
      73           0 :         if (!tok)
      74           0 :                 return NULL;
      75           0 :         tok->line = line;
      76           0 :         tok->col = col;
      77           0 :         tok->on_new_line = on_new_line;
      78           0 :         tok->is_keyword = 0;
      79           0 :         tok->u.s = NULL;
      80           0 :         return tok;
      81             : }
      82             : 
      83             : /* Return the type of "tok".
      84             :  */
      85           0 : int isl_token_get_type(struct isl_token *tok)
      86             : {
      87           0 :         return tok ? tok->type : ISL_TOKEN_ERROR;
      88             : }
      89             : 
      90             : /* Given a token of type ISL_TOKEN_VALUE, return the value it represents.
      91             :  */
      92           0 : __isl_give isl_val *isl_token_get_val(isl_ctx *ctx, struct isl_token *tok)
      93             : {
      94           0 :         if (!tok)
      95           0 :                 return NULL;
      96           0 :         if (tok->type != ISL_TOKEN_VALUE)
      97           0 :                 isl_die(ctx, isl_error_invalid, "not a value token",
      98             :                         return NULL);
      99             : 
     100           0 :         return isl_val_int_from_isl_int(ctx, tok->u.v);
     101             : }
     102             : 
     103             : /* Given a token with a string representation, return a copy of this string.
     104             :  */
     105           0 : __isl_give char *isl_token_get_str(isl_ctx *ctx, struct isl_token *tok)
     106             : {
     107           0 :         if (!tok)
     108           0 :                 return NULL;
     109           0 :         if (!tok->u.s)
     110           0 :                 isl_die(ctx, isl_error_invalid,
     111             :                         "token does not have a string representation",
     112             :                         return NULL);
     113             : 
     114           0 :         return strdup(tok->u.s);
     115             : }
     116             : 
     117           0 : void isl_token_free(struct isl_token *tok)
     118             : {
     119           0 :         if (!tok)
     120           0 :                 return;
     121           0 :         if (tok->type == ISL_TOKEN_VALUE)
     122           0 :                 isl_int_clear(tok->u.v);
     123           0 :         else if (tok->type == ISL_TOKEN_MAP)
     124           0 :                 isl_map_free(tok->u.map);
     125           0 :         else if (tok->type == ISL_TOKEN_AFF)
     126           0 :                 isl_pw_aff_free(tok->u.pwaff);
     127             :         else
     128           0 :                 free(tok->u.s);
     129           0 :         free(tok);
     130             : }
     131             : 
     132           0 : void isl_stream_error(__isl_keep isl_stream *s, struct isl_token *tok,
     133             :         char *msg)
     134             : {
     135           0 :         int line = tok ? tok->line : s->line;
     136           0 :         int col = tok ? tok->col : s->col;
     137           0 :         fprintf(stderr, "syntax error (%d, %d): %s\n", line, col, msg);
     138           0 :         if (tok) {
     139           0 :                 if (tok->type < 256)
     140           0 :                         fprintf(stderr, "got '%c'\n", tok->type);
     141           0 :                 else if (tok->type == ISL_TOKEN_IDENT)
     142           0 :                         fprintf(stderr, "got ident '%s'\n", tok->u.s);
     143           0 :                 else if (tok->is_keyword)
     144           0 :                         fprintf(stderr, "got keyword '%s'\n", tok->u.s);
     145           0 :                 else if (tok->type == ISL_TOKEN_VALUE) {
     146           0 :                         fprintf(stderr, "got value '");
     147           0 :                         isl_int_print(stderr, tok->u.v, 0);
     148           0 :                         fprintf(stderr, "'\n");
     149           0 :                 } else if (tok->type == ISL_TOKEN_MAP) {
     150             :                         isl_printer *p;
     151           0 :                         fprintf(stderr, "got map '");
     152           0 :                         p = isl_printer_to_file(s->ctx, stderr);
     153           0 :                         p = isl_printer_print_map(p, tok->u.map);
     154           0 :                         isl_printer_free(p);
     155           0 :                         fprintf(stderr, "'\n");
     156           0 :                 } else if (tok->type == ISL_TOKEN_AFF) {
     157             :                         isl_printer *p;
     158           0 :                         fprintf(stderr, "got affine expression '");
     159           0 :                         p = isl_printer_to_file(s->ctx, stderr);
     160           0 :                         p = isl_printer_print_pw_aff(p, tok->u.pwaff);
     161           0 :                         isl_printer_free(p);
     162           0 :                         fprintf(stderr, "'\n");
     163           0 :                 } else if (tok->u.s)
     164           0 :                         fprintf(stderr, "got token '%s'\n", tok->u.s);
     165             :                 else
     166           0 :                         fprintf(stderr, "got token type %d\n", tok->type);
     167             :         }
     168           0 : }
     169             : 
     170           0 : static __isl_give isl_stream* isl_stream_new(struct isl_ctx *ctx)
     171             : {
     172             :         int i;
     173           0 :         isl_stream *s = isl_calloc_type(ctx, struct isl_stream);
     174           0 :         if (!s)
     175           0 :                 return NULL;
     176           0 :         s->ctx = ctx;
     177           0 :         isl_ctx_ref(s->ctx);
     178           0 :         s->file = NULL;
     179           0 :         s->str = NULL;
     180           0 :         s->len = 0;
     181           0 :         s->line = 1;
     182           0 :         s->col = 1;
     183           0 :         s->eof = 0;
     184           0 :         s->last_line = 0;
     185           0 :         s->c = -1;
     186           0 :         s->n_un = 0;
     187           0 :         for (i = 0; i < 5; ++i)
     188           0 :                 s->tokens[i] = NULL;
     189           0 :         s->n_token = 0;
     190           0 :         s->keywords = NULL;
     191           0 :         s->size = 256;
     192           0 :         s->buffer = isl_alloc_array(ctx, char, s->size);
     193           0 :         if (!s->buffer)
     194           0 :                 goto error;
     195           0 :         return s;
     196             : error:
     197           0 :         isl_stream_free(s);
     198           0 :         return NULL;
     199             : }
     200             : 
     201           0 : __isl_give isl_stream* isl_stream_new_file(struct isl_ctx *ctx, FILE *file)
     202             : {
     203           0 :         isl_stream *s = isl_stream_new(ctx);
     204           0 :         if (!s)
     205           0 :                 return NULL;
     206           0 :         s->file = file;
     207           0 :         return s;
     208             : }
     209             : 
     210           0 : __isl_give isl_stream* isl_stream_new_str(struct isl_ctx *ctx, const char *str)
     211             : {
     212             :         isl_stream *s;
     213           0 :         if (!str)
     214           0 :                 return NULL;
     215           0 :         s = isl_stream_new(ctx);
     216           0 :         if (!s)
     217           0 :                 return NULL;
     218           0 :         s->str = str;
     219           0 :         return s;
     220             : }
     221             : 
     222             : /* Read a character from the stream and advance s->line and s->col
     223             :  * to point to the next character.
     224             :  */
     225           0 : static int stream_getc(__isl_keep isl_stream *s)
     226             : {
     227             :         int c;
     228           0 :         if (s->eof)
     229           0 :                 return -1;
     230           0 :         if (s->n_un)
     231           0 :                 return s->c = s->un[--s->n_un];
     232           0 :         if (s->file)
     233           0 :                 c = fgetc(s->file);
     234             :         else {
     235           0 :                 c = *s->str++;
     236           0 :                 if (c == '\0')
     237           0 :                         c = -1;
     238             :         }
     239           0 :         if (c == -1)
     240           0 :                 s->eof = 1;
     241           0 :         else if (c == '\n') {
     242           0 :                 s->line++;
     243           0 :                 s->col = 1;
     244             :         } else
     245           0 :                 s->col++;
     246           0 :         s->c = c;
     247           0 :         return c;
     248             : }
     249             : 
     250           0 : static void isl_stream_ungetc(__isl_keep isl_stream *s, int c)
     251             : {
     252           0 :         isl_assert(s->ctx, s->n_un < 5, return);
     253           0 :         s->un[s->n_un++] = c;
     254           0 :         s->c = -1;
     255             : }
     256             : 
     257             : /* Read a character from the stream, skipping pairs of '\\' and '\n'.
     258             :  * Set s->start_line and s->start_col to the line and column
     259             :  * of the returned character.
     260             :  */
     261           0 : static int isl_stream_getc(__isl_keep isl_stream *s)
     262             : {
     263             :         int c;
     264             : 
     265             :         do {
     266           0 :                 s->start_line = s->line;
     267           0 :                 s->start_col = s->col;
     268           0 :                 c = stream_getc(s);
     269           0 :                 if (c != '\\')
     270           0 :                         return c;
     271           0 :                 c = stream_getc(s);
     272           0 :         } while (c == '\n');
     273             : 
     274           0 :         isl_stream_ungetc(s, c);
     275             : 
     276           0 :         return '\\';
     277             : }
     278             : 
     279           0 : static int isl_stream_push_char(__isl_keep isl_stream *s, int c)
     280             : {
     281           0 :         if (s->len >= s->size) {
     282             :                 char *buffer;
     283           0 :                 s->size = (3*s->size)/2;
     284           0 :                 buffer = isl_realloc_array(s->ctx, s->buffer, char, s->size);
     285           0 :                 if (!buffer)
     286           0 :                         return -1;
     287           0 :                 s->buffer = buffer;
     288             :         }
     289           0 :         s->buffer[s->len++] = c;
     290           0 :         return 0;
     291             : }
     292             : 
     293           0 : void isl_stream_push_token(__isl_keep isl_stream *s, struct isl_token *tok)
     294             : {
     295           0 :         isl_assert(s->ctx, s->n_token < 5, return);
     296           0 :         s->tokens[s->n_token++] = tok;
     297             : }
     298             : 
     299           0 : static enum isl_token_type check_keywords(__isl_keep isl_stream *s)
     300             : {
     301             :         struct isl_hash_table_entry *entry;
     302             :         struct isl_keyword *keyword;
     303             :         uint32_t name_hash;
     304             : 
     305           0 :         if (!strcasecmp(s->buffer, "exists"))
     306           0 :                 return ISL_TOKEN_EXISTS;
     307           0 :         if (!strcasecmp(s->buffer, "and"))
     308           0 :                 return ISL_TOKEN_AND;
     309           0 :         if (!strcasecmp(s->buffer, "or"))
     310           0 :                 return ISL_TOKEN_OR;
     311           0 :         if (!strcasecmp(s->buffer, "implies"))
     312           0 :                 return ISL_TOKEN_IMPLIES;
     313           0 :         if (!strcasecmp(s->buffer, "not"))
     314           0 :                 return ISL_TOKEN_NOT;
     315           0 :         if (!strcasecmp(s->buffer, "infty"))
     316           0 :                 return ISL_TOKEN_INFTY;
     317           0 :         if (!strcasecmp(s->buffer, "infinity"))
     318           0 :                 return ISL_TOKEN_INFTY;
     319           0 :         if (!strcasecmp(s->buffer, "NaN"))
     320           0 :                 return ISL_TOKEN_NAN;
     321           0 :         if (!strcasecmp(s->buffer, "min"))
     322           0 :                 return ISL_TOKEN_MIN;
     323           0 :         if (!strcasecmp(s->buffer, "max"))
     324           0 :                 return ISL_TOKEN_MAX;
     325           0 :         if (!strcasecmp(s->buffer, "rat"))
     326           0 :                 return ISL_TOKEN_RAT;
     327           0 :         if (!strcasecmp(s->buffer, "true"))
     328           0 :                 return ISL_TOKEN_TRUE;
     329           0 :         if (!strcasecmp(s->buffer, "false"))
     330           0 :                 return ISL_TOKEN_FALSE;
     331           0 :         if (!strcasecmp(s->buffer, "ceild"))
     332           0 :                 return ISL_TOKEN_CEILD;
     333           0 :         if (!strcasecmp(s->buffer, "floord"))
     334           0 :                 return ISL_TOKEN_FLOORD;
     335           0 :         if (!strcasecmp(s->buffer, "mod"))
     336           0 :                 return ISL_TOKEN_MOD;
     337           0 :         if (!strcasecmp(s->buffer, "ceil"))
     338           0 :                 return ISL_TOKEN_CEIL;
     339           0 :         if (!strcasecmp(s->buffer, "floor"))
     340           0 :                 return ISL_TOKEN_FLOOR;
     341             : 
     342           0 :         if (!s->keywords)
     343           0 :                 return ISL_TOKEN_IDENT;
     344             : 
     345           0 :         name_hash = isl_hash_string(isl_hash_init(), s->buffer);
     346           0 :         entry = isl_hash_table_find(s->ctx, s->keywords, name_hash, same_name,
     347           0 :                                         s->buffer, 0);
     348           0 :         if (entry) {
     349           0 :                 keyword = entry->data;
     350           0 :                 return keyword->type;
     351             :         }
     352             : 
     353           0 :         return ISL_TOKEN_IDENT;
     354             : }
     355             : 
     356           0 : int isl_stream_skip_line(__isl_keep isl_stream *s)
     357             : {
     358             :         int c;
     359             : 
     360           0 :         while ((c = isl_stream_getc(s)) != -1 && c != '\n')
     361             :                 /* nothing */
     362             :                 ;
     363             : 
     364           0 :         return c == -1 ? -1 : 0;
     365             : }
     366             : 
     367           0 : static struct isl_token *next_token(__isl_keep isl_stream *s, int same_line)
     368             : {
     369             :         int c;
     370           0 :         struct isl_token *tok = NULL;
     371             :         int line, col;
     372           0 :         int old_line = s->last_line;
     373             : 
     374           0 :         if (s->n_token) {
     375           0 :                 if (same_line && s->tokens[s->n_token - 1]->on_new_line)
     376           0 :                         return NULL;
     377           0 :                 return s->tokens[--s->n_token];
     378             :         }
     379             : 
     380           0 :         if (same_line && s->c == '\n')
     381           0 :                 return NULL;
     382             : 
     383           0 :         s->len = 0;
     384             : 
     385             :         /* skip spaces and comment lines */
     386           0 :         while ((c = isl_stream_getc(s)) != -1) {
     387           0 :                 if (c == '#') {
     388           0 :                         if (isl_stream_skip_line(s) < 0)
     389           0 :                                 break;
     390           0 :                         c = '\n';
     391           0 :                         if (same_line)
     392           0 :                                 break;
     393           0 :                 } else if (!isspace(c) || (same_line && c == '\n'))
     394             :                         break;
     395             :         }
     396             : 
     397           0 :         line = s->start_line;
     398           0 :         col = s->start_col;
     399             : 
     400           0 :         if (c == -1 || (same_line && c == '\n'))
     401           0 :                 return NULL;
     402           0 :         s->last_line = line;
     403             : 
     404           0 :         if (c == '(' ||
     405           0 :             c == ')' ||
     406           0 :             c == '+' ||
     407           0 :             c == '*' ||
     408           0 :             c == '%' ||
     409           0 :             c == '?' ||
     410           0 :             c == '^' ||
     411           0 :             c == '@' ||
     412           0 :             c == '$' ||
     413           0 :             c == ',' ||
     414           0 :             c == '.' ||
     415           0 :             c == ';' ||
     416           0 :             c == '[' ||
     417           0 :             c == ']' ||
     418           0 :             c == '{' ||
     419             :             c == '}') {
     420           0 :                 tok = isl_token_new(s->ctx, line, col, old_line != line);
     421           0 :                 if (!tok)
     422           0 :                         return NULL;
     423           0 :                 tok->type = (enum isl_token_type)c;
     424           0 :                 return tok;
     425             :         }
     426           0 :         if (c == '-') {
     427             :                 int c;
     428           0 :                 if ((c = isl_stream_getc(s)) == '>') {
     429           0 :                         tok = isl_token_new(s->ctx, line, col, old_line != line);
     430           0 :                         if (!tok)
     431           0 :                                 return NULL;
     432           0 :                         tok->u.s = strdup("->");
     433           0 :                         tok->type = ISL_TOKEN_TO;
     434           0 :                         return tok;
     435             :                 }
     436           0 :                 if (c != -1)
     437           0 :                         isl_stream_ungetc(s, c);
     438           0 :                 if (!isdigit(c)) {
     439           0 :                         tok = isl_token_new(s->ctx, line, col, old_line != line);
     440           0 :                         if (!tok)
     441           0 :                                 return NULL;
     442           0 :                         tok->type = (enum isl_token_type) '-';
     443           0 :                         return tok;
     444             :                 }
     445             :         }
     446           0 :         if (c == '-' || isdigit(c)) {
     447           0 :                 int minus = c == '-';
     448           0 :                 tok = isl_token_new(s->ctx, line, col, old_line != line);
     449           0 :                 if (!tok)
     450           0 :                         return NULL;
     451           0 :                 tok->type = ISL_TOKEN_VALUE;
     452           0 :                 isl_int_init(tok->u.v);
     453           0 :                 if (isl_stream_push_char(s, c))
     454           0 :                         goto error;
     455           0 :                 while ((c = isl_stream_getc(s)) != -1 && isdigit(c))
     456           0 :                         if (isl_stream_push_char(s, c))
     457           0 :                                 goto error;
     458           0 :                 if (c != -1)
     459           0 :                         isl_stream_ungetc(s, c);
     460           0 :                 isl_stream_push_char(s, '\0');
     461           0 :                 isl_int_read(tok->u.v, s->buffer);
     462           0 :                 if (minus && isl_int_is_zero(tok->u.v)) {
     463           0 :                         tok->col++;
     464           0 :                         tok->on_new_line = 0;
     465           0 :                         isl_stream_push_token(s, tok);
     466           0 :                         tok = isl_token_new(s->ctx, line, col, old_line != line);
     467           0 :                         if (!tok)
     468           0 :                                 return NULL;
     469           0 :                         tok->type = (enum isl_token_type) '-';
     470             :                 }
     471           0 :                 return tok;
     472             :         }
     473           0 :         if (isalpha(c) || c == '_') {
     474           0 :                 tok = isl_token_new(s->ctx, line, col, old_line != line);
     475           0 :                 if (!tok)
     476           0 :                         return NULL;
     477           0 :                 isl_stream_push_char(s, c);
     478           0 :                 while ((c = isl_stream_getc(s)) != -1 &&
     479           0 :                                 (isalnum(c) || c == '_'))
     480           0 :                         isl_stream_push_char(s, c);
     481           0 :                 if (c != -1)
     482           0 :                         isl_stream_ungetc(s, c);
     483           0 :                 while ((c = isl_stream_getc(s)) != -1 && c == '\'')
     484           0 :                         isl_stream_push_char(s, c);
     485           0 :                 if (c != -1)
     486           0 :                         isl_stream_ungetc(s, c);
     487           0 :                 isl_stream_push_char(s, '\0');
     488           0 :                 tok->type = check_keywords(s);
     489           0 :                 if (tok->type != ISL_TOKEN_IDENT)
     490           0 :                         tok->is_keyword = 1;
     491           0 :                 tok->u.s = strdup(s->buffer);
     492           0 :                 if (!tok->u.s)
     493           0 :                         goto error;
     494           0 :                 return tok;
     495             :         }
     496           0 :         if (c == '"') {
     497           0 :                 tok = isl_token_new(s->ctx, line, col, old_line != line);
     498           0 :                 if (!tok)
     499           0 :                         return NULL;
     500           0 :                 tok->type = ISL_TOKEN_STRING;
     501           0 :                 tok->u.s = NULL;
     502           0 :                 while ((c = isl_stream_getc(s)) != -1 && c != '"' && c != '\n')
     503           0 :                         isl_stream_push_char(s, c);
     504           0 :                 if (c != '"') {
     505           0 :                         isl_stream_error(s, NULL, "unterminated string");
     506           0 :                         goto error;
     507             :                 }
     508           0 :                 isl_stream_push_char(s, '\0');
     509           0 :                 tok->u.s = strdup(s->buffer);
     510           0 :                 return tok;
     511             :         }
     512           0 :         if (c == '=') {
     513             :                 int c;
     514           0 :                 tok = isl_token_new(s->ctx, line, col, old_line != line);
     515           0 :                 if (!tok)
     516           0 :                         return NULL;
     517           0 :                 if ((c = isl_stream_getc(s)) == '=') {
     518           0 :                         tok->u.s = strdup("==");
     519           0 :                         tok->type = ISL_TOKEN_EQ_EQ;
     520           0 :                         return tok;
     521             :                 }
     522           0 :                 if (c != -1)
     523           0 :                         isl_stream_ungetc(s, c);
     524           0 :                 tok->type = (enum isl_token_type) '=';
     525           0 :                 return tok;
     526             :         }
     527           0 :         if (c == ':') {
     528             :                 int c;
     529           0 :                 tok = isl_token_new(s->ctx, line, col, old_line != line);
     530           0 :                 if (!tok)
     531           0 :                         return NULL;
     532           0 :                 if ((c = isl_stream_getc(s)) == '=') {
     533           0 :                         tok->u.s = strdup(":=");
     534           0 :                         tok->type = ISL_TOKEN_DEF;
     535           0 :                         return tok;
     536             :                 }
     537           0 :                 if (c != -1)
     538           0 :                         isl_stream_ungetc(s, c);
     539           0 :                 tok->type = (enum isl_token_type) ':';
     540           0 :                 return tok;
     541             :         }
     542           0 :         if (c == '>') {
     543             :                 int c;
     544           0 :                 tok = isl_token_new(s->ctx, line, col, old_line != line);
     545           0 :                 if (!tok)
     546           0 :                         return NULL;
     547           0 :                 if ((c = isl_stream_getc(s)) == '=') {
     548           0 :                         tok->u.s = strdup(">=");
     549           0 :                         tok->type = ISL_TOKEN_GE;
     550           0 :                         return tok;
     551           0 :                 } else if (c == '>') {
     552           0 :                         if ((c = isl_stream_getc(s)) == '=') {
     553           0 :                                 tok->u.s = strdup(">>=");
     554           0 :                                 tok->type = ISL_TOKEN_LEX_GE;
     555           0 :                                 return tok;
     556             :                         }
     557           0 :                         tok->u.s = strdup(">>");
     558           0 :                         tok->type = ISL_TOKEN_LEX_GT;
     559             :                 } else {
     560           0 :                         tok->u.s = strdup(">");
     561           0 :                         tok->type = ISL_TOKEN_GT;
     562             :                 }
     563           0 :                 if (c != -1)
     564           0 :                         isl_stream_ungetc(s, c);
     565           0 :                 return tok;
     566             :         }
     567           0 :         if (c == '<') {
     568             :                 int c;
     569           0 :                 tok = isl_token_new(s->ctx, line, col, old_line != line);
     570           0 :                 if (!tok)
     571           0 :                         return NULL;
     572           0 :                 if ((c = isl_stream_getc(s)) == '=') {
     573           0 :                         tok->u.s = strdup("<=");
     574           0 :                         tok->type = ISL_TOKEN_LE;
     575           0 :                         return tok;
     576           0 :                 } else if (c == '<') {
     577           0 :                         if ((c = isl_stream_getc(s)) == '=') {
     578           0 :                                 tok->u.s = strdup("<<=");
     579           0 :                                 tok->type = ISL_TOKEN_LEX_LE;
     580           0 :                                 return tok;
     581             :                         }
     582           0 :                         tok->u.s = strdup("<<");
     583           0 :                         tok->type = ISL_TOKEN_LEX_LT;
     584             :                 } else {
     585           0 :                         tok->u.s = strdup("<");
     586           0 :                         tok->type = ISL_TOKEN_LT;
     587             :                 }
     588           0 :                 if (c != -1)
     589           0 :                         isl_stream_ungetc(s, c);
     590           0 :                 return tok;
     591             :         }
     592           0 :         if (c == '&') {
     593           0 :                 tok = isl_token_new(s->ctx, line, col, old_line != line);
     594           0 :                 if (!tok)
     595           0 :                         return NULL;
     596           0 :                 tok->type = ISL_TOKEN_AND;
     597           0 :                 if ((c = isl_stream_getc(s)) != '&' && c != -1) {
     598           0 :                         tok->u.s = strdup("&");
     599           0 :                         isl_stream_ungetc(s, c);
     600             :                 } else
     601           0 :                         tok->u.s = strdup("&&");
     602           0 :                 return tok;
     603             :         }
     604           0 :         if (c == '|') {
     605           0 :                 tok = isl_token_new(s->ctx, line, col, old_line != line);
     606           0 :                 if (!tok)
     607           0 :                         return NULL;
     608           0 :                 tok->type = ISL_TOKEN_OR;
     609           0 :                 if ((c = isl_stream_getc(s)) != '|' && c != -1) {
     610           0 :                         tok->u.s = strdup("|");
     611           0 :                         isl_stream_ungetc(s, c);
     612             :                 } else
     613           0 :                         tok->u.s = strdup("||");
     614           0 :                 return tok;
     615             :         }
     616           0 :         if (c == '/') {
     617           0 :                 tok = isl_token_new(s->ctx, line, col, old_line != line);
     618           0 :                 if (!tok)
     619           0 :                         return NULL;
     620           0 :                 if ((c = isl_stream_getc(s)) != '\\' && c != -1) {
     621           0 :                         tok->type = (enum isl_token_type) '/';
     622           0 :                         isl_stream_ungetc(s, c);
     623             :                 } else {
     624           0 :                         tok->u.s = strdup("/\\");
     625           0 :                         tok->type = ISL_TOKEN_AND;
     626             :                 }
     627           0 :                 return tok;
     628             :         }
     629           0 :         if (c == '\\') {
     630           0 :                 tok = isl_token_new(s->ctx, line, col, old_line != line);
     631           0 :                 if (!tok)
     632           0 :                         return NULL;
     633           0 :                 if ((c = isl_stream_getc(s)) != '/' && c != -1) {
     634           0 :                         tok->type = (enum isl_token_type) '\\';
     635           0 :                         isl_stream_ungetc(s, c);
     636             :                 } else {
     637           0 :                         tok->u.s = strdup("\\/");
     638           0 :                         tok->type = ISL_TOKEN_OR;
     639             :                 }
     640           0 :                 return tok;
     641             :         }
     642           0 :         if (c == '!') {
     643           0 :                 tok = isl_token_new(s->ctx, line, col, old_line != line);
     644           0 :                 if (!tok)
     645           0 :                         return NULL;
     646           0 :                 if ((c = isl_stream_getc(s)) == '=') {
     647           0 :                         tok->u.s = strdup("!=");
     648           0 :                         tok->type = ISL_TOKEN_NE;
     649           0 :                         return tok;
     650             :                 } else {
     651           0 :                         tok->type = ISL_TOKEN_NOT;
     652           0 :                         tok->u.s = strdup("!");
     653             :                 }
     654           0 :                 if (c != -1)
     655           0 :                         isl_stream_ungetc(s, c);
     656           0 :                 return tok;
     657             :         }
     658             : 
     659           0 :         tok = isl_token_new(s->ctx, line, col, old_line != line);
     660           0 :         if (!tok)
     661           0 :                 return NULL;
     662           0 :         tok->type = ISL_TOKEN_UNKNOWN;
     663           0 :         return tok;
     664             : error:
     665           0 :         isl_token_free(tok);
     666           0 :         return NULL;
     667             : }
     668             : 
     669           0 : struct isl_token *isl_stream_next_token(__isl_keep isl_stream *s)
     670             : {
     671           0 :         return next_token(s, 0);
     672             : }
     673             : 
     674           0 : struct isl_token *isl_stream_next_token_on_same_line(__isl_keep isl_stream *s)
     675             : {
     676           0 :         return next_token(s, 1);
     677             : }
     678             : 
     679           0 : int isl_stream_eat_if_available(__isl_keep isl_stream *s, int type)
     680             : {
     681             :         struct isl_token *tok;
     682             : 
     683           0 :         tok = isl_stream_next_token(s);
     684           0 :         if (!tok)
     685           0 :                 return 0;
     686           0 :         if (tok->type == type) {
     687           0 :                 isl_token_free(tok);
     688           0 :                 return 1;
     689             :         }
     690           0 :         isl_stream_push_token(s, tok);
     691           0 :         return 0;
     692             : }
     693             : 
     694           0 : int isl_stream_next_token_is(__isl_keep isl_stream *s, int type)
     695             : {
     696             :         struct isl_token *tok;
     697             :         int r;
     698             : 
     699           0 :         tok = isl_stream_next_token(s);
     700           0 :         if (!tok)
     701           0 :                 return 0;
     702           0 :         r = tok->type == type;
     703           0 :         isl_stream_push_token(s, tok);
     704           0 :         return r;
     705             : }
     706             : 
     707           0 : char *isl_stream_read_ident_if_available(__isl_keep isl_stream *s)
     708             : {
     709             :         struct isl_token *tok;
     710             : 
     711           0 :         tok = isl_stream_next_token(s);
     712           0 :         if (!tok)
     713           0 :                 return NULL;
     714           0 :         if (tok->type == ISL_TOKEN_IDENT) {
     715           0 :                 char *ident = strdup(tok->u.s);
     716           0 :                 isl_token_free(tok);
     717           0 :                 return ident;
     718             :         }
     719           0 :         isl_stream_push_token(s, tok);
     720           0 :         return NULL;
     721             : }
     722             : 
     723           0 : int isl_stream_eat(__isl_keep isl_stream *s, int type)
     724             : {
     725             :         struct isl_token *tok;
     726             : 
     727           0 :         tok = isl_stream_next_token(s);
     728           0 :         if (!tok) {
     729           0 :                 if (s->eof)
     730           0 :                         isl_stream_error(s, NULL, "unexpected EOF");
     731           0 :                 return -1;
     732             :         }
     733           0 :         if (tok->type == type) {
     734           0 :                 isl_token_free(tok);
     735           0 :                 return 0;
     736             :         }
     737           0 :         isl_stream_error(s, tok, "expecting other token");
     738           0 :         isl_stream_push_token(s, tok);
     739           0 :         return -1;
     740             : }
     741             : 
     742           0 : int isl_stream_is_empty(__isl_keep isl_stream *s)
     743             : {
     744             :         struct isl_token *tok;
     745             : 
     746           0 :         tok = isl_stream_next_token(s);
     747             : 
     748           0 :         if (!tok)
     749           0 :                 return 1;
     750             : 
     751           0 :         isl_stream_push_token(s, tok);
     752           0 :         return 0;
     753             : }
     754             : 
     755           0 : static isl_stat free_keyword(void **p, void *user)
     756             : {
     757           0 :         struct isl_keyword *keyword = *p;
     758             : 
     759           0 :         free(keyword->name);
     760           0 :         free(keyword);
     761             : 
     762           0 :         return isl_stat_ok;
     763             : }
     764             : 
     765           0 : void isl_stream_flush_tokens(__isl_keep isl_stream *s)
     766             : {
     767             :         int i;
     768             : 
     769           0 :         if (!s)
     770           0 :                 return;
     771           0 :         for (i = 0; i < s->n_token; ++i)
     772           0 :                 isl_token_free(s->tokens[i]);
     773           0 :         s->n_token = 0;
     774             : }
     775             : 
     776           0 : isl_ctx *isl_stream_get_ctx(__isl_keep isl_stream *s)
     777             : {
     778           0 :         return s ? s->ctx : NULL;
     779             : }
     780             : 
     781           0 : void isl_stream_free(__isl_take isl_stream *s)
     782             : {
     783           0 :         if (!s)
     784           0 :                 return;
     785           0 :         free(s->buffer);
     786           0 :         if (s->n_token != 0) {
     787           0 :                 struct isl_token *tok = isl_stream_next_token(s);
     788           0 :                 isl_stream_error(s, tok, "unexpected token");
     789           0 :                 isl_token_free(tok);
     790             :         }
     791           0 :         if (s->keywords) {
     792           0 :                 isl_hash_table_foreach(s->ctx, s->keywords, &free_keyword, NULL);
     793           0 :                 isl_hash_table_free(s->ctx, s->keywords);
     794             :         }
     795           0 :         free(s->yaml_state);
     796           0 :         free(s->yaml_indent);
     797           0 :         isl_ctx_deref(s->ctx);
     798           0 :         free(s);
     799             : }
     800             : 
     801             : /* Push "state" onto the stack of currently active YAML elements.
     802             :  * The caller is responsible for setting the corresponding indentation.
     803             :  * Return 0 on success and -1 on failure.
     804             :  */
     805           0 : static int push_state(__isl_keep isl_stream *s, enum isl_yaml_state state)
     806             : {
     807           0 :         if (s->yaml_size < s->yaml_depth + 1) {
     808             :                 int *indent;
     809             :                 enum isl_yaml_state *state;
     810             : 
     811           0 :                 state = isl_realloc_array(s->ctx, s->yaml_state,
     812             :                                         enum isl_yaml_state, s->yaml_depth + 1);
     813           0 :                 if (!state)
     814           0 :                         return -1;
     815           0 :                 s->yaml_state = state;
     816             : 
     817           0 :                 indent = isl_realloc_array(s->ctx, s->yaml_indent,
     818             :                                         int, s->yaml_depth + 1);
     819           0 :                 if (!indent)
     820           0 :                         return -1;
     821           0 :                 s->yaml_indent = indent;
     822             : 
     823           0 :                 s->yaml_size = s->yaml_depth + 1;
     824             :         }
     825             : 
     826           0 :         s->yaml_state[s->yaml_depth] = state;
     827           0 :         s->yaml_depth++;
     828             : 
     829           0 :         return 0;
     830             : }
     831             : 
     832             : /* Remove the innermost active YAML element from the stack.
     833             :  * Return 0 on success and -1 on failure.
     834             :  */
     835           0 : static int pop_state(__isl_keep isl_stream *s)
     836             : {
     837           0 :         if (!s)
     838           0 :                 return -1;
     839           0 :         if (s->yaml_depth < 1)
     840           0 :                 isl_die(isl_stream_get_ctx(s), isl_error_invalid,
     841             :                         "not in YAML construct", return -1);
     842             : 
     843           0 :         s->yaml_depth--;
     844             : 
     845           0 :         return 0;
     846             : }
     847             : 
     848             : /* Set the state of the innermost active YAML element to "state".
     849             :  * Return 0 on success and -1 on failure.
     850             :  */
     851           0 : static int update_state(__isl_keep isl_stream *s, enum isl_yaml_state state)
     852             : {
     853           0 :         if (!s)
     854           0 :                 return -1;
     855           0 :         if (s->yaml_depth < 1)
     856           0 :                 isl_die(isl_stream_get_ctx(s), isl_error_invalid,
     857             :                         "not in YAML construct", return -1);
     858             : 
     859           0 :         s->yaml_state[s->yaml_depth - 1] = state;
     860             : 
     861           0 :         return 0;
     862             : }
     863             : 
     864             : /* Return the state of the innermost active YAML element.
     865             :  * Return isl_yaml_none if we are not inside any YAML element.
     866             :  */
     867           0 : static enum isl_yaml_state current_state(__isl_keep isl_stream *s)
     868             : {
     869           0 :         if (!s)
     870           0 :                 return isl_yaml_none;
     871           0 :         if (s->yaml_depth < 1)
     872           0 :                 return isl_yaml_none;
     873           0 :         return s->yaml_state[s->yaml_depth - 1];
     874             : }
     875             : 
     876             : /* Set the indentation of the innermost active YAML element to "indent".
     877             :  * If "indent" is equal to ISL_YAML_INDENT_FLOW, then this means
     878             :  * that the current elemient is in flow format.
     879             :  */
     880           0 : static int set_yaml_indent(__isl_keep isl_stream *s, int indent)
     881             : {
     882           0 :         if (s->yaml_depth < 1)
     883           0 :                 isl_die(s->ctx, isl_error_internal,
     884             :                         "not in YAML element", return -1);
     885             : 
     886           0 :         s->yaml_indent[s->yaml_depth - 1] = indent;
     887             : 
     888           0 :         return 0;
     889             : }
     890             : 
     891             : /* Return the indentation of the innermost active YAML element
     892             :  * of -1 on error.
     893             :  */
     894           0 : static int get_yaml_indent(__isl_keep isl_stream *s)
     895             : {
     896           0 :         if (s->yaml_depth < 1)
     897           0 :                 isl_die(s->ctx, isl_error_internal,
     898             :                         "not in YAML element", return -1);
     899             : 
     900           0 :         return s->yaml_indent[s->yaml_depth - 1];
     901             : }
     902             : 
     903             : /* Move to the next state at the innermost level.
     904             :  * Return 1 if successful.
     905             :  * Return 0 if we are at the end of the innermost level.
     906             :  * Return -1 on error.
     907             :  *
     908             :  * If we are in state isl_yaml_mapping_key_start, then we have just
     909             :  * started a mapping and we are expecting a key.  If the mapping started
     910             :  * with a '{', then we check if the next token is a '}'.  If so,
     911             :  * then the mapping is empty and there is no next state at this level.
     912             :  * Otherwise, we assume that there is at least one key (the one from
     913             :  * which we derived the indentation in isl_stream_yaml_read_start_mapping.
     914             :  *
     915             :  * If we are in state isl_yaml_mapping_key, then the we expect a colon
     916             :  * followed by a value, so there is always a next state unless
     917             :  * some error occurs.
     918             :  *
     919             :  * If we are in state isl_yaml_mapping_val, then there may or may
     920             :  * not be a subsequent key in the same mapping.
     921             :  * In flow format, the next key is preceded by a comma.
     922             :  * In block format, the next key has the same indentation as the first key.
     923             :  * If the first token has a smaller indentation, then we have reached
     924             :  * the end of the current mapping.
     925             :  *
     926             :  * If we are in state isl_yaml_sequence_start, then we have just
     927             :  * started a sequence.  If the sequence started with a '[',
     928             :  * then we check if the next token is a ']'.  If so, then the sequence
     929             :  * is empty and there is no next state at this level.
     930             :  * Otherwise, we assume that there is at least one element in the sequence
     931             :  * (the one from which we derived the indentation in
     932             :  * isl_stream_yaml_read_start_sequence.
     933             :  *
     934             :  * If we are in state isl_yaml_sequence, then there may or may
     935             :  * not be a subsequent element in the same sequence.
     936             :  * In flow format, the next element is preceded by a comma.
     937             :  * In block format, the next element is introduced by a dash with
     938             :  * the same indentation as that of the first element.
     939             :  * If the first token is not a dash or if it has a smaller indentation,
     940             :  * then we have reached the end of the current sequence.
     941             :  */
     942           0 : int isl_stream_yaml_next(__isl_keep isl_stream *s)
     943             : {
     944             :         struct isl_token *tok;
     945             :         enum isl_yaml_state state;
     946             :         int indent;
     947             : 
     948           0 :         state = current_state(s);
     949           0 :         if (state == isl_yaml_none)
     950           0 :                 isl_die(s->ctx, isl_error_invalid,
     951             :                         "not in YAML element", return -1);
     952           0 :         switch (state) {
     953             :         case isl_yaml_mapping_key_start:
     954           0 :                 if (get_yaml_indent(s) == ISL_YAML_INDENT_FLOW &&
     955           0 :                     isl_stream_next_token_is(s, '}'))
     956           0 :                         return 0;
     957           0 :                 if (update_state(s, isl_yaml_mapping_key) < 0)
     958           0 :                         return -1;
     959           0 :                 return 1;
     960             :         case isl_yaml_mapping_key:
     961           0 :                 tok = isl_stream_next_token(s);
     962           0 :                 if (!tok) {
     963           0 :                         if (s->eof)
     964           0 :                                 isl_stream_error(s, NULL, "unexpected EOF");
     965           0 :                         return -1;
     966             :                 }
     967           0 :                 if (tok->type == ':') {
     968           0 :                         isl_token_free(tok);
     969           0 :                         if (update_state(s, isl_yaml_mapping_val) < 0)
     970           0 :                                 return -1;
     971           0 :                         return 1;
     972             :                 }
     973           0 :                 isl_stream_error(s, tok, "expecting ':'");
     974           0 :                 isl_stream_push_token(s, tok);
     975           0 :                 return -1;
     976             :         case isl_yaml_mapping_val:
     977           0 :                 if (get_yaml_indent(s) == ISL_YAML_INDENT_FLOW) {
     978           0 :                         if (!isl_stream_eat_if_available(s, ','))
     979           0 :                                 return 0;
     980           0 :                         if (update_state(s, isl_yaml_mapping_key) < 0)
     981           0 :                                 return -1;
     982           0 :                         return 1;
     983             :                 }
     984           0 :                 tok = isl_stream_next_token(s);
     985           0 :                 if (!tok)
     986           0 :                         return 0;
     987           0 :                 indent = tok->col - 1;
     988           0 :                 isl_stream_push_token(s, tok);
     989           0 :                 if (indent < get_yaml_indent(s))
     990           0 :                         return 0;
     991           0 :                 if (update_state(s, isl_yaml_mapping_key) < 0)
     992           0 :                         return -1;
     993           0 :                 return 1;
     994             :         case isl_yaml_sequence_start:
     995           0 :                 if (get_yaml_indent(s) == ISL_YAML_INDENT_FLOW) {
     996           0 :                         if (isl_stream_next_token_is(s, ']'))
     997           0 :                                 return 0;
     998           0 :                         if (update_state(s, isl_yaml_sequence) < 0)
     999           0 :                                 return -1;
    1000           0 :                         return 1;
    1001             :                 }
    1002           0 :                 tok = isl_stream_next_token(s);
    1003           0 :                 if (!tok) {
    1004           0 :                         if (s->eof)
    1005           0 :                                 isl_stream_error(s, NULL, "unexpected EOF");
    1006           0 :                         return -1;
    1007             :                 }
    1008           0 :                 if (tok->type == '-') {
    1009           0 :                         isl_token_free(tok);
    1010           0 :                         if (update_state(s, isl_yaml_sequence) < 0)
    1011           0 :                                 return -1;
    1012           0 :                         return 1;
    1013             :                 }
    1014           0 :                 isl_stream_error(s, tok, "expecting '-'");
    1015           0 :                 isl_stream_push_token(s, tok);
    1016           0 :                 return 0;
    1017             :         case isl_yaml_sequence:
    1018           0 :                 if (get_yaml_indent(s) == ISL_YAML_INDENT_FLOW)
    1019           0 :                         return isl_stream_eat_if_available(s, ',');
    1020           0 :                 tok = isl_stream_next_token(s);
    1021           0 :                 if (!tok)
    1022           0 :                         return 0;
    1023           0 :                 indent = tok->col - 1;
    1024           0 :                 if (indent < get_yaml_indent(s) || tok->type != '-') {
    1025           0 :                         isl_stream_push_token(s, tok);
    1026           0 :                         return 0;
    1027             :                 }
    1028           0 :                 isl_token_free(tok);
    1029           0 :                 return 1;
    1030             :         default:
    1031           0 :                 isl_die(s->ctx, isl_error_internal,
    1032             :                         "unexpected state", return 0);
    1033             :         }
    1034             : }
    1035             : 
    1036             : /* Start reading a YAML mapping.
    1037             :  * Return 0 on success and -1 on error.
    1038             :  *
    1039             :  * If the first token on the stream is a '{' then we remove this token
    1040             :  * from the stream and keep track of the fact that the mapping
    1041             :  * is given in flow format.
    1042             :  * Otherwise, we assume the first token is the first key of the mapping and
    1043             :  * keep track of its indentation, but keep the token on the stream.
    1044             :  * In both cases, the next token we expect is the first key of the mapping.
    1045             :  */
    1046           0 : int isl_stream_yaml_read_start_mapping(__isl_keep isl_stream *s)
    1047             : {
    1048             :         struct isl_token *tok;
    1049             :         int indent;
    1050             : 
    1051           0 :         if (push_state(s, isl_yaml_mapping_key_start) < 0)
    1052           0 :                 return -1;
    1053             : 
    1054           0 :         tok = isl_stream_next_token(s);
    1055           0 :         if (!tok) {
    1056           0 :                 if (s->eof)
    1057           0 :                         isl_stream_error(s, NULL, "unexpected EOF");
    1058           0 :                 return -1;
    1059             :         }
    1060           0 :         if (isl_token_get_type(tok) == '{') {
    1061           0 :                 isl_token_free(tok);
    1062           0 :                 return set_yaml_indent(s, ISL_YAML_INDENT_FLOW);
    1063             :         }
    1064           0 :         indent = tok->col - 1;
    1065           0 :         isl_stream_push_token(s, tok);
    1066             : 
    1067           0 :         return set_yaml_indent(s, indent);
    1068             : }
    1069             : 
    1070             : /* Finish reading a YAML mapping.
    1071             :  * Return 0 on success and -1 on error.
    1072             :  *
    1073             :  * If the mapping started with a '{', then we expect a '}' to close
    1074             :  * the mapping.
    1075             :  * Otherwise, we double-check that the next token (if any)
    1076             :  * has a smaller indentation than that of the current mapping.
    1077             :  */
    1078           0 : int isl_stream_yaml_read_end_mapping(__isl_keep isl_stream *s)
    1079             : {
    1080             :         struct isl_token *tok;
    1081             :         int indent;
    1082             : 
    1083           0 :         if (get_yaml_indent(s) == ISL_YAML_INDENT_FLOW) {
    1084           0 :                 if (isl_stream_eat(s, '}') < 0)
    1085           0 :                         return -1;
    1086           0 :                 return pop_state(s);
    1087             :         }
    1088             : 
    1089           0 :         tok = isl_stream_next_token(s);
    1090           0 :         if (!tok)
    1091           0 :                 return pop_state(s);
    1092             : 
    1093           0 :         indent = tok->col - 1;
    1094           0 :         isl_stream_push_token(s, tok);
    1095             : 
    1096           0 :         if (indent >= get_yaml_indent(s))
    1097           0 :                 isl_die(isl_stream_get_ctx(s), isl_error_invalid,
    1098             :                         "mapping not finished", return -1);
    1099             : 
    1100           0 :         return pop_state(s);
    1101             : }
    1102             : 
    1103             : /* Start reading a YAML sequence.
    1104             :  * Return 0 on success and -1 on error.
    1105             :  *
    1106             :  * If the first token on the stream is a '[' then we remove this token
    1107             :  * from the stream and keep track of the fact that the sequence
    1108             :  * is given in flow format.
    1109             :  * Otherwise, we assume the first token is the dash that introduces
    1110             :  * the first element of the sequence and keep track of its indentation,
    1111             :  * but keep the token on the stream.
    1112             :  * In both cases, the next token we expect is the first element
    1113             :  * of the sequence.
    1114             :  */
    1115           0 : int isl_stream_yaml_read_start_sequence(__isl_keep isl_stream *s)
    1116             : {
    1117             :         struct isl_token *tok;
    1118             :         int indent;
    1119             : 
    1120           0 :         if (push_state(s, isl_yaml_sequence_start) < 0)
    1121           0 :                 return -1;
    1122             : 
    1123           0 :         tok = isl_stream_next_token(s);
    1124           0 :         if (!tok) {
    1125           0 :                 if (s->eof)
    1126           0 :                         isl_stream_error(s, NULL, "unexpected EOF");
    1127           0 :                 return -1;
    1128             :         }
    1129           0 :         if (isl_token_get_type(tok) == '[') {
    1130           0 :                 isl_token_free(tok);
    1131           0 :                 return set_yaml_indent(s, ISL_YAML_INDENT_FLOW);
    1132             :         }
    1133           0 :         indent = tok->col - 1;
    1134           0 :         isl_stream_push_token(s, tok);
    1135             : 
    1136           0 :         return set_yaml_indent(s, indent);
    1137             : }
    1138             : 
    1139             : /* Finish reading a YAML sequence.
    1140             :  * Return 0 on success and -1 on error.
    1141             :  *
    1142             :  * If the sequence started with a '[', then we expect a ']' to close
    1143             :  * the sequence.
    1144             :  * Otherwise, we double-check that the next token (if any)
    1145             :  * is not a dash or that it has a smaller indentation than
    1146             :  * that of the current sequence.
    1147             :  */
    1148           0 : int isl_stream_yaml_read_end_sequence(__isl_keep isl_stream *s)
    1149             : {
    1150             :         struct isl_token *tok;
    1151             :         int indent;
    1152             :         int dash;
    1153             : 
    1154           0 :         if (get_yaml_indent(s) == ISL_YAML_INDENT_FLOW) {
    1155           0 :                 if (isl_stream_eat(s, ']') < 0)
    1156           0 :                         return -1;
    1157           0 :                 return pop_state(s);
    1158             :         }
    1159             : 
    1160           0 :         tok = isl_stream_next_token(s);
    1161           0 :         if (!tok)
    1162           0 :                 return pop_state(s);
    1163             : 
    1164           0 :         indent = tok->col - 1;
    1165           0 :         dash = tok->type == '-';
    1166           0 :         isl_stream_push_token(s, tok);
    1167             : 
    1168           0 :         if (indent >= get_yaml_indent(s) && dash)
    1169           0 :                 isl_die(isl_stream_get_ctx(s), isl_error_invalid,
    1170             :                         "sequence not finished", return -1);
    1171             : 
    1172           0 :         return pop_state(s);
    1173             : }

Generated by: LCOV version 1.12