X-Git-Url: http://andersk.mit.edu/gitweb/libyaml.git/blobdiff_plain/21fbedd41555fc23a512b3ad7799b12e53eb3775..1893dabd78f6707d07882049997b7c2879bf02b9:/src/scanner.c diff --git a/src/scanner.c b/src/scanner.c index e701aa5..86e2050 100644 --- a/src/scanner.c +++ b/src/scanner.c @@ -475,318 +475,103 @@ * BLOCK-END */ -#if HAVE_CONFIG_H -#include -#endif - -#include - -#include +#include "yaml_private.h" /* * Ensure that the buffer contains the required number of characters. * Return 1 on success, 0 on failure (reader error or memory error). */ -#define UPDATE(parser,length) \ - (parser->unread >= (length) \ - ? 1 \ +#define CACHE(parser,length) \ + (parser->unread >= (length) \ + ? 1 \ : yaml_parser_update_buffer(parser, (length))) -/* - * Check the octet at the specified position. - */ - -#define CHECK_AT(parser,octet,offset) \ - (parser->pointer[offset] == (yaml_char_t)(octet)) - -/* - * Check the current octet in the buffer. - */ - -#define CHECK(parser,octet) CHECK_AT(parser,(octet),0) - -/* - * Check if the character at the specified position is an alphabetical - * character, a digit, '_', or '-'. - */ - -#define IS_ALPHA_AT(parser,offset) \ - ((parser->pointer[offset] >= (yaml_char_t) '0' && \ - parser->pointer[offset] <= (yaml_char_t) '9') || \ - (parser->pointer[offset] >= (yaml_char_t) 'A' && \ - parser->pointer[offset] <= (yaml_char_t) 'Z') || \ - (parser->pointer[offset] >= (yaml_char_t) 'a' && \ - parser->pointer[offset] <= (yaml_char_t) 'z') || \ - parser->pointer[offset] == '_' || \ - parser->pointer[offset] == '-') - -#define IS_ALPHA(parser) IS_ALPHA_AT(parser,0) - -/* - * Check if the character at the specified position is a digit. - */ - -#define IS_DIGIT_AT(parser,offset) \ - ((parser->pointer[offset] >= (yaml_char_t) '0' && \ - parser->pointer[offset] <= (yaml_char_t) '9')) - -#define IS_DIGIT(parser) IS_DIGIT_AT(parser,0) - -/* - * Get the value of a digit. - */ - -#define AS_DIGIT_AT(parser,offset) \ - (parser->pointer[offset] - (yaml_char_t) '0') - -#define AS_DIGIT(parser) AS_DIGIT_AT(parser,0) - -/* - * Check if the character at the specified position is a hex-digit. - */ - -#define IS_HEX_AT(parser,offset) \ - ((parser->pointer[offset] >= (yaml_char_t) '0' && \ - parser->pointer[offset] <= (yaml_char_t) '9') || \ - (parser->pointer[offset] >= (yaml_char_t) 'A' && \ - parser->pointer[offset] <= (yaml_char_t) 'F') || \ - (parser->pointer[offset] >= (yaml_char_t) 'a' && \ - parser->pointer[offset] <= (yaml_char_t) 'f')) - -#define IS_HEX(parser) IS_HEX_AT(parser,0) - -/* - * Get the value of a hex-digit. - */ - -#define AS_HEX_AT(parser,offset) \ - ((parser->pointer[offset] >= (yaml_char_t) 'A' && \ - parser->pointer[offset] <= (yaml_char_t) 'F') ? \ - (parser->pointer[offset] - (yaml_char_t) 'A' + 10) : \ - (parser->pointer[offset] >= (yaml_char_t) 'a' && \ - parser->pointer[offset] <= (yaml_char_t) 'f') ? \ - (parser->pointer[offset] - (yaml_char_t) 'a' + 10) : \ - (parser->pointer[offset] - (yaml_char_t) '0')) - -#define AS_HEX(parser) AS_HEX_AT(parser,0) - -/* - * Check if the character at the specified position is NUL. - */ - -#define IS_Z_AT(parser,offset) CHECK_AT(parser,'\0',(offset)) - -#define IS_Z(parser) IS_Z_AT(parser,0) - -/* - * Check if the character at the specified position is BOM. - */ - -#define IS_BOM_AT(parser,offset) \ - (CHECK_AT(parser,'\xEF',(offset)) \ - && CHECK_AT(parser,'\xBB',(offset)+1) \ - && CHECK_AT(parser,'\xBF',(offset)+1)) /* BOM (#xFEFF) */ - -#define IS_BOM(parser) IS_BOM_AT(parser,0) - -/* - * Check if the character at the specified position is space. - */ - -#define IS_SPACE_AT(parser,offset) CHECK_AT(parser,' ',(offset)) - -#define IS_SPACE(parser) IS_SPACE_AT(parser,0) - -/* - * Check if the character at the specified position is tab. - */ - -#define IS_TAB_AT(parser,offset) CHECK_AT(parser,'\t',(offset)) - -#define IS_TAB(parser) IS_TAB_AT(parser,0) - -/* - * Check if the character at the specified position is blank (space or tab). - */ - -#define IS_BLANK_AT(parser,offset) \ - (IS_SPACE_AT(parser,(offset)) || IS_TAB_AT(parser,(offset))) - -#define IS_BLANK(parser) IS_BLANK_AT(parser,0) - -/* - * Check if the character at the specified position is a line break. - */ - -#define IS_BREAK_AT(parser,offset) \ - (CHECK_AT(parser,'\r',(offset)) /* CR (#xD)*/ \ - || CHECK_AT(parser,'\n',(offset)) /* LF (#xA) */ \ - || (CHECK_AT(parser,'\xC2',(offset)) \ - && CHECK_AT(parser,'\x85',(offset)+1)) /* NEL (#x85) */ \ - || (CHECK_AT(parser,'\xE2',(offset)) \ - && CHECK_AT(parser,'\x80',(offset)+1) \ - && CHECK_AT(parser,'\xA8',(offset)+2)) /* LS (#x2028) */ \ - || (CHECK_AT(parser,'\xE2',(offset)) \ - && CHECK_AT(parser,'\x80',(offset)+1) \ - && CHECK_AT(parser,'\xA9',(offset)+2))) /* PS (#x2029) */ - -#define IS_BREAK(parser) IS_BREAK_AT(parser,0) - -#define IS_CRLF_AT(parser,offset) \ - (CHECK_AT(parser,'\r',(offset)) && CHECK_AT(parser,'\n',(offset)+1)) - -#define IS_CRLF(parser) IS_CRLF_AT(parser,0) - -/* - * Check if the character is a line break or NUL. - */ - -#define IS_BREAKZ_AT(parser,offset) \ - (IS_BREAK_AT(parser,(offset)) || IS_Z_AT(parser,(offset))) - -#define IS_BREAKZ(parser) IS_BREAKZ_AT(parser,0) - -/* - * Check if the character is a line break, space, or NUL. - */ - -#define IS_SPACEZ_AT(parser,offset) \ - (IS_SPACE_AT(parser,(offset)) || IS_BREAKZ_AT(parser,(offset))) - -#define IS_SPACEZ(parser) IS_SPACEZ_AT(parser,0) - -/* - * Check if the character is a line break, space, tab, or NUL. - */ - -#define IS_BLANKZ_AT(parser,offset) \ - (IS_BLANK_AT(parser,(offset)) || IS_BREAKZ_AT(parser,(offset))) - -#define IS_BLANKZ(parser) IS_BLANKZ_AT(parser,0) - -/* - * Determine the width of the character. - */ - -#define WIDTH_AT(parser,offset) \ - ((parser->pointer[(offset)] & 0x80) == 0x00 ? 1 : \ - (parser->pointer[(offset)] & 0xE0) == 0xC0 ? 2 : \ - (parser->pointer[(offset)] & 0xF0) == 0xE0 ? 3 : \ - (parser->pointer[(offset)] & 0xF8) == 0xF0 ? 4 : 0) - -#define WIDTH(parser) WIDTH_AT(parser,0) - /* * Advance the buffer pointer. */ -#define FORWARD(parser) \ - (parser->index ++, \ - parser->column ++, \ - parser->unread --, \ - parser->pointer += WIDTH(parser)) - -#define FORWARD_LINE(parser) \ - (IS_CRLF(parser) ? \ - (parser->index += 2, \ - parser->column = 0, \ - parser->line ++, \ - parser->unread -= 2, \ - parser->pointer += 2) : \ - IS_BREAK(parser) ? \ - (parser->index ++, \ - parser->column = 0, \ - parser->line ++, \ - parser->unread --, \ - parser->pointer += WIDTH(parser)) : 0) - -/* - * Resize a string if needed. - */ +#define SKIP(parser) \ + (parser->mark.index ++, \ + parser->mark.column ++, \ + parser->unread --, \ + parser->buffer.pointer += WIDTH(parser->buffer)) -#define RESIZE(parser,string) \ - ((string).pointer-(string).buffer+5 < (string).size ? 1 : \ - yaml_parser_resize_string(parser, &(string))) +#define SKIP_LINE(parser) \ + (IS_CRLF(parser->buffer) ? \ + (parser->mark.index += 2, \ + parser->mark.column = 0, \ + parser->mark.line ++, \ + parser->unread -= 2, \ + parser->buffer.pointer += 2) : \ + IS_BREAK(parser->buffer) ? \ + (parser->mark.index ++, \ + parser->mark.column = 0, \ + parser->mark.line ++, \ + parser->unread --, \ + parser->buffer.pointer += WIDTH(parser->buffer)) : 0) /* * Copy a character to a string buffer and advance pointers. */ -#define COPY(parser,string) \ - (((*parser->pointer & 0x80) == 0x00 ? \ - (*((string).pointer++) = *(parser->pointer++)) : \ - (*parser->pointer & 0xE0) == 0xC0 ? \ - (*((string).pointer++) = *(parser->pointer++), \ - *((string).pointer++) = *(parser->pointer++)) : \ - (*parser->pointer & 0xF0) == 0xE0 ? \ - (*((string).pointer++) = *(parser->pointer++), \ - *((string).pointer++) = *(parser->pointer++), \ - *((string).pointer++) = *(parser->pointer++)) : \ - (*parser->pointer & 0xF8) == 0xF0 ? \ - (*((string).pointer++) = *(parser->pointer++), \ - *((string).pointer++) = *(parser->pointer++), \ - *((string).pointer++) = *(parser->pointer++), \ - *((string).pointer++) = *(parser->pointer++)) : 0), \ - parser->index ++, \ - parser->column ++, \ - parser->unread --) +#define READ(parser,string) \ + (STRING_EXTEND(parser,string) ? \ + (COPY(string,parser->buffer), \ + parser->mark.index ++, \ + parser->mark.column ++, \ + parser->unread --, \ + 1) : 0) /* * Copy a line break character to a string buffer and advance pointers. */ -#define COPY_LINE(parser,string) \ - ((CHECK_AT(parser,'\r',0) && CHECK_AT(parser,'\n',1)) ? /* CR LF -> LF */ \ +#define READ_LINE(parser,string) \ + (STRING_EXTEND(parser,string) ? \ + (((CHECK_AT(parser->buffer,'\r',0) \ + && CHECK_AT(parser->buffer,'\n',1)) ? /* CR LF -> LF */ \ (*((string).pointer++) = (yaml_char_t) '\n', \ - parser->pointer += 2, \ - parser->index += 2, \ - parser->column = 0, \ - parser->line ++, \ + parser->buffer.pointer += 2, \ + parser->mark.index += 2, \ + parser->mark.column = 0, \ + parser->mark.line ++, \ parser->unread -= 2) : \ - (CHECK_AT(parser,'\r',0) || CHECK_AT(parser,'\n',0)) ? /* CR|LF -> LF */ \ + (CHECK_AT(parser->buffer,'\r',0) \ + || CHECK_AT(parser->buffer,'\n',0)) ? /* CR|LF -> LF */ \ (*((string).pointer++) = (yaml_char_t) '\n', \ - parser->pointer ++, \ - parser->index ++, \ - parser->column = 0, \ - parser->line ++, \ + parser->buffer.pointer ++, \ + parser->mark.index ++, \ + parser->mark.column = 0, \ + parser->mark.line ++, \ parser->unread --) : \ - (CHECK_AT(parser,'\xC2',0) && CHECK_AT(parser,'\x85',1)) ? /* NEL -> LF */ \ + (CHECK_AT(parser->buffer,'\xC2',0) \ + && CHECK_AT(parser->buffer,'\x85',1)) ? /* NEL -> LF */ \ (*((string).pointer++) = (yaml_char_t) '\n', \ - parser->pointer += 2, \ - parser->index ++, \ - parser->column = 0, \ - parser->line ++, \ + parser->buffer.pointer += 2, \ + parser->mark.index ++, \ + parser->mark.column = 0, \ + parser->mark.line ++, \ parser->unread --) : \ - (CHECK_AT(parser,'\xE2',0) && \ - CHECK_AT(parser,'\x80',1) && \ - (CHECK_AT(parser,'\xA8',2) || \ - CHECK_AT(parser,'\xA9',2))) ? /* LS|PS -> LS|PS */ \ - (*((string).pointer++) = *(parser->pointer++), \ - *((string).pointer++) = *(parser->pointer++), \ - *((string).pointer++) = *(parser->pointer++), \ - parser->index ++, \ - parser->column = 0, \ - parser->line ++, \ - parser->unread --) : 0) - -/* - * Append a string to another string and clear the former string. - */ - -#define JOIN(parser,head_string,tail_string) \ - (yaml_parser_join_string(parser, &(head_string), &(tail_string)) && \ - yaml_parser_clear_string(parser, &(tail_string))) + (CHECK_AT(parser->buffer,'\xE2',0) && \ + CHECK_AT(parser->buffer,'\x80',1) && \ + (CHECK_AT(parser->buffer,'\xA8',2) || \ + CHECK_AT(parser->buffer,'\xA9',2))) ? /* LS|PS -> LS|PS */ \ + (*((string).pointer++) = *(parser->buffer.pointer++), \ + *((string).pointer++) = *(parser->buffer.pointer++), \ + *((string).pointer++) = *(parser->buffer.pointer++), \ + parser->mark.index ++, \ + parser->mark.column = 0, \ + parser->mark.line ++, \ + parser->unread --) : 0), \ + 1) : 0) /* * Public API declarations. */ -YAML_DECLARE(yaml_token_t *) -yaml_parser_get_token(yaml_parser_t *parser); - -YAML_DECLARE(yaml_token_t *) -yaml_parser_peek_token(yaml_parser_t *parser); +YAML_DECLARE(int) +yaml_parser_scan(yaml_parser_t *parser, yaml_token_t *token); /* * Error handling. @@ -796,41 +581,11 @@ static int yaml_parser_set_scanner_error(yaml_parser_t *parser, const char *context, yaml_mark_t context_mark, const char *problem); -static yaml_mark_t -yaml_parser_get_mark(yaml_parser_t *parser); - -/* - * Buffers and lists. - */ - -typedef struct { - yaml_char_t *buffer; - yaml_char_t *pointer; - size_t size; -} yaml_string_t; - -static yaml_string_t -yaml_parser_new_string(yaml_parser_t *parser); - -static int -yaml_parser_resize_string(yaml_parser_t *parser, yaml_string_t *string); - -static int -yaml_parser_join_string(yaml_parser_t *parser, - yaml_string_t *string1, yaml_string_t *string2); - -static int -yaml_parser_clear_string(yaml_parser_t *parser, yaml_string_t *string); - -static int -yaml_parser_resize_list(yaml_parser_t *parser, void **buffer, size_t *size, - size_t item_size); - /* * High-level token API. */ -static int +YAML_DECLARE(int) yaml_parser_fetch_more_tokens(yaml_parser_t *parser); static int @@ -855,17 +610,6 @@ yaml_parser_increase_flow_level(yaml_parser_t *parser); static int yaml_parser_decrease_flow_level(yaml_parser_t *parser); -/* - * Token manipulation. - */ - -static int -yaml_parser_append_token(yaml_parser_t *parser, yaml_token_t *token); - -static int -yaml_parser_insert_token(yaml_parser_t *parser, - int number, yaml_token_t *token); - /* * Indentation treatment. */ @@ -936,8 +680,8 @@ yaml_parser_fetch_plain_scalar(yaml_parser_t *parser); static int yaml_parser_scan_to_next_token(yaml_parser_t *parser); -static yaml_token_t * -yaml_parser_scan_directive(yaml_parser_t *parser); +static int +yaml_parser_scan_directive(yaml_parser_t *parser, yaml_token_t *token); static int yaml_parser_scan_directive_name(yaml_parser_t *parser, @@ -955,12 +699,12 @@ static int yaml_parser_scan_tag_directive_value(yaml_parser_t *parser, yaml_mark_t mark, yaml_char_t **handle, yaml_char_t **prefix); -static yaml_token_t * -yaml_parser_scan_anchor(yaml_parser_t *parser, +static int +yaml_parser_scan_anchor(yaml_parser_t *parser, yaml_token_t *token, yaml_token_type_t type); -static yaml_token_t * -yaml_parser_scan_tag(yaml_parser_t *parser); +static int +yaml_parser_scan_tag(yaml_parser_t *parser, yaml_token_t *token); static int yaml_parser_scan_tag_handle(yaml_parser_t *parser, int directive, @@ -974,175 +718,59 @@ static int yaml_parser_scan_uri_escapes(yaml_parser_t *parser, int directive, yaml_mark_t start_mark, yaml_string_t *string); -static yaml_token_t * -yaml_parser_scan_block_scalar(yaml_parser_t *parser, int literal); +static int +yaml_parser_scan_block_scalar(yaml_parser_t *parser, yaml_token_t *token, + int literal); static int yaml_parser_scan_block_scalar_breaks(yaml_parser_t *parser, int *indent, yaml_string_t *breaks, yaml_mark_t start_mark, yaml_mark_t *end_mark); -static yaml_token_t * -yaml_parser_scan_flow_scalar(yaml_parser_t *parser, int single); - -static yaml_token_t * -yaml_parser_scan_plain_scalar(yaml_parser_t *parser); - -/* - * Get the next token and remove it from the tokens queue. - */ - -YAML_DECLARE(yaml_token_t *) -yaml_parser_get_token(yaml_parser_t *parser) -{ - yaml_token_t *token; - - assert(parser); /* Non-NULL parser object is expected. */ - assert(!parser->stream_end_produced); /* No tokens after STREAM-END. */ - - /* Ensure that the tokens queue contains enough tokens. */ - - if (!yaml_parser_fetch_more_tokens(parser)) return NULL; - - /* Fetch the next token from the queue. */ - - token = parser->tokens[parser->tokens_head]; - - /* Move the queue head. */ - - parser->tokens[parser->tokens_head++] = NULL; - if (parser->tokens_head == parser->tokens_size) - parser->tokens_head = 0; - - parser->tokens_parsed++; +static int +yaml_parser_scan_flow_scalar(yaml_parser_t *parser, yaml_token_t *token, + int single); - return token; -} +static int +yaml_parser_scan_plain_scalar(yaml_parser_t *parser, yaml_token_t *token); /* - * Get the next token, but don't remove it from the queue. + * Get the next token. */ -YAML_DECLARE(yaml_token_t *) -yaml_parser_peek_token(yaml_parser_t *parser) +YAML_DECLARE(int) +yaml_parser_scan(yaml_parser_t *parser, yaml_token_t *token) { assert(parser); /* Non-NULL parser object is expected. */ - assert(!parser->stream_end_produced); /* No tokens after STREAM-END. */ - - /* Ensure that the tokens queue contains enough tokens. */ - - if (!yaml_parser_fetch_more_tokens(parser)) return NULL; - - /* Fetch the next token from the queue. */ - - return parser->tokens[parser->tokens_head]; -} - -/* - * Create a new string. - */ - -static yaml_string_t -yaml_parser_new_string(yaml_parser_t *parser) -{ - yaml_string_t string = { NULL, NULL, 0 }; - - string.buffer = yaml_malloc(YAML_DEFAULT_SIZE); - if (!string.buffer) { - parser->error = YAML_MEMORY_ERROR; - return string; - } + assert(token); /* Non-NULL token object is expected. */ - memset(string.buffer, 0, YAML_DEFAULT_SIZE); - string.pointer = string.buffer; - string.size = YAML_DEFAULT_SIZE; + /* Erase the token object. */ - return string; -} + memset(token, 0, sizeof(yaml_token_t)); -/* - * Double the size of a string. - */ + /* No tokens after STREAM-END or error. */ -static int -yaml_parser_resize_string(yaml_parser_t *parser, yaml_string_t *string) -{ - yaml_char_t *new_buffer = yaml_realloc(string->buffer, string->size*2); - - if (!new_buffer) { - yaml_free(string->buffer); - string->buffer = NULL; - string->pointer = NULL; - string->size = 0; - parser->error = YAML_MEMORY_ERROR; - return 0; + if (parser->stream_end_produced || parser->error) { + return 1; } - memset(new_buffer+string->size, 0, string->size); - - string->pointer = new_buffer + (string->buffer-string->pointer); - string->buffer = new_buffer; - string->size *= 2; - - return 1; -} - -/* - * Append a string to another string. - */ - -static int -yaml_parser_join_string(yaml_parser_t *parser, - yaml_string_t *string1, yaml_string_t *string2) -{ - if (string2->buffer == string2->pointer) return 1; + /* Ensure that the tokens queue contains enough tokens. */ - while (string1->pointer - string1->buffer + string2->pointer - string2->buffer + 1 - > string1->size) { - if (!yaml_parser_resize_string(parser, string1)) return 0; + if (!parser->token_available) { + if (!yaml_parser_fetch_more_tokens(parser)) + return 0; } - memcpy(string1->pointer, string2->buffer, string2->pointer-string2->buffer); - - return 1; -} - -/* - * Fill the string with NULs and move the pointer to the beginning. - */ - -static int -yaml_parser_clear_string(yaml_parser_t *parser, yaml_string_t *string) -{ - if (string->buffer == string->pointer) return 1; - - memset(string->buffer, 0, string->pointer-string->buffer); - - string->pointer = string->buffer; - - return 1; -} - -/* - * Double a list. - */ - -static int -yaml_parser_resize_list(yaml_parser_t *parser, void **buffer, size_t *size, - size_t item_size) -{ - void *new_buffer = yaml_realloc(*buffer, item_size*(*size)*2); + /* Fetch the next token from the queue. */ + + *token = DEQUEUE(parser, parser->tokens); + parser->token_available = 0; + parser->tokens_parsed ++; - if (!new_buffer) { - parser->error = YAML_MEMORY_ERROR; - return 0; + if (token->type == YAML_STREAM_END_TOKEN) { + parser->stream_end_produced = 1; } - memset(new_buffer+(*size), 0, item_size*(*size)); - - *buffer = new_buffer; - *size *= 2; - return 1; } @@ -1158,32 +786,20 @@ yaml_parser_set_scanner_error(yaml_parser_t *parser, const char *context, parser->context = context; parser->context_mark = context_mark; parser->problem = problem; - parser->problem_mark = yaml_parser_get_mark(parser); -} - -/* - * Get the mark for the current buffer position. - */ - -static yaml_mark_t -yaml_parser_get_mark(yaml_parser_t *parser) -{ - yaml_mark_t mark = { parser->index, parser->line, parser->column }; + parser->problem_mark = parser->mark; - return mark; + return 0; } - /* * Ensure that the tokens queue contains at least one token which can be * returned to the Parser. */ -static int +YAML_DECLARE(int) yaml_parser_fetch_more_tokens(yaml_parser_t *parser) { int need_more_tokens; - int k; /* While we need more tokens to fetch, do it. */ @@ -1195,7 +811,7 @@ yaml_parser_fetch_more_tokens(yaml_parser_t *parser) need_more_tokens = 0; - if (parser->tokens_head == parser->tokens_tail) + if (parser->tokens.head == parser->tokens.tail) { /* Queue is empty. */ @@ -1203,12 +819,17 @@ yaml_parser_fetch_more_tokens(yaml_parser_t *parser) } else { + yaml_simple_key_t *simple_key; + /* Check if any potential simple key may occupy the head position. */ - for (k = 0; k <= parser->flow_level; k++) { - yaml_simple_key_t *simple_key = parser->simple_keys[k]; - if (simple_key - && (simple_key->token_number == parser->tokens_parsed)) { + if (!yaml_parser_stale_simple_keys(parser)) + return 0; + + for (simple_key = parser->simple_keys.start; + simple_key != parser->simple_keys.top; simple_key++) { + if (simple_key->possible + && simple_key->token_number == parser->tokens_parsed) { need_more_tokens = 1; break; } @@ -1226,6 +847,8 @@ yaml_parser_fetch_more_tokens(yaml_parser_t *parser) return 0; } + parser->token_available = 1; + return 1; } @@ -1238,7 +861,7 @@ yaml_parser_fetch_next_token(yaml_parser_t *parser) { /* Ensure that the buffer is initialized. */ - if (!UPDATE(parser, 1)) + if (!CACHE(parser, 1)) return 0; /* Check if we just started scanning. Fetch STREAM-START then. */ @@ -1251,9 +874,14 @@ yaml_parser_fetch_next_token(yaml_parser_t *parser) if (!yaml_parser_scan_to_next_token(parser)) return 0; + /* Remove obsolete potential simple keys. */ + + if (!yaml_parser_stale_simple_keys(parser)) + return 0; + /* Check the indentation level against the current column. */ - if (!yaml_parser_unroll_indent(parser, parser->column)) + if (!yaml_parser_unroll_indent(parser, parser->mark.column)) return 0; /* @@ -1261,116 +889,118 @@ yaml_parser_fetch_next_token(yaml_parser_t *parser) * of the longest indicators ('--- ' and '... '). */ - if (!UPDATE(parser, 4)) + if (!CACHE(parser, 4)) return 0; /* Is it the end of the stream? */ - if (IS_Z(parser)) + if (IS_Z(parser->buffer)) return yaml_parser_fetch_stream_end(parser); /* Is it a directive? */ - if (parser->column == 0 && CHECK(parser, '%')) + if (parser->mark.column == 0 && CHECK(parser->buffer, '%')) return yaml_parser_fetch_directive(parser); /* Is it the document start indicator? */ - if (parser->column == 0 - && CHECK_AT(parser, '-', 0) - && CHECK_AT(parser, '-', 1) - && CHECK_AT(parser, '-', 2) - && IS_BLANKZ_AT(parser, 3)) + if (parser->mark.column == 0 + && CHECK_AT(parser->buffer, '-', 0) + && CHECK_AT(parser->buffer, '-', 1) + && CHECK_AT(parser->buffer, '-', 2) + && IS_BLANKZ_AT(parser->buffer, 3)) return yaml_parser_fetch_document_indicator(parser, YAML_DOCUMENT_START_TOKEN); /* Is it the document end indicator? */ - if (parser->column == 0 - && CHECK_AT(parser, '.', 0) - && CHECK_AT(parser, '.', 1) - && CHECK_AT(parser, '.', 2) - && IS_BLANKZ_AT(parser, 3)) + if (parser->mark.column == 0 + && CHECK_AT(parser->buffer, '.', 0) + && CHECK_AT(parser->buffer, '.', 1) + && CHECK_AT(parser->buffer, '.', 2) + && IS_BLANKZ_AT(parser->buffer, 3)) return yaml_parser_fetch_document_indicator(parser, YAML_DOCUMENT_END_TOKEN); /* Is it the flow sequence start indicator? */ - if (CHECK(parser, '[')) + if (CHECK(parser->buffer, '[')) return yaml_parser_fetch_flow_collection_start(parser, YAML_FLOW_SEQUENCE_START_TOKEN); /* Is it the flow mapping start indicator? */ - if (CHECK(parser, '{')) + if (CHECK(parser->buffer, '{')) return yaml_parser_fetch_flow_collection_start(parser, YAML_FLOW_MAPPING_START_TOKEN); /* Is it the flow sequence end indicator? */ - if (CHECK(parser, ']')) + if (CHECK(parser->buffer, ']')) return yaml_parser_fetch_flow_collection_end(parser, YAML_FLOW_SEQUENCE_END_TOKEN); /* Is it the flow mapping end indicator? */ - if (CHECK(parser, '}')) + if (CHECK(parser->buffer, '}')) return yaml_parser_fetch_flow_collection_end(parser, YAML_FLOW_MAPPING_END_TOKEN); /* Is it the flow entry indicator? */ - if (CHECK(parser, ',')) + if (CHECK(parser->buffer, ',')) return yaml_parser_fetch_flow_entry(parser); /* Is it the block entry indicator? */ - if (CHECK(parser, '-') && IS_BLANKZ_AT(parser, 1)) + if (CHECK(parser->buffer, '-') && IS_BLANKZ_AT(parser->buffer, 1)) return yaml_parser_fetch_block_entry(parser); /* Is it the key indicator? */ - if (CHECK(parser, '?') && (!parser->flow_level || IS_BLANKZ_AT(parser, 1))) + if (CHECK(parser->buffer, '?') + && (parser->flow_level || IS_BLANKZ_AT(parser->buffer, 1))) return yaml_parser_fetch_key(parser); /* Is it the value indicator? */ - if (CHECK(parser, ':') && (!parser->flow_level || IS_BLANKZ_AT(parser, 1))) + if (CHECK(parser->buffer, ':') + && (parser->flow_level || IS_BLANKZ_AT(parser->buffer, 1))) return yaml_parser_fetch_value(parser); /* Is it an alias? */ - if (CHECK(parser, '*')) + if (CHECK(parser->buffer, '*')) return yaml_parser_fetch_anchor(parser, YAML_ALIAS_TOKEN); /* Is it an anchor? */ - if (CHECK(parser, '&')) + if (CHECK(parser->buffer, '&')) return yaml_parser_fetch_anchor(parser, YAML_ANCHOR_TOKEN); /* Is it a tag? */ - if (CHECK(parser, '!')) + if (CHECK(parser->buffer, '!')) return yaml_parser_fetch_tag(parser); /* Is it a literal scalar? */ - if (CHECK(parser, '|') && !parser->flow_level) + if (CHECK(parser->buffer, '|') && !parser->flow_level) return yaml_parser_fetch_block_scalar(parser, 1); /* Is it a folded scalar? */ - if (CHECK(parser, '>') && !parser->flow_level) + if (CHECK(parser->buffer, '>') && !parser->flow_level) return yaml_parser_fetch_block_scalar(parser, 0); /* Is it a single-quoted scalar? */ - if (CHECK(parser, '\'')) + if (CHECK(parser->buffer, '\'')) return yaml_parser_fetch_flow_scalar(parser, 1); /* Is it a double-quoted scalar? */ - if (CHECK(parser, '"')) + if (CHECK(parser->buffer, '"')) return yaml_parser_fetch_flow_scalar(parser, 0); /* @@ -1382,7 +1012,8 @@ yaml_parser_fetch_next_token(yaml_parser_t *parser) * '#', '&', '*', '!', '|', '>', '\'', '\"', * '%', '@', '`'. * - * In the block context, it may also start with the characters + * In the block context (and, for the '-' indicator, in the flow context + * too), it may also start with the characters * * '-', '?', ':' * @@ -1391,24 +1022,29 @@ yaml_parser_fetch_next_token(yaml_parser_t *parser) * The last rule is more restrictive than the specification requires. */ - if (!(IS_BLANKZ(parser) || CHECK(parser, '-') || CHECK(parser, '?') - || CHECK(parser, ':') || CHECK(parser, ',') || CHECK(parser, '[') - || CHECK(parser, ']') || CHECK(parser, '{') || CHECK(parser, '}') - || CHECK(parser, '#') || CHECK(parser, '&') || CHECK(parser, '*') - || CHECK(parser, '!') || CHECK(parser, '|') || CHECK(parser, '>') - || CHECK(parser, '\'') || CHECK(parser, '"') || CHECK(parser, '%') - || CHECK(parser, '@') || CHECK(parser, '`')) || + if (!(IS_BLANKZ(parser->buffer) || CHECK(parser->buffer, '-') + || CHECK(parser->buffer, '?') || CHECK(parser->buffer, ':') + || CHECK(parser->buffer, ',') || CHECK(parser->buffer, '[') + || CHECK(parser->buffer, ']') || CHECK(parser->buffer, '{') + || CHECK(parser->buffer, '}') || CHECK(parser->buffer, '#') + || CHECK(parser->buffer, '&') || CHECK(parser->buffer, '*') + || CHECK(parser->buffer, '!') || CHECK(parser->buffer, '|') + || CHECK(parser->buffer, '>') || CHECK(parser->buffer, '\'') + || CHECK(parser->buffer, '"') || CHECK(parser->buffer, '%') + || CHECK(parser->buffer, '@') || CHECK(parser->buffer, '`')) || + (CHECK(parser->buffer, '-') && !IS_BLANK_AT(parser->buffer, 1)) || (!parser->flow_level && - (CHECK(parser, '-') || CHECK(parser, '?') || CHECK(parser, ':')) && - IS_BLANKZ_AT(parser, 1))) + (CHECK(parser->buffer, '?') || CHECK(parser->buffer, ':')) + && !IS_BLANKZ_AT(parser->buffer, 1))) return yaml_parser_fetch_plain_scalar(parser); /* * If we don't determine the token type so far, it is an error. */ - return yaml_parser_set_scanner_error(parser, "while scanning for the next token", - yaml_parser_get_mark(parser), "found character that cannot start any token"); + return yaml_parser_set_scanner_error(parser, + "while scanning for the next token", parser->mark, + "found character that cannot start any token"); } /* @@ -1419,14 +1055,13 @@ yaml_parser_fetch_next_token(yaml_parser_t *parser) static int yaml_parser_stale_simple_keys(yaml_parser_t *parser) { - int level; + yaml_simple_key_t *simple_key; /* Check for a potential simple key for each flow level. */ - for (level = 0; level <= parser->flow_level; level++) + for (simple_key = parser->simple_keys.start; + simple_key != parser->simple_keys.top; simple_key ++) { - yaml_simple_key_t *simple_key = parser->simple_keys[level]; - /* * The specification requires that a simple key * @@ -1434,19 +1069,19 @@ yaml_parser_stale_simple_keys(yaml_parser_t *parser) * - is shorter than 1024 characters. */ - if (simple_key && (simple_key->line < parser->line || - simple_key->index < parser->index+1024)) { + if (simple_key->possible + && (simple_key->mark.line < parser->mark.line + || simple_key->mark.index+1024 < parser->mark.index)) { /* Check if the potential simple key to be removed is required. */ if (simple_key->required) { return yaml_parser_set_scanner_error(parser, "while scanning a simple key", simple_key->mark, - "could not found expected ':'"); + "could not find expected ':'"); } - yaml_free(simple_key); - parser->simple_keys[level] = NULL; + simple_key->possible = 0; } } @@ -1467,7 +1102,8 @@ yaml_parser_save_simple_key(yaml_parser_t *parser) * level. */ - int required = (!parser->flow_level && parser->indent == parser->column); + int required = (!parser->flow_level + && parser->indent == (int)parser->mark.column); /* * A simple key is required only when it is the first token in the current @@ -1482,21 +1118,16 @@ yaml_parser_save_simple_key(yaml_parser_t *parser) if (parser->simple_key_allowed) { - yaml_simple_key_t simple_key = { required, - parser->tokens_parsed + parser->tokens_tail - parser->tokens_head, - parser->index, parser->line, parser->column, - yaml_parser_get_mark(parser) }; + yaml_simple_key_t simple_key; + simple_key.possible = 1; + simple_key.required = required; + simple_key.token_number = + parser->tokens_parsed + parser->tokens.tail - parser->tokens.head; + simple_key.mark = parser->mark; if (!yaml_parser_remove_simple_key(parser)) return 0; - parser->simple_keys[parser->flow_level] = - yaml_malloc(sizeof(yaml_simple_key_t)); - if (!parser->simple_keys[parser->flow_level]) { - parser->error = YAML_MEMORY_ERROR; - return 0; - } - - *(parser->simple_keys[parser->flow_level]) = simple_key; + *(parser->simple_keys.top-1) = simple_key; } return 1; @@ -1509,23 +1140,22 @@ yaml_parser_save_simple_key(yaml_parser_t *parser) static int yaml_parser_remove_simple_key(yaml_parser_t *parser) { - yaml_simple_key_t *simple_key = parser->simple_keys[parser->flow_level]; + yaml_simple_key_t *simple_key = parser->simple_keys.top-1; - if (simple_key) + if (simple_key->possible) { /* If the key is required, it is an error. */ if (simple_key->required) { return yaml_parser_set_scanner_error(parser, "while scanning a simple key", simple_key->mark, - "could not found expected ':'"); + "could not find expected ':'"); } + } - /* Remove the key from the list. */ + /* Remove the key from the stack. */ - yaml_free(simple_key); - parser->simple_keys[parser->flow_level] = NULL; - } + simple_key->possible = 0; return 1; } @@ -1537,17 +1167,16 @@ yaml_parser_remove_simple_key(yaml_parser_t *parser) static int yaml_parser_increase_flow_level(yaml_parser_t *parser) { - /* Check if we need to resize the list. */ + yaml_simple_key_t empty_simple_key = { 0, 0, 0, { 0, 0, 0 } }; - if (parser->flow_level == parser->simple_keys_size-1) { - if (!yaml_parser_resize_list(parser, (void **)&parser->simple_keys, - &parser->simple_keys_size, sizeof(yaml_simple_key_t *))) - return 0; - } + /* Reset the simple key on the next level. */ - /* Increase the flow level and reset the simple key. */ + if (!PUSH(parser, parser->simple_keys, empty_simple_key)) + return 0; + + /* Increase the flow level. */ - parser->simple_keys[++parser->flow_level] = NULL; + parser->flow_level++; return 1; } @@ -1559,75 +1188,13 @@ yaml_parser_increase_flow_level(yaml_parser_t *parser) static int yaml_parser_decrease_flow_level(yaml_parser_t *parser) { - assert(parser->flow_level); /* Greater than 0. */ - assert(!parser->simple_keys[parser->flow_level]); /* Must be removed. */ + yaml_simple_key_t dummy_key; /* Used to eliminate a compiler warning. */ - parser->flow_level --; - - return 1; -} - -/* - * Add a token to the tail of the tokens queue. - */ - -static int -yaml_parser_append_token(yaml_parser_t *parser, yaml_token_t *token) -{ - return yaml_parser_insert_token(parser, -1, token); -} - -/* - * Insert the token into the tokens queue. The number parameter is the - * ordinal number of the token. If the number is equal to -1, add the token - * to the tail of the queue. - */ - -static int -yaml_parser_insert_token(yaml_parser_t *parser, - int number, yaml_token_t *token) -{ - /* The index of the token in the queue. */ - - int index = (number == -1) - ? parser->tokens_tail - parser->tokens_head - : number - parser->tokens_parsed; - - assert(index >= 0 && index <= (parser->tokens_tail-parser->tokens_head)); - - /* Check if we need to resize the queue. */ - - if (parser->tokens_head == 0 && parser->tokens_tail == parser->tokens_size) { - if (!yaml_parser_resize_list(parser, (void **)&parser->tokens, - &parser->tokens_size, sizeof(yaml_token_t *))) - return 0; - } - - /* Check if we need to move the queue to the beginning of the buffer. */ - - if (parser->tokens_tail == parser->tokens_size) - { - if (parser->tokens_head < parser->tokens_tail) { - memmove(parser->tokens, parser->tokens+parser->tokens_head, - sizeof(yaml_token_t *)*(parser->tokens_tail-parser->tokens_head)); - } - parser->tokens_tail -= parser->tokens_head; - parser->tokens_head = 0; - } - - /* Check if we need to free space within the queue. */ - - if (index < (parser->tokens_tail-parser->tokens_head)) { - memmove(parser->tokens+parser->tokens_head+index+1, - parser->tokens+parser->tokens_head+index, - sizeof(yaml_token_t *)*(parser->tokens_tail-parser->tokens_head-index)); + if (parser->flow_level) { + parser->flow_level --; + dummy_key = POP(parser, parser->simple_keys); } - /* Insert the token. */ - - parser->tokens[parser->tokens_head+index] = token; - parser->tokens_tail ++; - return 1; } @@ -1642,7 +1209,7 @@ static int yaml_parser_roll_indent(yaml_parser_t *parser, int column, int number, yaml_token_type_t type, yaml_mark_t mark) { - yaml_token_t *token; + yaml_token_t token; /* In the flow context, do nothing. */ @@ -1651,35 +1218,28 @@ yaml_parser_roll_indent(yaml_parser_t *parser, int column, if (parser->indent < column) { - /* Check if we need to expand the indents stack. */ - - if (parser->indents_length == parser->indents_size) { - if (!yaml_parser_resize_list(parser, (void **)&parser->indents, - &parser->indents_size, sizeof(int))) - return 0; - } - /* * Push the current indentation level to the stack and set the new * indentation level. */ - parser->indents[parser->indents_length++] = parser->indent; + if (!PUSH(parser, parser->indents, parser->indent)) + return 0; + parser->indent = column; - /* Create a token. */ + /* Create a token and insert it into the queue. */ - token = yaml_token_new(type, mark, mark); - if (!token) { - parser->error = YAML_MEMORY_ERROR; - return 0; - } - - /* Insert the token into the queue. */ + TOKEN_INIT(token, type, mark, mark); - if (!yaml_parser_insert_token(parser, number, token)) { - yaml_token_delete(token); - return 0; + if (number == -1) { + if (!ENQUEUE(parser, parser->tokens, token)) + return 0; + } + else { + if (!QUEUE_INSERT(parser, + parser->tokens, number - parser->tokens_parsed, token)) + return 0; } } @@ -1696,7 +1256,7 @@ yaml_parser_roll_indent(yaml_parser_t *parser, int column, static int yaml_parser_unroll_indent(yaml_parser_t *parser, int column) { - yaml_token_t *token; + yaml_token_t token; /* In the flow context, do nothing. */ @@ -1707,28 +1267,16 @@ yaml_parser_unroll_indent(yaml_parser_t *parser, int column) while (parser->indent > column) { - yaml_mark_t mark = yaml_parser_get_mark(parser); + /* Create a token and append it to the queue. */ - /* Create a token. */ + TOKEN_INIT(token, YAML_BLOCK_END_TOKEN, parser->mark, parser->mark); - token = yaml_token_new(YAML_BLOCK_END_TOKEN, mark, mark); - if (!token) { - parser->error = YAML_MEMORY_ERROR; + if (!ENQUEUE(parser, parser->tokens, token)) return 0; - } - - /* Append the token to the queue. */ - - if (!yaml_parser_append_token(parser, token)) { - yaml_token_delete(token); - return 0; - } /* Pop the indentation level. */ - assert(parser->indents_length); /* Non-empty stack expected. */ - - parser->indent = parser->indents[--parser->indents_length]; + parser->indent = POP(parser, parser->indents); } return 1; @@ -1741,13 +1289,18 @@ yaml_parser_unroll_indent(yaml_parser_t *parser, int column) static int yaml_parser_fetch_stream_start(yaml_parser_t *parser) { - yaml_mark_t mark = yaml_parser_get_mark(parser); - yaml_token_t *token; + yaml_simple_key_t simple_key = { 0, 0, 0, { 0, 0, 0 } }; + yaml_token_t token; /* Set the initial indentation. */ parser->indent = -1; + /* Initialize the simple key stack. */ + + if (!PUSH(parser, parser->simple_keys, simple_key)) + return 0; + /* A simple key is allowed at the beginning of the stream. */ parser->simple_key_allowed = 1; @@ -1756,20 +1309,13 @@ yaml_parser_fetch_stream_start(yaml_parser_t *parser) parser->stream_start_produced = 1; - /* Create the STREAM-START token. */ + /* Create the STREAM-START token and append it to the queue. */ - token = yaml_stream_start_token_new(parser->encoding, mark, mark); - if (!token) { - parser->error = YAML_MEMORY_ERROR; - return 0; - } - - /* Append the token to the queue. */ + STREAM_START_TOKEN_INIT(token, parser->encoding, + parser->mark, parser->mark); - if (!yaml_parser_append_token(parser, token)) { - yaml_token_delete(token); + if (!ENQUEUE(parser, parser->tokens, token)) return 0; - } return 1; } @@ -1781,44 +1327,45 @@ yaml_parser_fetch_stream_start(yaml_parser_t *parser) static int yaml_parser_fetch_stream_end(yaml_parser_t *parser) { - yaml_mark_t mark = yaml_parser_get_mark(parser); - yaml_token_t *token; + yaml_token_t token; + + /* Force new line. */ + + if (parser->mark.column != 0) { + parser->mark.column = 0; + parser->mark.line ++; + } /* Reset the indentation level. */ if (!yaml_parser_unroll_indent(parser, -1)) return 0; - /* We have finished. */ + /* Reset simple keys. */ - parser->stream_end_produced = 1; + if (!yaml_parser_remove_simple_key(parser)) + return 0; - /* Create the STREAM-END token. */ + parser->simple_key_allowed = 0; - token = yaml_stream_end_token_new(mark, mark); - if (!token) { - parser->error = YAML_MEMORY_ERROR; - return 0; - } + /* Create the STREAM-END token and append it to the queue. */ - /* Append the token to the queue. */ + STREAM_END_TOKEN_INIT(token, parser->mark, parser->mark); - if (!yaml_parser_append_token(parser, token)) { - yaml_token_delete(token); + if (!ENQUEUE(parser, parser->tokens, token)) return 0; - } return 1; } /* - * Produce the YAML-DIRECTIVE or TAG-DIRECTIVE token. + * Produce a VERSION-DIRECTIVE or TAG-DIRECTIVE token. */ static int yaml_parser_fetch_directive(yaml_parser_t *parser) { - yaml_token_t *token; + yaml_token_t token; /* Reset the indentation level. */ @@ -1834,13 +1381,13 @@ yaml_parser_fetch_directive(yaml_parser_t *parser) /* Create the YAML-DIRECTIVE or TAG-DIRECTIVE token. */ - token = yaml_parser_scan_directive(parser); - if (!token) return 0; + if (!yaml_parser_scan_directive(parser, &token)) + return 0; /* Append the token to the queue. */ - if (!yaml_parser_append_token(parser, token)) { - yaml_token_delete(token); + if (!ENQUEUE(parser, parser->tokens, token)) { + yaml_token_delete(&token); return 0; } @@ -1856,7 +1403,7 @@ yaml_parser_fetch_document_indicator(yaml_parser_t *parser, yaml_token_type_t type) { yaml_mark_t start_mark, end_mark; - yaml_token_t *token; + yaml_token_t token; /* Reset the indentation level. */ @@ -1872,28 +1419,22 @@ yaml_parser_fetch_document_indicator(yaml_parser_t *parser, /* Consume the token. */ - start_mark = yaml_parser_get_mark(parser); + start_mark = parser->mark; - FORWARD(parser); - FORWARD(parser); - FORWARD(parser); + SKIP(parser); + SKIP(parser); + SKIP(parser); - end_mark = yaml_parser_get_mark(parser); + end_mark = parser->mark; /* Create the DOCUMENT-START or DOCUMENT-END token. */ - token = yaml_token_new(type, start_mark, end_mark); - if (!token) { - parser->error = YAML_MEMORY_ERROR; - return 0; - } + TOKEN_INIT(token, type, start_mark, end_mark); /* Append the token to the queue. */ - if (!yaml_parser_append_token(parser, token)) { - yaml_token_delete(token); + if (!ENQUEUE(parser, parser->tokens, token)) return 0; - } return 1; } @@ -1907,7 +1448,7 @@ yaml_parser_fetch_flow_collection_start(yaml_parser_t *parser, yaml_token_type_t type) { yaml_mark_t start_mark, end_mark; - yaml_token_t *token; + yaml_token_t token; /* The indicators '[' and '{' may start a simple key. */ @@ -1925,24 +1466,18 @@ yaml_parser_fetch_flow_collection_start(yaml_parser_t *parser, /* Consume the token. */ - start_mark = yaml_parser_get_mark(parser); - FORWARD(parser); - end_mark = yaml_parser_get_mark(parser); + start_mark = parser->mark; + SKIP(parser); + end_mark = parser->mark; /* Create the FLOW-SEQUENCE-START of FLOW-MAPPING-START token. */ - token = yaml_token_new(type, start_mark, end_mark); - if (!token) { - parser->error = YAML_MEMORY_ERROR; - return 0; - } + TOKEN_INIT(token, type, start_mark, end_mark); /* Append the token to the queue. */ - if (!yaml_parser_append_token(parser, token)) { - yaml_token_delete(token); + if (!ENQUEUE(parser, parser->tokens, token)) return 0; - } return 1; } @@ -1956,7 +1491,7 @@ yaml_parser_fetch_flow_collection_end(yaml_parser_t *parser, yaml_token_type_t type) { yaml_mark_t start_mark, end_mark; - yaml_token_t *token; + yaml_token_t token; /* Reset any potential simple key on the current flow level. */ @@ -1974,24 +1509,18 @@ yaml_parser_fetch_flow_collection_end(yaml_parser_t *parser, /* Consume the token. */ - start_mark = yaml_parser_get_mark(parser); - FORWARD(parser); - end_mark = yaml_parser_get_mark(parser); + start_mark = parser->mark; + SKIP(parser); + end_mark = parser->mark; /* Create the FLOW-SEQUENCE-END of FLOW-MAPPING-END token. */ - token = yaml_token_new(type, start_mark, end_mark); - if (!token) { - parser->error = YAML_MEMORY_ERROR; - return 0; - } + TOKEN_INIT(token, type, start_mark, end_mark); /* Append the token to the queue. */ - if (!yaml_parser_append_token(parser, token)) { - yaml_token_delete(token); + if (!ENQUEUE(parser, parser->tokens, token)) return 0; - } return 1; } @@ -2004,7 +1533,7 @@ static int yaml_parser_fetch_flow_entry(yaml_parser_t *parser) { yaml_mark_t start_mark, end_mark; - yaml_token_t *token; + yaml_token_t token; /* Reset any potential simple keys on the current flow level. */ @@ -2017,24 +1546,16 @@ yaml_parser_fetch_flow_entry(yaml_parser_t *parser) /* Consume the token. */ - start_mark = yaml_parser_get_mark(parser); - FORWARD(parser); - end_mark = yaml_parser_get_mark(parser); + start_mark = parser->mark; + SKIP(parser); + end_mark = parser->mark; - /* Create the FLOW-ENTRY token. */ + /* Create the FLOW-ENTRY token and append it to the queue. */ - token = yaml_token_new(YAML_FLOW_ENTRY_TOKEN, start_mark, end_mark); - if (!token) { - parser->error = YAML_MEMORY_ERROR; - return 0; - } - - /* Append the token to the queue. */ + TOKEN_INIT(token, YAML_FLOW_ENTRY_TOKEN, start_mark, end_mark); - if (!yaml_parser_append_token(parser, token)) { - yaml_token_delete(token); + if (!ENQUEUE(parser, parser->tokens, token)) return 0; - } return 1; } @@ -2047,7 +1568,7 @@ static int yaml_parser_fetch_block_entry(yaml_parser_t *parser) { yaml_mark_t start_mark, end_mark; - yaml_token_t *token; + yaml_token_t token; /* Check if the scanner is in the block context. */ @@ -2056,15 +1577,14 @@ yaml_parser_fetch_block_entry(yaml_parser_t *parser) /* Check if we are allowed to start a new entry. */ if (!parser->simple_key_allowed) { - return yaml_parser_set_scanner_error(parser, NULL, - yaml_parser_get_mark(parser), + return yaml_parser_set_scanner_error(parser, NULL, parser->mark, "block sequence entries are not allowed in this context"); } /* Add the BLOCK-SEQUENCE-START token if needed. */ - if (!yaml_parser_roll_indent(parser, parser->column, -1, - YAML_BLOCK_SEQUENCE_START_TOKEN, yaml_parser_get_mark(parser))) + if (!yaml_parser_roll_indent(parser, parser->mark.column, -1, + YAML_BLOCK_SEQUENCE_START_TOKEN, parser->mark)) return 0; } else @@ -2087,24 +1607,16 @@ yaml_parser_fetch_block_entry(yaml_parser_t *parser) /* Consume the token. */ - start_mark = yaml_parser_get_mark(parser); - FORWARD(parser); - end_mark = yaml_parser_get_mark(parser); + start_mark = parser->mark; + SKIP(parser); + end_mark = parser->mark; - /* Create the BLOCK-ENTRY token. */ + /* Create the BLOCK-ENTRY token and append it to the queue. */ - token = yaml_token_new(YAML_BLOCK_ENTRY_TOKEN, start_mark, end_mark); - if (!token) { - parser->error = YAML_MEMORY_ERROR; - return 0; - } + TOKEN_INIT(token, YAML_BLOCK_ENTRY_TOKEN, start_mark, end_mark); - /* Append the token to the queue. */ - - if (!yaml_parser_append_token(parser, token)) { - yaml_token_delete(token); + if (!ENQUEUE(parser, parser->tokens, token)) return 0; - } return 1; } @@ -2117,7 +1629,7 @@ static int yaml_parser_fetch_key(yaml_parser_t *parser) { yaml_mark_t start_mark, end_mark; - yaml_token_t *token; + yaml_token_t token; /* In the block context, additional checks are required. */ @@ -2126,15 +1638,14 @@ yaml_parser_fetch_key(yaml_parser_t *parser) /* Check if we are allowed to start a new key (not nessesary simple). */ if (!parser->simple_key_allowed) { - return yaml_parser_set_scanner_error(parser, NULL, - yaml_parser_get_mark(parser), + return yaml_parser_set_scanner_error(parser, NULL, parser->mark, "mapping keys are not allowed in this context"); } /* Add the BLOCK-MAPPING-START token if needed. */ - if (!yaml_parser_roll_indent(parser, parser->column, -1, - YAML_BLOCK_MAPPING_START_TOKEN, yaml_parser_get_mark(parser))) + if (!yaml_parser_roll_indent(parser, parser->mark.column, -1, + YAML_BLOCK_MAPPING_START_TOKEN, parser->mark)) return 0; } @@ -2149,24 +1660,16 @@ yaml_parser_fetch_key(yaml_parser_t *parser) /* Consume the token. */ - start_mark = yaml_parser_get_mark(parser); - FORWARD(parser); - end_mark = yaml_parser_get_mark(parser); + start_mark = parser->mark; + SKIP(parser); + end_mark = parser->mark; - /* Create the KEY token. */ - - token = yaml_token_new(YAML_KEY_TOKEN, start_mark, end_mark); - if (!token) { - parser->error = YAML_MEMORY_ERROR; - return 0; - } + /* Create the KEY token and append it to the queue. */ - /* Append the token to the queue. */ + TOKEN_INIT(token, YAML_KEY_TOKEN, start_mark, end_mark); - if (!yaml_parser_append_token(parser, token)) { - yaml_token_delete(token); + if (!ENQUEUE(parser, parser->tokens, token)) return 0; - } return 1; } @@ -2179,40 +1682,32 @@ static int yaml_parser_fetch_value(yaml_parser_t *parser) { yaml_mark_t start_mark, end_mark; - yaml_token_t *token; + yaml_token_t token; + yaml_simple_key_t *simple_key = parser->simple_keys.top-1; /* Have we found a simple key? */ - if (parser->simple_keys[parser->flow_level]) + if (simple_key->possible) { - yaml_simple_key_t *simple_key = parser->simple_keys[parser->flow_level]; - /* Create the KEY token. */ + /* Create the KEY token and insert it into the queue. */ - token = yaml_token_new(YAML_KEY_TOKEN, simple_key->mark, simple_key->mark); - if (!token) { - parser->error = YAML_MEMORY_ERROR; - return 0; - } - - /* Insert the token into the queue. */ + TOKEN_INIT(token, YAML_KEY_TOKEN, simple_key->mark, simple_key->mark); - if (!yaml_parser_insert_token(parser, simple_key->token_number, token)) { - yaml_token_delete(token); + if (!QUEUE_INSERT(parser, parser->tokens, + simple_key->token_number - parser->tokens_parsed, token)) return 0; - } /* In the block context, we may need to add the BLOCK-MAPPING-START token. */ - if (!yaml_parser_roll_indent(parser, parser->column, + if (!yaml_parser_roll_indent(parser, simple_key->mark.column, simple_key->token_number, YAML_BLOCK_MAPPING_START_TOKEN, simple_key->mark)) return 0; - /* Remove the simple key from the list. */ + /* Remove the simple key. */ - yaml_free(simple_key); - parser->simple_keys[parser->flow_level] = NULL; + simple_key->possible = 0; /* A simple key cannot follow another simple key. */ @@ -2229,15 +1724,14 @@ yaml_parser_fetch_value(yaml_parser_t *parser) /* Check if we are allowed to start a complex value. */ if (!parser->simple_key_allowed) { - return yaml_parser_set_scanner_error(parser, NULL, - yaml_parser_get_mark(parser), + return yaml_parser_set_scanner_error(parser, NULL, parser->mark, "mapping values are not allowed in this context"); } /* Add the BLOCK-MAPPING-START token if needed. */ - if (!yaml_parser_roll_indent(parser, parser->column, -1, - YAML_BLOCK_MAPPING_START_TOKEN, yaml_parser_get_mark(parser))) + if (!yaml_parser_roll_indent(parser, parser->mark.column, -1, + YAML_BLOCK_MAPPING_START_TOKEN, parser->mark)) return 0; } @@ -2248,24 +1742,16 @@ yaml_parser_fetch_value(yaml_parser_t *parser) /* Consume the token. */ - start_mark = yaml_parser_get_mark(parser); - FORWARD(parser); - end_mark = yaml_parser_get_mark(parser); + start_mark = parser->mark; + SKIP(parser); + end_mark = parser->mark; - /* Create the VALUE token. */ + /* Create the VALUE token and append it to the queue. */ - token = yaml_token_new(YAML_VALUE_TOKEN, start_mark, end_mark); - if (!token) { - parser->error = YAML_MEMORY_ERROR; - return 0; - } - - /* Append the token to the queue. */ + TOKEN_INIT(token, YAML_VALUE_TOKEN, start_mark, end_mark); - if (!yaml_parser_append_token(parser, token)) { - yaml_token_delete(token); + if (!ENQUEUE(parser, parser->tokens, token)) return 0; - } return 1; } @@ -2277,7 +1763,7 @@ yaml_parser_fetch_value(yaml_parser_t *parser) static int yaml_parser_fetch_anchor(yaml_parser_t *parser, yaml_token_type_t type) { - yaml_token_t *token; + yaml_token_t token; /* An anchor or an alias could be a simple key. */ @@ -2288,18 +1774,15 @@ yaml_parser_fetch_anchor(yaml_parser_t *parser, yaml_token_type_t type) parser->simple_key_allowed = 0; - /* Create the ALIAS or ANCHOR token. */ - - token = yaml_parser_scan_anchor(parser, type); - if (!token) return 0; + /* Create the ALIAS or ANCHOR token and append it to the queue. */ - /* Append the token to the queue. */ + if (!yaml_parser_scan_anchor(parser, &token, type)) + return 0; - if (!yaml_parser_append_token(parser, token)) { - yaml_token_delete(token); + if (!ENQUEUE(parser, parser->tokens, token)) { + yaml_token_delete(&token); return 0; } - return 1; } @@ -2310,7 +1793,7 @@ yaml_parser_fetch_anchor(yaml_parser_t *parser, yaml_token_type_t type) static int yaml_parser_fetch_tag(yaml_parser_t *parser) { - yaml_token_t *token; + yaml_token_t token; /* A tag could be a simple key. */ @@ -2321,15 +1804,13 @@ yaml_parser_fetch_tag(yaml_parser_t *parser) parser->simple_key_allowed = 0; - /* Create the TAG token. */ - - token = yaml_parser_scan_tag(parser); - if (!token) return 0; + /* Create the TAG token and append it to the queue. */ - /* Append the token to the queue. */ + if (!yaml_parser_scan_tag(parser, &token)) + return 0; - if (!yaml_parser_append_token(parser, token)) { - yaml_token_delete(token); + if (!ENQUEUE(parser, parser->tokens, token)) { + yaml_token_delete(&token); return 0; } @@ -2343,7 +1824,7 @@ yaml_parser_fetch_tag(yaml_parser_t *parser) static int yaml_parser_fetch_block_scalar(yaml_parser_t *parser, int literal) { - yaml_token_t *token; + yaml_token_t token; /* Remove any potential simple keys. */ @@ -2354,15 +1835,13 @@ yaml_parser_fetch_block_scalar(yaml_parser_t *parser, int literal) parser->simple_key_allowed = 1; - /* Create the SCALAR token. */ - - token = yaml_parser_scan_block_scalar(parser, literal); - if (!token) return 0; + /* Create the SCALAR token and append it to the queue. */ - /* Append the token to the queue. */ + if (!yaml_parser_scan_block_scalar(parser, &token, literal)) + return 0; - if (!yaml_parser_append_token(parser, token)) { - yaml_token_delete(token); + if (!ENQUEUE(parser, parser->tokens, token)) { + yaml_token_delete(&token); return 0; } @@ -2376,7 +1855,7 @@ yaml_parser_fetch_block_scalar(yaml_parser_t *parser, int literal) static int yaml_parser_fetch_flow_scalar(yaml_parser_t *parser, int single) { - yaml_token_t *token; + yaml_token_t token; /* A plain scalar could be a simple key. */ @@ -2387,15 +1866,13 @@ yaml_parser_fetch_flow_scalar(yaml_parser_t *parser, int single) parser->simple_key_allowed = 0; - /* Create the SCALAR token. */ - - token = yaml_parser_scan_flow_scalar(parser, single); - if (!token) return 0; + /* Create the SCALAR token and append it to the queue. */ - /* Append the token to the queue. */ + if (!yaml_parser_scan_flow_scalar(parser, &token, single)) + return 0; - if (!yaml_parser_append_token(parser, token)) { - yaml_token_delete(token); + if (!ENQUEUE(parser, parser->tokens, token)) { + yaml_token_delete(&token); return 0; } @@ -2409,7 +1886,7 @@ yaml_parser_fetch_flow_scalar(yaml_parser_t *parser, int single) static int yaml_parser_fetch_plain_scalar(yaml_parser_t *parser) { - yaml_token_t *token; + yaml_token_t token; /* A plain scalar could be a simple key. */ @@ -2420,15 +1897,13 @@ yaml_parser_fetch_plain_scalar(yaml_parser_t *parser) parser->simple_key_allowed = 0; - /* Create the SCALAR token. */ - - token = yaml_parser_scan_plain_scalar(parser); - if (!token) return 0; + /* Create the SCALAR token and append it to the queue. */ - /* Append the token to the queue. */ + if (!yaml_parser_scan_plain_scalar(parser, &token)) + return 0; - if (!yaml_parser_append_token(parser, token)) { - yaml_token_delete(token); + if (!ENQUEUE(parser, parser->tokens, token)) { + yaml_token_delete(&token); return 0; } @@ -2448,10 +1923,10 @@ yaml_parser_scan_to_next_token(yaml_parser_t *parser) { /* Allow the BOM mark to start a line. */ - if (!UPDATE(parser, 1)) return 0; + if (!CACHE(parser, 1)) return 0; - if (parser->column == 0 && IS_BOM(parser)) - FORWARD(parser); + if (parser->mark.column == 0 && IS_BOM(parser->buffer)) + SKIP(parser); /* * Eat whitespaces. @@ -2463,30 +1938,30 @@ yaml_parser_scan_to_next_token(yaml_parser_t *parser) * after '-', '?', or ':' (complex value). */ - if (!UPDATE(parser, 1)) return 0; + if (!CACHE(parser, 1)) return 0; - while (CHECK(parser,' ') || + while (CHECK(parser->buffer,' ') || ((parser->flow_level || !parser->simple_key_allowed) && - CHECK(parser, '\t'))) { - FORWARD(parser); - if (!UPDATE(parser, 1)) return 0; + CHECK(parser->buffer, '\t'))) { + SKIP(parser); + if (!CACHE(parser, 1)) return 0; } /* Eat a comment until a line break. */ - if (CHECK(parser, '#')) { - while (!IS_BREAKZ(parser)) { - FORWARD(parser); - if (!UPDATE(parser, 1)) return 0; + if (CHECK(parser->buffer, '#')) { + while (!IS_BREAKZ(parser->buffer)) { + SKIP(parser); + if (!CACHE(parser, 1)) return 0; } } /* If it is a line break, eat it. */ - if (IS_BREAK(parser)) + if (IS_BREAK(parser->buffer)) { - if (!UPDATE(parser, 2)) return 0; - FORWARD_LINE(parser); + if (!CACHE(parser, 2)) return 0; + SKIP_LINE(parser); /* In the block context, a new line may start a simple key. */ @@ -2515,20 +1990,19 @@ yaml_parser_scan_to_next_token(yaml_parser_t *parser) * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */ -static yaml_token_t * -yaml_parser_scan_directive(yaml_parser_t *parser) +int +yaml_parser_scan_directive(yaml_parser_t *parser, yaml_token_t *token) { yaml_mark_t start_mark, end_mark; yaml_char_t *name = NULL; int major, minor; yaml_char_t *handle = NULL, *prefix = NULL; - yaml_token_t *token = NULL; /* Eat '%'. */ - start_mark = yaml_parser_get_mark(parser); + start_mark = parser->mark; - FORWARD(parser); + SKIP(parser); /* Scan the directive name. */ @@ -2545,16 +2019,12 @@ yaml_parser_scan_directive(yaml_parser_t *parser) &major, &minor)) goto error; - end_mark = yaml_parser_get_mark(parser); + end_mark = parser->mark; /* Create a VERSION-DIRECTIVE token. */ - token = yaml_version_directive_token_new(major, minor, + VERSION_DIRECTIVE_TOKEN_INIT(*token, major, minor, start_mark, end_mark); - if (!token) { - parser->error = YAML_MEMORY_ERROR; - return 0; - } } /* Is it a TAG directive? */ @@ -2567,16 +2037,12 @@ yaml_parser_scan_directive(yaml_parser_t *parser) &handle, &prefix)) goto error; - end_mark = yaml_parser_get_mark(parser); + end_mark = parser->mark; /* Create a TAG-DIRECTIVE token. */ - token = yaml_tag_directive_token_new(handle, prefix, + TAG_DIRECTIVE_TOKEN_INIT(*token, handle, prefix, start_mark, end_mark); - if (!token) { - parser->error = YAML_MEMORY_ERROR; - return 0; - } } /* Unknown directive. */ @@ -2590,43 +2056,44 @@ yaml_parser_scan_directive(yaml_parser_t *parser) /* Eat the rest of the line including any comments. */ - while (IS_BLANK(parser)) { - FORWARD(parser); - if (!UPDATE(parser, 1)) goto error; + if (!CACHE(parser, 1)) goto error; + + while (IS_BLANK(parser->buffer)) { + SKIP(parser); + if (!CACHE(parser, 1)) goto error; } - if (CHECK(parser, '#')) { - while (!IS_BREAKZ(parser)) { - FORWARD(parser); - if (!UPDATE(parser, 1)) goto error; + if (CHECK(parser->buffer, '#')) { + while (!IS_BREAKZ(parser->buffer)) { + SKIP(parser); + if (!CACHE(parser, 1)) goto error; } } /* Check if we are at the end of the line. */ - if (!IS_BREAKZ(parser)) { + if (!IS_BREAKZ(parser->buffer)) { yaml_parser_set_scanner_error(parser, "while scanning a directive", - start_mark, "did not found expected comment or line break"); + start_mark, "did not find expected comment or line break"); goto error; } /* Eat a line break. */ - if (IS_BREAK(parser)) { - if (!UPDATE(parser, 2)) goto error; - FORWARD_LINE(parser); + if (IS_BREAK(parser->buffer)) { + if (!CACHE(parser, 2)) goto error; + SKIP_LINE(parser); } yaml_free(name); - return token; + return 1; error: - yaml_free(token); yaml_free(prefix); yaml_free(handle); yaml_free(name); - return NULL; + return 0; } /* @@ -2643,43 +2110,42 @@ static int yaml_parser_scan_directive_name(yaml_parser_t *parser, yaml_mark_t start_mark, yaml_char_t **name) { - yaml_string_t string = yaml_parser_new_string(parser); + yaml_string_t string = NULL_STRING; - if (!string.buffer) goto error; + if (!STRING_INIT(parser, string, INITIAL_STRING_SIZE)) goto error; /* Consume the directive name. */ - if (!UPDATE(parser, 1)) goto error; + if (!CACHE(parser, 1)) goto error; - while (IS_ALPHA(parser)) + while (IS_ALPHA(parser->buffer)) { - if (!RESIZE(parser, string)) goto error; - COPY(parser, string); - if (!UPDATE(parser, 1)) goto error; + if (!READ(parser, string)) goto error; + if (!CACHE(parser, 1)) goto error; } /* Check if the name is empty. */ - if (string.buffer == string.pointer) { + if (string.start == string.pointer) { yaml_parser_set_scanner_error(parser, "while scanning a directive", - start_mark, "cannot found expected directive name"); + start_mark, "could not find expected directive name"); goto error; } /* Check for an blank character after the name. */ - if (!IS_BLANKZ(parser)) { + if (!IS_BLANKZ(parser->buffer)) { yaml_parser_set_scanner_error(parser, "while scanning a directive", start_mark, "found unexpected non-alphabetical character"); goto error; } - *name = string.buffer; + *name = string.start; return 1; error: - yaml_free(string.buffer); + STRING_DEL(parser, string); return 0; } @@ -2697,11 +2163,11 @@ yaml_parser_scan_version_directive_value(yaml_parser_t *parser, { /* Eat whitespaces. */ - if (!UPDATE(parser, 1)) return 0; + if (!CACHE(parser, 1)) return 0; - while (IS_BLANK(parser)) { - FORWARD(parser); - if (!UPDATE(parser, 1)) return 0; + while (IS_BLANK(parser->buffer)) { + SKIP(parser); + if (!CACHE(parser, 1)) return 0; } /* Consume the major version number. */ @@ -2711,17 +2177,19 @@ yaml_parser_scan_version_directive_value(yaml_parser_t *parser, /* Eat '.'. */ - if (!CHECK(parser, '.')) { + if (!CHECK(parser->buffer, '.')) { return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive", start_mark, "did not find expected digit or '.' character"); } - FORWARD(parser); + SKIP(parser); /* Consume the minor version number. */ if (!yaml_parser_scan_version_directive_number(parser, start_mark, minor)) return 0; + + return 1; } #define MAX_NUMBER_LENGTH 9 @@ -2745,9 +2213,9 @@ yaml_parser_scan_version_directive_number(yaml_parser_t *parser, /* Repeat while the next character is digit. */ - if (!UPDATE(parser, 1)) return 0; + if (!CACHE(parser, 1)) return 0; - while (IS_DIGIT(parser)) + while (IS_DIGIT(parser->buffer)) { /* Check if the number is too long. */ @@ -2756,11 +2224,11 @@ yaml_parser_scan_version_directive_number(yaml_parser_t *parser, start_mark, "found extremely long version number"); } - value = value*10 + AS_DIGIT(parser); + value = value*10 + AS_DIGIT(parser->buffer); - FORWARD(parser); + SKIP(parser); - if (!UPDATE(parser, 1)) return 0; + if (!CACHE(parser, 1)) return 0; } /* Check if the number was present. */ @@ -2792,11 +2260,11 @@ yaml_parser_scan_tag_directive_value(yaml_parser_t *parser, /* Eat whitespaces. */ - if (!UPDATE(parser, 1)) goto error; + if (!CACHE(parser, 1)) goto error; - while (IS_BLANK(parser)) { - FORWARD(parser); - if (!UPDATE(parser, 1)) goto error; + while (IS_BLANK(parser->buffer)) { + SKIP(parser); + if (!CACHE(parser, 1)) goto error; } /* Scan a handle. */ @@ -2806,9 +2274,9 @@ yaml_parser_scan_tag_directive_value(yaml_parser_t *parser, /* Expect a whitespace. */ - if (!UPDATE(parser, 1)) goto error; + if (!CACHE(parser, 1)) goto error; - if (!IS_BLANK(parser)) { + if (!IS_BLANK(parser->buffer)) { yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive", start_mark, "did not find expected whitespace"); goto error; @@ -2816,9 +2284,9 @@ yaml_parser_scan_tag_directive_value(yaml_parser_t *parser, /* Eat whitespaces. */ - while (IS_BLANK(parser)) { - FORWARD(parser); - if (!UPDATE(parser, 1)) goto error; + while (IS_BLANK(parser->buffer)) { + SKIP(parser); + if (!CACHE(parser, 1)) goto error; } /* Scan a prefix. */ @@ -2828,9 +2296,9 @@ yaml_parser_scan_tag_directive_value(yaml_parser_t *parser, /* Expect a whitespace or line break. */ - if (!UPDATE(parser, 1)) goto error; + if (!CACHE(parser, 1)) goto error; - if (!IS_BLANKZ(parser)) { + if (!IS_BLANKZ(parser->buffer)) { yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive", start_mark, "did not find expected whitespace or line break"); goto error; @@ -2847,35 +2315,33 @@ error: return 0; } -static yaml_token_t * -yaml_parser_scan_anchor(yaml_parser_t *parser, +static int +yaml_parser_scan_anchor(yaml_parser_t *parser, yaml_token_t *token, yaml_token_type_t type) { int length = 0; yaml_mark_t start_mark, end_mark; - yaml_token_t *token = NULL; - yaml_string_t string = yaml_parser_new_string(parser); + yaml_string_t string = NULL_STRING; - if (!string.buffer) goto error; + if (!STRING_INIT(parser, string, INITIAL_STRING_SIZE)) goto error; /* Eat the indicator character. */ - start_mark = yaml_parser_get_mark(parser); + start_mark = parser->mark; - FORWARD(parser); + SKIP(parser); /* Consume the value. */ - if (!UPDATE(parser, 1)) goto error; + if (!CACHE(parser, 1)) goto error; - while (IS_ALPHA(parser)) { - if (!RESIZE(parser, string)) goto error; - COPY(parser, string); - if (!UPDATE(parser, 1)) goto error; + while (IS_ALPHA(parser->buffer)) { + if (!READ(parser, string)) goto error; + if (!CACHE(parser, 1)) goto error; length ++; } - end_mark = yaml_parser_get_mark(parser); + end_mark = parser->mark; /* * Check if length of the anchor is greater than 0 and it is followed by @@ -2884,9 +2350,11 @@ yaml_parser_scan_anchor(yaml_parser_t *parser, * '?', ':', ',', ']', '}', '%', '@', '`'. */ - if (!length || !(IS_BLANKZ(parser) || CHECK(parser, '?') || CHECK(parser, ':') || - CHECK(parser, ',') || CHECK(parser, ']') || CHECK(parser, '}') || - CHECK(parser, '%') || CHECK(parser, '@') || CHECK(parser, '`'))) { + if (!length || !(IS_BLANKZ(parser->buffer) || CHECK(parser->buffer, '?') + || CHECK(parser->buffer, ':') || CHECK(parser->buffer, ',') + || CHECK(parser->buffer, ']') || CHECK(parser->buffer, '}') + || CHECK(parser->buffer, '%') || CHECK(parser->buffer, '@') + || CHECK(parser->buffer, '`'))) { yaml_parser_set_scanner_error(parser, type == YAML_ANCHOR_TOKEN ? "while scanning an anchor" : "while scanning an alias", start_mark, "did not find expected alphabetic or numeric character"); @@ -2895,19 +2363,17 @@ yaml_parser_scan_anchor(yaml_parser_t *parser, /* Create a token. */ - token = type == YAML_ANCHOR_TOKEN ? - yaml_anchor_token_new(string.buffer, start_mark, end_mark) : - yaml_alias_token_new(string.buffer, start_mark, end_mark); - if (!token) { - parser->error = YAML_MEMORY_ERROR; - return 0; + if (type == YAML_ANCHOR_TOKEN) { + ANCHOR_TOKEN_INIT(*token, string.start, start_mark, end_mark); + } + else { + ALIAS_TOKEN_INIT(*token, string.start, start_mark, end_mark); } - return token; + return 1; error: - yaml_free(string.buffer); - yaml_free(token); + STRING_DEL(parser, string); return 0; } @@ -2915,21 +2381,20 @@ error: * Scan a TAG token. */ -static yaml_token_t * -yaml_parser_scan_tag(yaml_parser_t *parser) +static int +yaml_parser_scan_tag(yaml_parser_t *parser, yaml_token_t *token) { yaml_char_t *handle = NULL; yaml_char_t *suffix = NULL; - yaml_token_t *token = NULL; yaml_mark_t start_mark, end_mark; - start_mark = yaml_parser_get_mark(parser); + start_mark = parser->mark; /* Check if the tag is in the canonical form. */ - if (!UPDATE(parser, 2)) goto error; + if (!CACHE(parser, 2)) goto error; - if (CHECK_AT(parser, '<', 1)) + if (CHECK_AT(parser->buffer, '<', 1)) { /* Set the handle to '' */ @@ -2939,8 +2404,8 @@ yaml_parser_scan_tag(yaml_parser_t *parser) /* Eat '!<' */ - FORWARD(parser); - FORWARD(parser); + SKIP(parser); + SKIP(parser); /* Consume the tag value. */ @@ -2949,13 +2414,13 @@ yaml_parser_scan_tag(yaml_parser_t *parser) /* Check for '>' and eat it. */ - if (!CHECK(parser, '>')) { + if (!CHECK(parser->buffer, '>')) { yaml_parser_set_scanner_error(parser, "while scanning a tag", start_mark, "did not find the expected '>'"); goto error; } - FORWARD(parser); + SKIP(parser); } else { @@ -2989,35 +2454,42 @@ yaml_parser_scan_tag(yaml_parser_t *parser) if (!handle) goto error; handle[0] = '!'; handle[1] = '\0'; + + /* + * A special case: the '!' tag. Set the handle to '' and the + * suffix to '!'. + */ + + if (suffix[0] == '\0') { + yaml_char_t *tmp = handle; + handle = suffix; + suffix = tmp; + } } } /* Check the character which ends the tag. */ - if (!UPDATE(parser, 1)) goto error; + if (!CACHE(parser, 1)) goto error; - if (!IS_BLANKZ(parser)) { + if (!IS_BLANKZ(parser->buffer)) { yaml_parser_set_scanner_error(parser, "while scanning a tag", - start_mark, "did not found expected whitespace or line break"); + start_mark, "did not find expected whitespace or line break"); goto error; } - end_mark = yaml_parser_get_mark(parser); + end_mark = parser->mark; /* Create a token. */ - token = yaml_tag_token_new(handle, suffix, start_mark, end_mark); - if (!token) { - parser->error = YAML_MEMORY_ERROR; - return 0; - } + TAG_TOKEN_INIT(*token, handle, suffix, start_mark, end_mark); - return token; + return 1; error: yaml_free(handle); yaml_free(suffix); - return NULL; + return 0; } /* @@ -3028,15 +2500,15 @@ static int yaml_parser_scan_tag_handle(yaml_parser_t *parser, int directive, yaml_mark_t start_mark, yaml_char_t **handle) { - yaml_string_t string = yaml_parser_new_string(parser); + yaml_string_t string = NULL_STRING; - if (!string.buffer) goto error; + if (!STRING_INIT(parser, string, INITIAL_STRING_SIZE)) goto error; /* Check the initial '!' character. */ - if (!UPDATE(parser, 1)) goto error; + if (!CACHE(parser, 1)) goto error; - if (!CHECK(parser, '!')) { + if (!CHECK(parser->buffer, '!')) { yaml_parser_set_scanner_error(parser, directive ? "while scanning a tag directive" : "while scanning a tag", start_mark, "did not find expected '!'"); @@ -3045,46 +2517,45 @@ yaml_parser_scan_tag_handle(yaml_parser_t *parser, int directive, /* Copy the '!' character. */ - COPY(parser, string); + if (!READ(parser, string)) goto error; /* Copy all subsequent alphabetical and numerical characters. */ - if (!UPDATE(parser, 1)) goto error; + if (!CACHE(parser, 1)) goto error; - while (IS_ALPHA(parser)) + while (IS_ALPHA(parser->buffer)) { - if (!RESIZE(parser, string)) goto error; - COPY(parser, string); - if (!UPDATE(parser, 1)) goto error; + if (!READ(parser, string)) goto error; + if (!CACHE(parser, 1)) goto error; } /* Check if the trailing character is '!' and copy it. */ - if (CHECK(parser, '!')) + if (CHECK(parser->buffer, '!')) { - if (!RESIZE(parser, string)) goto error; - COPY(parser, string); + if (!READ(parser, string)) goto error; } else { /* - * It's not really a tag handle. If it's a %TAG directive, it's an - * error. If it's a tag token, it must be a part of URI. + * It's either the '!' tag or not really a tag handle. If it's a %TAG + * directive, it's an error. If it's a tag token, it must be a part of + * URI. */ - if (directive) { - yaml_parser_set_scanner_error(parser, "while parsing a directive", + if (directive && !(string.start[0] == '!' && string.start[1] == '\0')) { + yaml_parser_set_scanner_error(parser, "while parsing a tag directive", start_mark, "did not find expected '!'"); goto error; } } - *handle = string.buffer; + *handle = string.start; return 1; error: - yaml_free(string.buffer); + STRING_DEL(parser, string); return 0; } @@ -3097,26 +2568,33 @@ yaml_parser_scan_tag_uri(yaml_parser_t *parser, int directive, yaml_char_t *head, yaml_mark_t start_mark, yaml_char_t **uri) { size_t length = head ? strlen((char *)head) : 0; - yaml_string_t string = yaml_parser_new_string(parser); + yaml_string_t string = NULL_STRING; - if (!string.buffer) goto error; + if (!STRING_INIT(parser, string, INITIAL_STRING_SIZE)) goto error; /* Resize the string to include the head. */ - while (string.size <= length) { - if (!yaml_parser_resize_string(parser, &string)) goto error; + while (string.end - string.start <= (int)length) { + if (!yaml_string_extend(&string.start, &string.pointer, &string.end)) { + parser->error = YAML_MEMORY_ERROR; + goto error; + } } - /* Copy the head if needed. */ + /* + * Copy the head if needed. + * + * Note that we don't copy the leading '!' character. + */ - if (length) { - memcpy(string.buffer, head, length); - string.pointer += length; + if (length > 1) { + memcpy(string.start, head+1, length-1); + string.pointer += length-1; } /* Scan the tag. */ - if (!UPDATE(parser, 1)) goto error; + if (!CACHE(parser, 1)) goto error; /* * The set of characters that may appear in URI is as follows: @@ -3126,45 +2604,50 @@ yaml_parser_scan_tag_uri(yaml_parser_t *parser, int directive, * '%'. */ - while (IS_ALPHA(parser) || CHECK(parser, ';') || CHECK(parser, '/') || - CHECK(parser, '?') || CHECK(parser, ':') || CHECK(parser, '@') || - CHECK(parser, '&') || CHECK(parser, '=') || CHECK(parser, '+') || - CHECK(parser, '$') || CHECK(parser, ',') || CHECK(parser, '.') || - CHECK(parser, '!') || CHECK(parser, '~') || CHECK(parser, '*') || - CHECK(parser, '\'') || CHECK(parser, '(') || CHECK(parser, ')') || - CHECK(parser, '[') || CHECK(parser, ']') || CHECK(parser, '%')) + while (IS_ALPHA(parser->buffer) || CHECK(parser->buffer, ';') + || CHECK(parser->buffer, '/') || CHECK(parser->buffer, '?') + || CHECK(parser->buffer, ':') || CHECK(parser->buffer, '@') + || CHECK(parser->buffer, '&') || CHECK(parser->buffer, '=') + || CHECK(parser->buffer, '+') || CHECK(parser->buffer, '$') + || CHECK(parser->buffer, ',') || CHECK(parser->buffer, '.') + || CHECK(parser->buffer, '!') || CHECK(parser->buffer, '~') + || CHECK(parser->buffer, '*') || CHECK(parser->buffer, '\'') + || CHECK(parser->buffer, '(') || CHECK(parser->buffer, ')') + || CHECK(parser->buffer, '[') || CHECK(parser->buffer, ']') + || CHECK(parser->buffer, '%')) { - if (!RESIZE(parser, string)) goto error; - /* Check if it is a URI-escape sequence. */ - if (CHECK(parser, '%')) { + if (CHECK(parser->buffer, '%')) { if (!yaml_parser_scan_uri_escapes(parser, directive, start_mark, &string)) goto error; } else { - COPY(parser, string); + if (!READ(parser, string)) goto error; } length ++; - if (!UPDATE(parser, 1)) goto error; + if (!CACHE(parser, 1)) goto error; } /* Check if the tag is non-empty. */ if (!length) { + if (!STRING_EXTEND(parser, string)) + goto error; + yaml_parser_set_scanner_error(parser, directive ? "while parsing a %TAG directive" : "while parsing a tag", start_mark, "did not find expected tag URI"); goto error; } - *uri = string.buffer; + *uri = string.start; return 1; error: - yaml_free(string.buffer); + STRING_DEL(parser, string); return 0; } @@ -3186,9 +2669,11 @@ yaml_parser_scan_uri_escapes(yaml_parser_t *parser, int directive, /* Check for a URI-escaped octet. */ - if (!UPDATE(parser, 3)) return 0; + if (!CACHE(parser, 3)) return 0; - if (!(CHECK(parser, '%') && IS_HEX_AT(parser, 1) && IS_HEX_AT(parser, 2))) { + if (!(CHECK(parser->buffer, '%') + && IS_HEX_AT(parser->buffer, 1) + && IS_HEX_AT(parser->buffer, 2))) { return yaml_parser_set_scanner_error(parser, directive ? "while parsing a %TAG directive" : "while parsing a tag", start_mark, "did not find URI escaped octet"); @@ -3196,7 +2681,7 @@ yaml_parser_scan_uri_escapes(yaml_parser_t *parser, int directive, /* Get the octet. */ - octet = (AS_HEX_AT(parser, 1) << 4) + AS_HEX_AT(parser, 2); + octet = (AS_HEX_AT(parser->buffer, 1) << 4) + AS_HEX_AT(parser->buffer, 2); /* If it is the leading octet, determine the length of the UTF-8 sequence. */ @@ -3226,9 +2711,9 @@ yaml_parser_scan_uri_escapes(yaml_parser_t *parser, int directive, /* Copy the octet and move the pointers. */ *(string->pointer++) = octet; - FORWARD(parser); - FORWARD(parser); - FORWARD(parser); + SKIP(parser); + SKIP(parser); + SKIP(parser); } while (--width); @@ -3239,54 +2724,54 @@ yaml_parser_scan_uri_escapes(yaml_parser_t *parser, int directive, * Scan a block scalar. */ -static yaml_token_t * -yaml_parser_scan_block_scalar(yaml_parser_t *parser, int literal) +static int +yaml_parser_scan_block_scalar(yaml_parser_t *parser, yaml_token_t *token, + int literal) { yaml_mark_t start_mark; yaml_mark_t end_mark; - yaml_string_t string = yaml_parser_new_string(parser); - yaml_string_t leading_break = yaml_parser_new_string(parser); - yaml_string_t trailing_breaks = yaml_parser_new_string(parser); - yaml_token_t *token = NULL; + yaml_string_t string = NULL_STRING; + yaml_string_t leading_break = NULL_STRING; + yaml_string_t trailing_breaks = NULL_STRING; int chomping = 0; int increment = 0; int indent = 0; int leading_blank = 0; int trailing_blank = 0; - if (!string.buffer) goto error; - if (!leading_break.buffer) goto error; - if (!trailing_breaks.buffer) goto error; + if (!STRING_INIT(parser, string, INITIAL_STRING_SIZE)) goto error; + if (!STRING_INIT(parser, leading_break, INITIAL_STRING_SIZE)) goto error; + if (!STRING_INIT(parser, trailing_breaks, INITIAL_STRING_SIZE)) goto error; /* Eat the indicator '|' or '>'. */ - start_mark = yaml_parser_get_mark(parser); + start_mark = parser->mark; - FORWARD(parser); + SKIP(parser); /* Scan the additional block scalar indicators. */ - if (!UPDATE(parser, 1)) goto error; + if (!CACHE(parser, 1)) goto error; /* Check for a chomping indicator. */ - if (CHECK(parser, '+') || CHECK(parser, '-')) + if (CHECK(parser->buffer, '+') || CHECK(parser->buffer, '-')) { /* Set the chomping method and eat the indicator. */ - chomping = CHECK(parser, '+') ? +1 : -1; + chomping = CHECK(parser->buffer, '+') ? +1 : -1; - FORWARD(parser); + SKIP(parser); /* Check for an indentation indicator. */ - if (!UPDATE(parser, 1)) goto error; + if (!CACHE(parser, 1)) goto error; - if (IS_DIGIT(parser)) + if (IS_DIGIT(parser->buffer)) { /* Check that the intendation is greater than 0. */ - if (CHECK(parser, '0')) { + if (CHECK(parser->buffer, '0')) { yaml_parser_set_scanner_error(parser, "while scanning a block scalar", start_mark, "found an intendation indicator equal to 0"); goto error; @@ -3294,66 +2779,67 @@ yaml_parser_scan_block_scalar(yaml_parser_t *parser, int literal) /* Get the intendation level and eat the indicator. */ - increment = AS_DIGIT(parser); + increment = AS_DIGIT(parser->buffer); - FORWARD(parser); + SKIP(parser); } } /* Do the same as above, but in the opposite order. */ - else if (IS_DIGIT(parser)) + else if (IS_DIGIT(parser->buffer)) { - if (CHECK(parser, '0')) { + if (CHECK(parser->buffer, '0')) { yaml_parser_set_scanner_error(parser, "while scanning a block scalar", start_mark, "found an intendation indicator equal to 0"); goto error; } - increment = AS_DIGIT(parser); + increment = AS_DIGIT(parser->buffer); + + SKIP(parser); - FORWARD(parser); + if (!CACHE(parser, 1)) goto error; - if (!UPDATE(parser, 1)) goto error; + if (CHECK(parser->buffer, '+') || CHECK(parser->buffer, '-')) { + chomping = CHECK(parser->buffer, '+') ? +1 : -1; - if (CHECK(parser, '+') || CHECK(parser, '-')) { - chomping = CHECK(parser, '+') ? +1 : -1; - FORWARD(parser); + SKIP(parser); } } /* Eat whitespaces and comments to the end of the line. */ - if (!UPDATE(parser, 1)) goto error; + if (!CACHE(parser, 1)) goto error; - while (IS_BLANK(parser)) { - FORWARD(parser); - if (!UPDATE(parser, 1)) goto error; + while (IS_BLANK(parser->buffer)) { + SKIP(parser); + if (!CACHE(parser, 1)) goto error; } - if (CHECK(parser, '#')) { - while (!IS_BREAKZ(parser)) { - FORWARD(parser); - if (!UPDATE(parser, 1)) goto error; + if (CHECK(parser->buffer, '#')) { + while (!IS_BREAKZ(parser->buffer)) { + SKIP(parser); + if (!CACHE(parser, 1)) goto error; } } /* Check if we are at the end of the line. */ - if (!IS_BREAKZ(parser)) { + if (!IS_BREAKZ(parser->buffer)) { yaml_parser_set_scanner_error(parser, "while scanning a block scalar", - start_mark, "did not found expected comment or line break"); + start_mark, "did not find expected comment or line break"); goto error; } /* Eat a line break. */ - if (IS_BREAK(parser)) { - if (!UPDATE(parser, 2)) goto error; - FORWARD_LINE(parser); + if (IS_BREAK(parser->buffer)) { + if (!CACHE(parser, 2)) goto error; + SKIP_LINE(parser); } - end_mark = yaml_parser_get_mark(parser); + end_mark = parser->mark; /* Set the intendation level if it was specified. */ @@ -3368,9 +2854,9 @@ yaml_parser_scan_block_scalar(yaml_parser_t *parser, int literal) /* Scan the block scalar content. */ - if (!UPDATE(parser, 1)) goto error; + if (!CACHE(parser, 1)) goto error; - while (parser->column == indent && !IS_Z(parser)) + while ((int)parser->mark.column == indent && !IS_Z(parser->buffer)) { /* * We are at the beginning of a non-empty line. @@ -3378,47 +2864,48 @@ yaml_parser_scan_block_scalar(yaml_parser_t *parser, int literal) /* Is it a trailing whitespace? */ - trailing_blank = IS_BLANK(parser); + trailing_blank = IS_BLANK(parser->buffer); /* Check if we need to fold the leading line break. */ - if (!literal && (*leading_break.buffer == '\n') + if (!literal && (*leading_break.start == '\n') && !leading_blank && !trailing_blank) { /* Do we need to join the lines by space? */ - if (*trailing_breaks.buffer == '\0') { - if (!RESIZE(parser, string)) goto error; + if (*trailing_breaks.start == '\0') { + if (!STRING_EXTEND(parser, string)) goto error; *(string.pointer ++) = ' '; } - yaml_parser_clear_string(parser, &leading_break); + CLEAR(parser, leading_break); } else { if (!JOIN(parser, string, leading_break)) goto error; + CLEAR(parser, leading_break); } /* Append the remaining line breaks. */ if (!JOIN(parser, string, trailing_breaks)) goto error; + CLEAR(parser, trailing_breaks); /* Is it a leading whitespace? */ - leading_blank = IS_BLANK(parser); + leading_blank = IS_BLANK(parser->buffer); /* Consume the current line. */ - while (!IS_BREAKZ(parser)) { - if (!RESIZE(parser, string)) goto error; - COPY(parser, string); - if (!UPDATE(parser, 1)) goto error; + while (!IS_BREAKZ(parser->buffer)) { + if (!READ(parser, string)) goto error; + if (!CACHE(parser, 1)) goto error; } /* Consume the line break. */ - if (!UPDATE(parser, 2)) goto error; + if (!CACHE(parser, 2)) goto error; - COPY_LINE(parser, leading_break); + if (!READ_LINE(parser, leading_break)) goto error; /* Eat the following intendation spaces and line breaks. */ @@ -3437,25 +2924,21 @@ yaml_parser_scan_block_scalar(yaml_parser_t *parser, int literal) /* Create a token. */ - token = yaml_scalar_token_new(string.buffer, string.pointer-string.buffer, + SCALAR_TOKEN_INIT(*token, string.start, string.pointer-string.start, literal ? YAML_LITERAL_SCALAR_STYLE : YAML_FOLDED_SCALAR_STYLE, start_mark, end_mark); - if (!token) { - parser->error = YAML_MEMORY_ERROR; - return 0; - } - yaml_free(leading_break.buffer); - yaml_free(trailing_breaks.buffer); + STRING_DEL(parser, leading_break); + STRING_DEL(parser, trailing_breaks); - return token; + return 1; error: - yaml_free(string.buffer); - yaml_free(leading_break.buffer); - yaml_free(trailing_breaks.buffer); + STRING_DEL(parser, string); + STRING_DEL(parser, leading_break); + STRING_DEL(parser, trailing_breaks); - return NULL; + return 0; } /* @@ -3470,7 +2953,7 @@ yaml_parser_scan_block_scalar_breaks(yaml_parser_t *parser, { int max_indent = 0; - *end_mark = yaml_parser_get_mark(parser); + *end_mark = parser->mark; /* Eat the intendation spaces and line breaks. */ @@ -3478,33 +2961,34 @@ yaml_parser_scan_block_scalar_breaks(yaml_parser_t *parser, { /* Eat the intendation spaces. */ - if (!UPDATE(parser, 1)) return 0; + if (!CACHE(parser, 1)) return 0; - while ((!*indent || parser->column < *indent) && IS_SPACE(parser)) { - FORWARD(parser); - if (!UPDATE(parser, 1)) return 0; + while ((!*indent || (int)parser->mark.column < *indent) + && IS_SPACE(parser->buffer)) { + SKIP(parser); + if (!CACHE(parser, 1)) return 0; } - if (parser->column > max_indent) - max_indent = parser->column; + if ((int)parser->mark.column > max_indent) + max_indent = (int)parser->mark.column; /* Check for a tab character messing the intendation. */ - if ((!*indent || parser->column < *indent) && IS_TAB(parser)) { + if ((!*indent || (int)parser->mark.column < *indent) + && IS_TAB(parser->buffer)) { return yaml_parser_set_scanner_error(parser, "while scanning a block scalar", start_mark, "found a tab character where an intendation space is expected"); } /* Have we found a non-empty line? */ - if (!IS_BREAK(parser)) break; + if (!IS_BREAK(parser->buffer)) break; /* Consume the line break. */ - if (!UPDATE(parser, 2)) return 0; - if (!RESIZE(parser, *breaks)) return 0; - COPY_LINE(parser, *breaks); - *end_mark = yaml_parser_get_mark(parser); + if (!CACHE(parser, 2)) return 0; + if (!READ_LINE(parser, *breaks)) return 0; + *end_mark = parser->mark; } /* Determine the indentation level if needed. */ @@ -3524,28 +3008,28 @@ yaml_parser_scan_block_scalar_breaks(yaml_parser_t *parser, * Scan a quoted scalar. */ -static yaml_token_t * -yaml_parser_scan_flow_scalar(yaml_parser_t *parser, int single) +static int +yaml_parser_scan_flow_scalar(yaml_parser_t *parser, yaml_token_t *token, + int single) { yaml_mark_t start_mark; yaml_mark_t end_mark; - yaml_string_t string = yaml_parser_new_string(parser); - yaml_string_t leading_break = yaml_parser_new_string(parser); - yaml_string_t trailing_breaks = yaml_parser_new_string(parser); - yaml_string_t whitespaces = yaml_parser_new_string(parser); - yaml_token_t *token = NULL; + yaml_string_t string = NULL_STRING; + yaml_string_t leading_break = NULL_STRING; + yaml_string_t trailing_breaks = NULL_STRING; + yaml_string_t whitespaces = NULL_STRING; int leading_blanks; - if (!string.buffer) goto error; - if (!leading_break.buffer) goto error; - if (!trailing_breaks.buffer) goto error; - if (!whitespaces.buffer) goto error; + if (!STRING_INIT(parser, string, INITIAL_STRING_SIZE)) goto error; + if (!STRING_INIT(parser, leading_break, INITIAL_STRING_SIZE)) goto error; + if (!STRING_INIT(parser, trailing_breaks, INITIAL_STRING_SIZE)) goto error; + if (!STRING_INIT(parser, whitespaces, INITIAL_STRING_SIZE)) goto error; /* Eat the left quote. */ - start_mark = yaml_parser_get_mark(parser); + start_mark = parser->mark; - FORWARD(parser); + SKIP(parser); /* Consume the content of the quoted scalar. */ @@ -3553,16 +3037,16 @@ yaml_parser_scan_flow_scalar(yaml_parser_t *parser, int single) { /* Check that there are no document indicators at the beginning of the line. */ - if (!UPDATE(parser, 4)) goto error; + if (!CACHE(parser, 4)) goto error; - if (parser->column == 0 && - ((CHECK_AT(parser, '-', 0) && - CHECK_AT(parser, '-', 1) && - CHECK_AT(parser, '-', 2)) || - (CHECK_AT(parser, '.', 0) && - CHECK_AT(parser, '.', 1) && - CHECK_AT(parser, '.', 2))) && - IS_BLANKZ_AT(parser, 3)) + if (parser->mark.column == 0 && + ((CHECK_AT(parser->buffer, '-', 0) && + CHECK_AT(parser->buffer, '-', 1) && + CHECK_AT(parser->buffer, '-', 2)) || + (CHECK_AT(parser->buffer, '.', 0) && + CHECK_AT(parser->buffer, '.', 1) && + CHECK_AT(parser->buffer, '.', 2))) && + IS_BLANKZ_AT(parser->buffer, 3)) { yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar", start_mark, "found unexpected document indicator"); @@ -3571,7 +3055,7 @@ yaml_parser_scan_flow_scalar(yaml_parser_t *parser, int single) /* Check for EOF. */ - if (IS_Z(parser)) { + if (IS_Z(parser->buffer)) { yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar", start_mark, "found unexpected end of stream"); goto error; @@ -3579,49 +3063,53 @@ yaml_parser_scan_flow_scalar(yaml_parser_t *parser, int single) /* Consume non-blank characters. */ - if (!UPDATE(parser, 2)) goto error; - if (!RESIZE(parser, string)) goto error; + if (!CACHE(parser, 2)) goto error; leading_blanks = 0; - while (!IS_BLANKZ(parser)) + while (!IS_BLANKZ(parser->buffer)) { /* Check for an escaped single quote. */ - if (single && CHECK_AT(parser, '\'', 0) && CHECK_AT(parser, '\'', 1)) + if (single && CHECK_AT(parser->buffer, '\'', 0) + && CHECK_AT(parser->buffer, '\'', 1)) { + if (!STRING_EXTEND(parser, string)) goto error; *(string.pointer++) = '\''; - FORWARD(parser); - FORWARD(parser); + SKIP(parser); + SKIP(parser); } /* Check for the right quote. */ - else if (CHECK(parser, single ? '\'' : '"')) + else if (CHECK(parser->buffer, single ? '\'' : '"')) { break; } /* Check for an escaped line break. */ - else if (!single && CHECK(parser, '\\') && IS_BREAK_AT(parser, 1)) + else if (!single && CHECK(parser->buffer, '\\') + && IS_BREAK_AT(parser->buffer, 1)) { - if (!UPDATE(parser, 3)) goto error; - FORWARD(parser); - FORWARD_LINE(parser); + if (!CACHE(parser, 3)) goto error; + SKIP(parser); + SKIP_LINE(parser); leading_blanks = 1; break; } /* Check for an escape sequence. */ - else if (!single && CHECK(parser, '\\')) + else if (!single && CHECK(parser->buffer, '\\')) { - int code_length = 0; + size_t code_length = 0; + + if (!STRING_EXTEND(parser, string)) goto error; /* Check the escape character. */ - switch (parser->pointer[1]) + switch (parser->buffer.pointer[1]) { case '0': *(string.pointer++) = '\0'; @@ -3672,6 +3160,10 @@ yaml_parser_scan_flow_scalar(yaml_parser_t *parser, int single) *(string.pointer++) = '\''; break; + case '\\': + *(string.pointer++) = '\\'; + break; + case 'N': /* NEL (#x85) */ *(string.pointer++) = '\xC2'; *(string.pointer++) = '\x85'; @@ -3691,7 +3183,7 @@ yaml_parser_scan_flow_scalar(yaml_parser_t *parser, int single) case 'P': /* PS (#x2029) */ *(string.pointer++) = '\xE2'; *(string.pointer++) = '\x80'; - *(string.pointer++) = '\xA8'; + *(string.pointer++) = '\xA9'; break; case 'x': @@ -3712,27 +3204,27 @@ yaml_parser_scan_flow_scalar(yaml_parser_t *parser, int single) goto error; } - FORWARD(parser); - FORWARD(parser); + SKIP(parser); + SKIP(parser); /* Consume an arbitrary escape code. */ if (code_length) { unsigned int value = 0; - int k; + size_t k; /* Scan the character value. */ - if (!UPDATE(parser, code_length)) goto error; + if (!CACHE(parser, code_length)) goto error; for (k = 0; k < code_length; k ++) { - if (!IS_HEX_AT(parser, k)) { + if (!IS_HEX_AT(parser->buffer, k)) { yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar", start_mark, "did not find expected hexdecimal number"); goto error; } - value = (value << 4) + AS_HEX_AT(parser, k); + value = (value << 4) + AS_HEX_AT(parser->buffer, k); } /* Check the value and write the character. */ @@ -3765,7 +3257,7 @@ yaml_parser_scan_flow_scalar(yaml_parser_t *parser, int single) /* Advance the pointer. */ for (k = 0; k < code_length; k ++) { - FORWARD(parser); + SKIP(parser); } } } @@ -3774,136 +3266,134 @@ yaml_parser_scan_flow_scalar(yaml_parser_t *parser, int single) { /* It is a non-escaped non-blank character. */ - COPY(parser, string); + if (!READ(parser, string)) goto error; } - if (!UPDATE(parser, 2)) goto error; - if (!RESIZE(parser, string)) goto error; + if (!CACHE(parser, 2)) goto error; } /* Check if we are at the end of the scalar. */ - if (CHECK(parser, single ? '\'' : '"')) + if (CHECK(parser->buffer, single ? '\'' : '"')) break; /* Consume blank characters. */ - if (!UPDATE(parser, 1)) goto error; + if (!CACHE(parser, 1)) goto error; - while (IS_BLANK(parser) || IS_BREAK(parser)) + while (IS_BLANK(parser->buffer) || IS_BREAK(parser->buffer)) { - if (IS_BLANK(parser)) + if (IS_BLANK(parser->buffer)) { /* Consume a space or a tab character. */ if (!leading_blanks) { - if (!RESIZE(parser, whitespaces)) goto error; - COPY(parser, whitespaces); + if (!READ(parser, whitespaces)) goto error; + } + else { + SKIP(parser); } } else { - if (!UPDATE(parser, 2)) goto error; + if (!CACHE(parser, 2)) goto error; /* Check if it is a first line break. */ if (!leading_blanks) { - yaml_parser_clear_string(parser, &whitespaces); - COPY_LINE(parser, leading_break); + CLEAR(parser, whitespaces); + if (!READ_LINE(parser, leading_break)) goto error; leading_blanks = 1; } else { - if (!RESIZE(parser, trailing_breaks)) goto error; - COPY_LINE(parser, trailing_breaks); + if (!READ_LINE(parser, trailing_breaks)) goto error; } } - if (!UPDATE(parser, 1)) goto error; + if (!CACHE(parser, 1)) goto error; } /* Join the whitespaces or fold line breaks. */ - if (!RESIZE(parser, string)) goto error; - if (leading_blanks) { /* Do we need to fold line breaks? */ - if (leading_break.buffer[0] == '\n') { - if (trailing_breaks.buffer[0] == '\0') { + if (leading_break.start[0] == '\n') { + if (trailing_breaks.start[0] == '\0') { + if (!STRING_EXTEND(parser, string)) goto error; *(string.pointer++) = ' '; } else { if (!JOIN(parser, string, trailing_breaks)) goto error; + CLEAR(parser, trailing_breaks); } - yaml_parser_clear_string(parser, &leading_break); + CLEAR(parser, leading_break); } else { if (!JOIN(parser, string, leading_break)) goto error; if (!JOIN(parser, string, trailing_breaks)) goto error; + CLEAR(parser, leading_break); + CLEAR(parser, trailing_breaks); } } else { if (!JOIN(parser, string, whitespaces)) goto error; + CLEAR(parser, whitespaces); } } /* Eat the right quote. */ - FORWARD(parser); + SKIP(parser); - end_mark = yaml_parser_get_mark(parser); + end_mark = parser->mark; /* Create a token. */ - token = yaml_scalar_token_new(string.buffer, string.pointer-string.buffer, + SCALAR_TOKEN_INIT(*token, string.start, string.pointer-string.start, single ? YAML_SINGLE_QUOTED_SCALAR_STYLE : YAML_DOUBLE_QUOTED_SCALAR_STYLE, start_mark, end_mark); - if (!token) { - parser->error = YAML_MEMORY_ERROR; - return 0; - } - yaml_free(leading_break.buffer); - yaml_free(trailing_breaks.buffer); - yaml_free(whitespaces.buffer); + STRING_DEL(parser, leading_break); + STRING_DEL(parser, trailing_breaks); + STRING_DEL(parser, whitespaces); - return token; + return 1; error: - yaml_free(string.buffer); - yaml_free(leading_break.buffer); - yaml_free(trailing_breaks.buffer); - yaml_free(whitespaces.buffer); + STRING_DEL(parser, string); + STRING_DEL(parser, leading_break); + STRING_DEL(parser, trailing_breaks); + STRING_DEL(parser, whitespaces); - return NULL; + return 0; } /* * Scan a plain scalar. */ -static yaml_token_t * -yaml_parser_scan_plain_scalar(yaml_parser_t *parser) +static int +yaml_parser_scan_plain_scalar(yaml_parser_t *parser, yaml_token_t *token) { yaml_mark_t start_mark; yaml_mark_t end_mark; - yaml_string_t string = yaml_parser_new_string(parser); - yaml_string_t leading_break = yaml_parser_new_string(parser); - yaml_string_t trailing_breaks = yaml_parser_new_string(parser); - yaml_string_t whitespaces = yaml_parser_new_string(parser); - yaml_token_t *token = NULL; + yaml_string_t string = NULL_STRING; + yaml_string_t leading_break = NULL_STRING; + yaml_string_t trailing_breaks = NULL_STRING; + yaml_string_t whitespaces = NULL_STRING; int leading_blanks = 0; int indent = parser->indent+1; - if (!string.buffer) goto error; - if (!leading_break.buffer) goto error; - if (!trailing_breaks.buffer) goto error; - if (!whitespaces.buffer) goto error; + if (!STRING_INIT(parser, string, INITIAL_STRING_SIZE)) goto error; + if (!STRING_INIT(parser, leading_break, INITIAL_STRING_SIZE)) goto error; + if (!STRING_INIT(parser, trailing_breaks, INITIAL_STRING_SIZE)) goto error; + if (!STRING_INIT(parser, whitespaces, INITIAL_STRING_SIZE)) goto error; - start_mark = yaml_parser_get_mark(parser); + start_mark = end_mark = parser->mark; /* Consume the content of the plain scalar. */ @@ -3911,29 +3401,31 @@ yaml_parser_scan_plain_scalar(yaml_parser_t *parser) { /* Check for a document indicator. */ - if (!UPDATE(parser, 4)) goto error; + if (!CACHE(parser, 4)) goto error; - if (parser->column == 0 && - ((CHECK_AT(parser, '-', 0) && - CHECK_AT(parser, '-', 1) && - CHECK_AT(parser, '-', 2)) || - (CHECK_AT(parser, '.', 0) && - CHECK_AT(parser, '.', 1) && - CHECK_AT(parser, '.', 2))) && - IS_BLANKZ_AT(parser, 3)) break; + if (parser->mark.column == 0 && + ((CHECK_AT(parser->buffer, '-', 0) && + CHECK_AT(parser->buffer, '-', 1) && + CHECK_AT(parser->buffer, '-', 2)) || + (CHECK_AT(parser->buffer, '.', 0) && + CHECK_AT(parser->buffer, '.', 1) && + CHECK_AT(parser->buffer, '.', 2))) && + IS_BLANKZ_AT(parser->buffer, 3)) break; /* Check for a comment. */ - if (CHECK(parser, '#')) + if (CHECK(parser->buffer, '#')) break; /* Consume non-blank characters. */ - while (!IS_BLANKZ(parser)) + while (!IS_BLANKZ(parser->buffer)) { - /* Check for 'x:x' in the flow context. */ + /* Check for 'x:x' in the flow context. TODO: Fix the test "spec-08-13". */ - if (parser->flow_level && CHECK(parser, ':') && !IS_BLANKZ_AT(parser, 1)) { + if (parser->flow_level + && CHECK(parser->buffer, ':') + && !IS_BLANKZ_AT(parser->buffer, 1)) { yaml_parser_set_scanner_error(parser, "while scanning a plain scalar", start_mark, "found unexpected ':'"); goto error; @@ -3941,36 +3433,38 @@ yaml_parser_scan_plain_scalar(yaml_parser_t *parser) /* Check for indicators that may end a plain scalar. */ - if ((CHECK(parser, ':') && IS_BLANKZ_AT(parser, 1)) || - (parser->flow_level && - (CHECK(parser, ',') || CHECK(parser, ':') || - CHECK(parser, '?') || CHECK(parser, '[') || - CHECK(parser, ']') || CHECK(parser, '{') || - CHECK(parser, '}')))) + if ((CHECK(parser->buffer, ':') && IS_BLANKZ_AT(parser->buffer, 1)) + || (parser->flow_level && + (CHECK(parser->buffer, ',') || CHECK(parser->buffer, ':') + || CHECK(parser->buffer, '?') || CHECK(parser->buffer, '[') + || CHECK(parser->buffer, ']') || CHECK(parser->buffer, '{') + || CHECK(parser->buffer, '}')))) break; /* Check if we need to join whitespaces and breaks. */ - if (leading_blanks || whitespaces.buffer != whitespaces.pointer) + if (leading_blanks || whitespaces.start != whitespaces.pointer) { - if (!RESIZE(parser, string)) goto error; - if (leading_blanks) { /* Do we need to fold line breaks? */ - if (leading_break.buffer[0] == '\n') { - if (trailing_breaks.buffer[0] == '\0') { + if (leading_break.start[0] == '\n') { + if (trailing_breaks.start[0] == '\0') { + if (!STRING_EXTEND(parser, string)) goto error; *(string.pointer++) = ' '; } else { if (!JOIN(parser, string, trailing_breaks)) goto error; + CLEAR(parser, trailing_breaks); } - yaml_parser_clear_string(parser, &leading_break); + CLEAR(parser, leading_break); } else { if (!JOIN(parser, string, leading_break)) goto error; if (!JOIN(parser, string, trailing_breaks)) goto error; + CLEAR(parser, leading_break); + CLEAR(parser, trailing_breaks); } leading_blanks = 0; @@ -3978,83 +3472,80 @@ yaml_parser_scan_plain_scalar(yaml_parser_t *parser) else { if (!JOIN(parser, string, whitespaces)) goto error; + CLEAR(parser, whitespaces); } } /* Copy the character. */ - if (!RESIZE(parser, string)) goto error; - - COPY(parser, string); + if (!READ(parser, string)) goto error; - end_mark = yaml_parser_get_mark(parser); + end_mark = parser->mark; - if (!UPDATE(parser, 2)) goto error; + if (!CACHE(parser, 2)) goto error; } /* Is it the end? */ - if (!(IS_BLANK(parser) || IS_BREAK(parser))) + if (!(IS_BLANK(parser->buffer) || IS_BREAK(parser->buffer))) break; /* Consume blank characters. */ - if (!UPDATE(parser, 1)) goto error; + if (!CACHE(parser, 1)) goto error; - while (IS_BLANK(parser) || IS_BREAK(parser)) + while (IS_BLANK(parser->buffer) || IS_BREAK(parser->buffer)) { - if (IS_BLANK(parser)) + if (IS_BLANK(parser->buffer)) { /* Check for tab character that abuse intendation. */ - if (leading_blanks && parser->column < indent && IS_TAB(parser)) { + if (leading_blanks && (int)parser->mark.column < indent + && IS_TAB(parser->buffer)) { yaml_parser_set_scanner_error(parser, "while scanning a plain scalar", start_mark, "found a tab character that violate intendation"); - break; + goto error; } /* Consume a space or a tab character. */ if (!leading_blanks) { - if (!RESIZE(parser, whitespaces)) goto error; - COPY(parser, whitespaces); + if (!READ(parser, whitespaces)) goto error; + } + else { + SKIP(parser); } } else { - if (!UPDATE(parser, 2)) goto error; + if (!CACHE(parser, 2)) goto error; /* Check if it is a first line break. */ if (!leading_blanks) { - yaml_parser_clear_string(parser, &whitespaces); - COPY_LINE(parser, leading_break); + CLEAR(parser, whitespaces); + if (!READ_LINE(parser, leading_break)) goto error; leading_blanks = 1; } else { - if (!RESIZE(parser, trailing_breaks)) goto error; - COPY_LINE(parser, trailing_breaks); + if (!READ_LINE(parser, trailing_breaks)) goto error; } } - if (!UPDATE(parser, 1)) goto error; + if (!CACHE(parser, 1)) goto error; } /* Check intendation level. */ - if (parser->column < indent) + if (!parser->flow_level && (int)parser->mark.column < indent) break; } /* Create a token. */ - token = yaml_scalar_token_new(string.buffer, string.pointer-string.buffer, + SCALAR_TOKEN_INIT(*token, string.start, string.pointer-string.start, YAML_PLAIN_SCALAR_STYLE, start_mark, end_mark); - if (!token) { - parser->error = YAML_MEMORY_ERROR; - return 0; - } /* Note that we change the 'simple_key_allowed' flag. */ @@ -4062,18 +3553,18 @@ yaml_parser_scan_plain_scalar(yaml_parser_t *parser) parser->simple_key_allowed = 1; } - yaml_free(leading_break.buffer); - yaml_free(trailing_breaks.buffer); - yaml_free(whitespaces.buffer); + STRING_DEL(parser, leading_break); + STRING_DEL(parser, trailing_breaks); + STRING_DEL(parser, whitespaces); - return token; + return 1; error: - yaml_free(string.buffer); - yaml_free(leading_break.buffer); - yaml_free(trailing_breaks.buffer); - yaml_free(whitespaces.buffer); + STRING_DEL(parser, string); + STRING_DEL(parser, leading_break); + STRING_DEL(parser, trailing_breaks); + STRING_DEL(parser, whitespaces); - return NULL; + return 0; }