source: libyaml/trunk/src/scanner.c @ 187

Revision 187, 78.8 KB checked in by xi, 9 years ago (diff)

Implement scanners for directives, anchors, and tags.

Line 
1
2/*
3 * Introduction
4 * ************
5 *
6 * The following notes assume that you are familiar with the YAML specification
7 * (http://yaml.org/spec/cvs/current.html).  We mostly follow it, although in
8 * some cases we are less restrictive that it requires.
9 *
10 * The process of transforming a YAML stream into a sequence of events is
11 * divided on two steps: Scanning and Parsing.
12 *
13 * The Scanner transforms the input stream into a sequence of tokens, while the
14 * parser transform the sequence of tokens produced by the Scanner into a
15 * sequence of parsing events.
16 *
17 * The Scanner is rather clever and complicated. The Parser, on the contrary,
18 * is a straightforward implementation of a recursive-descendant parser (or,
19 * LL(1) parser, as it is usually called).
20 *
21 * Actually there are two issues of Scanning that might be called "clever", the
22 * rest is quite straightforward.  The issues are "block collection start" and
23 * "simple keys".  Both issues are explained below in details.
24 *
25 * Here the Scanning step is explained and implemented.  We start with the list
26 * of all the tokens produced by the Scanner together with short descriptions.
27 *
28 * Now, tokens:
29 *
30 *      STREAM-START(encoding)          # The stream start.
31 *      STREAM-END                      # The stream end.
32 *      VERSION-DIRECTIVE(major,minor)  # The '%YAML' directive.
33 *      TAG-DIRECTIVE(handle,prefix)    # The '%TAG' directive.
34 *      DOCUMENT-START                  # '---'
35 *      DOCUMENT-END                    # '...'
36 *      BLOCK-SEQUENCE-START            # Indentation increase denoting a block
37 *      BLOCK-MAPPING-START             # sequence or a block mapping.
38 *      BLOCK-END                       # Indentation decrease.
39 *      FLOW-SEQUENCE-START             # '['
40 *      FLOW-SEQUENCE-END               # ']'
41 *      BLOCK-SEQUENCE-START            # '{'
42 *      BLOCK-SEQUENCE-END              # '}'
43 *      BLOCK-ENTRY                     # '-'
44 *      FLOW-ENTRY                      # ','
45 *      KEY                             # '?' or nothing (simple keys).
46 *      VALUE                           # ':'
47 *      ALIAS(anchor)                   # '*anchor'
48 *      ANCHOR(anchor)                  # '&anchor'
49 *      TAG(handle,suffix)              # '!handle!suffix'
50 *      SCALAR(value,style)             # A scalar.
51 *
52 * The following two tokens are "virtual" tokens denoting the beginning and the
53 * end of the stream:
54 *
55 *      STREAM-START(encoding)
56 *      STREAM-END
57 *
58 * We pass the information about the input stream encoding with the
59 * STREAM-START token.
60 *
61 * The next two tokens are responsible for tags:
62 *
63 *      VERSION-DIRECTIVE(major,minor)
64 *      TAG-DIRECTIVE(handle,prefix)
65 *
66 * Example:
67 *
68 *      %YAML   1.1
69 *      %TAG    !   !foo
70 *      %TAG    !yaml!  tag:yaml.org,2002:
71 *      ---
72 *
73 * The correspoding sequence of tokens:
74 *
75 *      STREAM-START(utf-8)
76 *      VERSION-DIRECTIVE(1,1)
77 *      TAG-DIRECTIVE("!","!foo")
78 *      TAG-DIRECTIVE("!yaml","tag:yaml.org,2002:")
79 *      DOCUMENT-START
80 *      STREAM-END
81 *
82 * Note that the VERSION-DIRECTIVE and TAG-DIRECTIVE tokens occupy a whole
83 * line.
84 *
85 * The document start and end indicators are represented by:
86 *
87 *      DOCUMENT-START
88 *      DOCUMENT-END
89 *
90 * Note that if a YAML stream contains an implicit document (without '---'
91 * and '...' indicators), no DOCUMENT-START and DOCUMENT-END tokens will be
92 * produced.
93 *
94 * In the following examples, we present whole documents together with the
95 * produced tokens.
96 *
97 *      1. An implicit document:
98 *
99 *          'a scalar'
100 *
101 *      Tokens:
102 *
103 *          STREAM-START(utf-8)
104 *          SCALAR("a scalar",single-quoted)
105 *          STREAM-END
106 *
107 *      2. An explicit document:
108 *
109 *          ---
110 *          'a scalar'
111 *          ...
112 *
113 *      Tokens:
114 *
115 *          STREAM-START(utf-8)
116 *          DOCUMENT-START
117 *          SCALAR("a scalar",single-quoted)
118 *          DOCUMENT-END
119 *          STREAM-END
120 *
121 *      3. Several documents in a stream:
122 *
123 *          'a scalar'
124 *          ---
125 *          'another scalar'
126 *          ---
127 *          'yet another scalar'
128 *
129 *      Tokens:
130 *
131 *          STREAM-START(utf-8)
132 *          SCALAR("a scalar",single-quoted)
133 *          DOCUMENT-START
134 *          SCALAR("another scalar",single-quoted)
135 *          DOCUMENT-START
136 *          SCALAR("yet another scalar",single-quoted)
137 *          STREAM-END
138 *
139 * We have already introduced the SCALAR token above.  The following tokens are
140 * used to describe aliases, anchors, tag, and scalars:
141 *
142 *      ALIAS(anchor)
143 *      ANCHOR(anchor)
144 *      TAG(handle,suffix)
145 *      SCALAR(value,style)
146 *
147 * The following series of examples illustrate the usage of these tokens:
148 *
149 *      1. A recursive sequence:
150 *
151 *          &A [ *A ]
152 *
153 *      Tokens:
154 *
155 *          STREAM-START(utf-8)
156 *          ANCHOR("A")
157 *          FLOW-SEQUENCE-START
158 *          ALIAS("A")
159 *          FLOW-SEQUENCE-END
160 *          STREAM-END
161 *
162 *      2. A tagged scalar:
163 *
164 *          !!float "3.14"  # A good approximation.
165 *
166 *      Tokens:
167 *
168 *          STREAM-START(utf-8)
169 *          TAG("!!","float")
170 *          SCALAR("3.14",double-quoted)
171 *          STREAM-END
172 *
173 *      3. Various scalar styles:
174 *
175 *          --- # Implicit empty plain scalars do not produce tokens.
176 *          --- a plain scalar
177 *          --- 'a single-quoted scalar'
178 *          --- "a double-quoted scalar"
179 *          --- |-
180 *            a literal scalar
181 *          --- >-
182 *            a folded
183 *            scalar
184 *
185 *      Tokens:
186 *
187 *          STREAM-START(utf-8)
188 *          DOCUMENT-START
189 *          DOCUMENT-START
190 *          SCALAR("a plain scalar",plain)
191 *          DOCUMENT-START
192 *          SCALAR("a single-quoted scalar",single-quoted)
193 *          DOCUMENT-START
194 *          SCALAR("a double-quoted scalar",double-quoted)
195 *          DOCUMENT-START
196 *          SCALAR("a literal scalar",literal)
197 *          DOCUMENT-START
198 *          SCALAR("a folded scalar",folded)
199 *          STREAM-END
200 *
201 * Now it's time to review collection-related tokens. We will start with
202 * flow collections:
203 *
204 *      FLOW-SEQUENCE-START
205 *      FLOW-SEQUENCE-END
206 *      FLOW-MAPPING-START
207 *      FLOW-MAPPING-END
208 *      FLOW-ENTRY
209 *      KEY
210 *      VALUE
211 *
212 * The tokens FLOW-SEQUENCE-START, FLOW-SEQUENCE-END, FLOW-MAPPING-START, and
213 * FLOW-MAPPING-END represent the indicators '[', ']', '{', and '}'
214 * correspondingly.  FLOW-ENTRY represent the ',' indicator.  Finally the
215 * indicators '?' and ':', which are used for denoting mapping keys and values,
216 * are represented by the KEY and VALUE tokens.
217 *
218 * The following examples show flow collections:
219 *
220 *      1. A flow sequence:
221 *
222 *          [item 1, item 2, item 3]
223 *
224 *      Tokens:
225 *
226 *          STREAM-START(utf-8)
227 *          FLOW-SEQUENCE-START
228 *          SCALAR("item 1",plain)
229 *          FLOW-ENTRY
230 *          SCALAR("item 2",plain)
231 *          FLOW-ENTRY
232 *          SCALAR("item 3",plain)
233 *          FLOW-SEQUENCE-END
234 *          STREAM-END
235 *
236 *      2. A flow mapping:
237 *
238 *          {
239 *              a simple key: a value,  # Note that the KEY token is produced.
240 *              ? a complex key: another value,
241 *          }
242 *
243 *      Tokens:
244 *
245 *          STREAM-START(utf-8)
246 *          FLOW-MAPPING-START
247 *          KEY
248 *          SCALAR("a simple key",plain)
249 *          VALUE
250 *          SCALAR("a value",plain)
251 *          FLOW-ENTRY
252 *          KEY
253 *          SCALAR("a complex key",plain)
254 *          VALUE
255 *          SCALAR("another value",plain)
256 *          FLOW-ENTRY
257 *          FLOW-MAPPING-END
258 *          STREAM-END
259 *
260 * A simple key is a key which is not denoted by the '?' indicator.  Note that
261 * the Scanner still produce the KEY token whenever it encounters a simple key.
262 *
263 * For scanning block collections, the following tokens are used (note that we
264 * repeat KEY and VALUE here):
265 *
266 *      BLOCK-SEQUENCE-START
267 *      BLOCK-MAPPING-START
268 *      BLOCK-END
269 *      BLOCK-ENTRY
270 *      KEY
271 *      VALUE
272 *
273 * The tokens BLOCK-SEQUENCE-START and BLOCK-MAPPING-START denote indentation
274 * increase that precedes a block collection (cf. the INDENT token in Python).
275 * The token BLOCK-END denote indentation decrease that ends a block collection
276 * (cf. the DEDENT token in Python).  However YAML has some syntax pecularities
277 * that makes detections of these tokens more complex.
278 *
279 * The tokens BLOCK-ENTRY, KEY, and VALUE are used to represent the indicators
280 * '-', '?', and ':' correspondingly.
281 *
282 * The following examples show how the tokens BLOCK-SEQUENCE-START,
283 * BLOCK-MAPPING-START, and BLOCK-END are emitted by the Scanner:
284 *
285 *      1. Block sequences:
286 *
287 *          - item 1
288 *          - item 2
289 *          -
290 *            - item 3.1
291 *            - item 3.2
292 *          -
293 *            key 1: value 1
294 *            key 2: value 2
295 *
296 *      Tokens:
297 *
298 *          STREAM-START(utf-8)
299 *          BLOCK-SEQUENCE-START
300 *          BLOCK-ENTRY
301 *          SCALAR("item 1",plain)
302 *          BLOCK-ENTRY
303 *          SCALAR("item 2",plain)
304 *          BLOCK-ENTRY
305 *          BLOCK-SEQUENCE-START
306 *          BLOCK-ENTRY
307 *          SCALAR("item 3.1",plain)
308 *          BLOCK-ENTRY
309 *          SCALAR("item 3.2",plain)
310 *          BLOCK-END
311 *          BLOCK-ENTRY
312 *          BLOCK-MAPPING-START
313 *          KEY
314 *          SCALAR("key 1",plain)
315 *          VALUE
316 *          SCALAR("value 1",plain)
317 *          KEY
318 *          SCALAR("key 2",plain)
319 *          VALUE
320 *          SCALAR("value 2",plain)
321 *          BLOCK-END
322 *          BLOCK-END
323 *          STREAM-END
324 *
325 *      2. Block mappings:
326 *
327 *          a simple key: a value   # The KEY token is produced here.
328 *          ? a complex key
329 *          : another value
330 *          a mapping:
331 *            key 1: value 1
332 *            key 2: value 2
333 *          a sequence:
334 *            - item 1
335 *            - item 2
336 *
337 *      Tokens:
338 *
339 *          STREAM-START(utf-8)
340 *          BLOCK-MAPPING-START
341 *          KEY
342 *          SCALAR("a simple key",plain)
343 *          VALUE
344 *          SCALAR("a value",plain)
345 *          KEY
346 *          SCALAR("a complex key",plain)
347 *          VALUE
348 *          SCALAR("another value",plain)
349 *          KEY
350 *          SCALAR("a mapping",plain)
351 *          BLOCK-MAPPING-START
352 *          KEY
353 *          SCALAR("key 1",plain)
354 *          VALUE
355 *          SCALAR("value 1",plain)
356 *          KEY
357 *          SCALAR("key 2",plain)
358 *          VALUE
359 *          SCALAR("value 2",plain)
360 *          BLOCK-END
361 *          KEY
362 *          SCALAR("a sequence",plain)
363 *          VALUE
364 *          BLOCK-SEQUENCE-START
365 *          BLOCK-ENTRY
366 *          SCALAR("item 1",plain)
367 *          BLOCK-ENTRY
368 *          SCALAR("item 2",plain)
369 *          BLOCK-END
370 *          BLOCK-END
371 *          STREAM-END
372 *
373 * YAML does not always require to start a new block collection from a new
374 * line.  If the current line contains only '-', '?', and ':' indicators, a new
375 * block collection may start at the current line.  The following examples
376 * illustrate this case:
377 *
378 *      1. Collections in a sequence:
379 *
380 *          - - item 1
381 *            - item 2
382 *          - key 1: value 1
383 *            key 2: value 2
384 *          - ? complex key
385 *            : complex value
386 *
387 *      Tokens:
388 *
389 *          STREAM-START(utf-8)
390 *          BLOCK-SEQUENCE-START
391 *          BLOCK-ENTRY
392 *          BLOCK-SEQUENCE-START
393 *          BLOCK-ENTRY
394 *          SCALAR("item 1",plain)
395 *          BLOCK-ENTRY
396 *          SCALAR("item 2",plain)
397 *          BLOCK-END
398 *          BLOCK-ENTRY
399 *          BLOCK-MAPPING-START
400 *          KEY
401 *          SCALAR("key 1",plain)
402 *          VALUE
403 *          SCALAR("value 1",plain)
404 *          KEY
405 *          SCALAR("key 2",plain)
406 *          VALUE
407 *          SCALAR("value 2",plain)
408 *          BLOCK-END
409 *          BLOCK-ENTRY
410 *          BLOCK-MAPPING-START
411 *          KEY
412 *          SCALAR("complex key")
413 *          VALUE
414 *          SCALAR("complex value")
415 *          BLOCK-END
416 *          BLOCK-END
417 *          STREAM-END
418 *
419 *      2. Collections in a mapping:
420 *
421 *          ? a sequence
422 *          : - item 1
423 *            - item 2
424 *          ? a mapping
425 *          : key 1: value 1
426 *            key 2: value 2
427 *
428 *      Tokens:
429 *
430 *          STREAM-START(utf-8)
431 *          BLOCK-MAPPING-START
432 *          KEY
433 *          SCALAR("a sequence",plain)
434 *          VALUE
435 *          BLOCK-SEQUENCE-START
436 *          BLOCK-ENTRY
437 *          SCALAR("item 1",plain)
438 *          BLOCK-ENTRY
439 *          SCALAR("item 2",plain)
440 *          BLOCK-END
441 *          KEY
442 *          SCALAR("a mapping",plain)
443 *          VALUE
444 *          BLOCK-MAPPING-START
445 *          KEY
446 *          SCALAR("key 1",plain)
447 *          VALUE
448 *          SCALAR("value 1",plain)
449 *          KEY
450 *          SCALAR("key 2",plain)
451 *          VALUE
452 *          SCALAR("value 2",plain)
453 *          BLOCK-END
454 *          BLOCK-END
455 *          STREAM-END
456 *
457 * YAML also permits non-indented sequences if they are included into a block
458 * mapping.  In this case, the token BLOCK-SEQUENCE-START is not produced:
459 *
460 *      key:
461 *      - item 1    # BLOCK-SEQUENCE-START is NOT produced here.
462 *      - item 2
463 *
464 * Tokens:
465 *
466 *      STREAM-START(utf-8)
467 *      BLOCK-MAPPING-START
468 *      KEY
469 *      SCALAR("key",plain)
470 *      VALUE
471 *      BLOCK-ENTRY
472 *      SCALAR("item 1",plain)
473 *      BLOCK-ENTRY
474 *      SCALAR("item 2",plain)
475 *      BLOCK-END
476 */
477
478#if HAVE_CONFIG_H
479#include <config.h>
480#endif
481
482#include <yaml/yaml.h>
483
484#include <assert.h>
485
486/*
487 * Ensure that the buffer contains the required number of characters.
488 * Return 1 on success, 0 on failure (reader error or memory error).
489 */
490
491#define UPDATE(parser,length)   \
492    (parser->unread >= (length) \
493        ? 1                     \
494        : yaml_parser_update_buffer(parser, (length)))
495
496/*
497 * Check the octet at the specified position.
498 */
499
500#define CHECK_AT(parser,octet,offset)   \
501    (parser->pointer[offset] == (yaml_char_t)(octet))
502
503/*
504 * Check the current octet in the buffer.
505 */
506
507#define CHECK(parser,octet) CHECK_AT(parser,(octet),0)
508
509/*
510 * Check if the character at the specified position is an alphabetical
511 * character, a digit, '_', or '-'.
512 */
513
514#define IS_ALPHA_AT(parser,offset)  \
515     ((parser->pointer[offset] >= (yaml_char_t) '0' &&      \
516       parser->pointer[offset] <= (yaml_char_t) '9') ||     \
517      (parser->pointer[offset] >= (yaml_char_t) 'A' &&      \
518       parser->pointer[offset] <= (yaml_char_t) 'Z') ||     \
519      (parser->pointer[offset] >= (yaml_char_t) 'a' &&      \
520       parser->pointer[offset] <= (yaml_char_t) 'z') ||     \
521      parser->pointer[offset] == '_' ||                     \
522      parser->pointer[offset] == '-')
523
524#define IS_ALPHA(parser)    IS_ALPHA_AT(parser,0)
525
526/*
527 * Check if the character at the specified position is a digit.
528 */
529
530#define IS_DIGIT_AT(parser,offset)  \
531     ((parser->pointer[offset] >= (yaml_char_t) '0' &&      \
532       parser->pointer[offset] <= (yaml_char_t) '9'))
533
534#define IS_DIGIT(parser)    IS_DIGIT_AT(parser,0)
535
536/*
537 * Get the value of a digit.
538 */
539
540#define AS_DIGIT_AT(parser,offset)  \
541     (parser->pointer[offset] - (yaml_char_t) '0')
542
543#define AS_DIGIT(parser)    AS_DIGIT_AT(parser,0)
544
545/*
546 * Check if the character at the specified position is a hex-digit.
547 */
548
549#define IS_HEX_AT(parser,offset)    \
550     ((parser->pointer[offset] >= (yaml_char_t) '0' &&      \
551       parser->pointer[offset] <= (yaml_char_t) '9') ||     \
552      (parser->pointer[offset] >= (yaml_char_t) 'A' &&      \
553       parser->pointer[offset] <= (yaml_char_t) 'F') ||     \
554      (parser->pointer[offset] >= (yaml_char_t) 'a' &&      \
555       parser->pointer[offset] <= (yaml_char_t) 'f'))
556
557#define IS_HEX(parser)    IS_HEX_AT(parser,0)
558
559/*
560 * Get the value of a hex-digit.
561 */
562
563#define AS_HEX_AT(parser,offset)    \
564      ((parser->pointer[offset] >= (yaml_char_t) 'A' &&     \
565        parser->pointer[offset] <= (yaml_char_t) 'F') ?     \
566       (parser->pointer[offset] - (yaml_char_t) 'A' + 10) : \
567       (parser->pointer[offset] >= (yaml_char_t) 'a' &&     \
568        parser->pointer[offset] <= (yaml_char_t) 'f') ?     \
569       (parser->pointer[offset] - (yaml_char_t) 'a' + 10) : \
570       (parser->pointer[offset] - (yaml_char_t) '0'))
571 
572#define AS_HEX(parser)  AS_HEX_AT(parser,0)
573 
574/*
575 * Check if the character at the specified position is NUL.
576 */
577
578#define IS_Z_AT(parser,offset)    CHECK_AT(parser,'\0',(offset))
579
580#define IS_Z(parser)    IS_Z_AT(parser,0)
581
582/*
583 * Check if the character at the specified position is BOM.
584 */
585
586#define IS_BOM_AT(parser,offset)                                    \
587     (CHECK_AT(parser,'\xEF',(offset))                              \
588      && CHECK_AT(parser,'\xBB',(offset)+1)                         \
589      && CHECK_AT(parser,'\xBF',(offset)+1))    /* BOM (#xFEFF) */
590
591#define IS_BOM(parser)  IS_BOM_AT(parser,0)
592
593/*
594 * Check if the character at the specified position is space.
595 */
596
597#define IS_SPACE_AT(parser,offset)  CHECK_AT(parser,' ',(offset))
598
599#define IS_SPACE(parser)    IS_SPACE_AT(parser,0)
600
601/*
602 * Check if the character at the specified position is tab.
603 */
604
605#define IS_TAB_AT(parser,offset)    CHECK_AT(parser,'\t',(offset))
606
607#define IS_TAB(parser)  IS_TAB_AT(parser,0)
608
609/*
610 * Check if the character at the specified position is blank (space or tab).
611 */
612
613#define IS_BLANK_AT(parser,offset)  \
614    (IS_SPACE_AT(parser,(offset)) || IS_TAB_AT(parser,(offset)))
615
616#define IS_BLANK(parser)    IS_BLANK_AT(parser,0)
617
618/*
619 * Check if the character at the specified position is a line break.
620 */
621
622#define IS_BREAK_AT(parser,offset)                                      \
623    (CHECK_AT(parser,'\r',(offset))                 /* CR (#xD)*/       \
624     || CHECK_AT(parser,'\n',(offset))              /* LF (#xA) */      \
625     || (CHECK_AT(parser,'\xC2',(offset))                               \
626         && CHECK_AT(parser,'\x85',(offset)+1))     /* NEL (#x85) */    \
627     || (CHECK_AT(parser,'\xE2',(offset))                               \
628         && CHECK_AT(parser,'\x80',(offset)+1)                          \
629         && CHECK_AT(parser,'\xA8',(offset)+2))     /* LS (#x2028) */   \
630     || (CHECK_AT(parser,'\xE2',(offset))                               \
631         && CHECK_AT(parser,'\x80',(offset)+1)                          \
632         && CHECK_AT(parser,'\xA9',(offset)+2)))    /* LS (#x2029) */
633
634#define IS_BREAK(parser)    IS_BREAK_AT(parser,0)
635
636#define IS_CRLF_AT(parser,offset) \
637     (CHECK_AT(parser,'\r',(offset)) && CHECK_AT(parser,'\n',(offset)+1))
638
639#define IS_CRLF(parser) IS_CRLF_AT(parser,0)
640
641/*
642 * Check if the character is a line break or NUL.
643 */
644
645#define IS_BREAKZ_AT(parser,offset) \
646    (IS_BREAK_AT(parser,(offset)) || IS_Z_AT(parser,(offset)))
647
648#define IS_BREAKZ(parser)   IS_BREAKZ_AT(parser,0)
649
650/*
651 * Check if the character is a line break, space, or NUL.
652 */
653
654#define IS_SPACEZ_AT(parser,offset) \
655    (IS_SPACE_AT(parser,(offset)) || IS_BREAKZ_AT(parser,(offset)))
656
657#define IS_SPACEZ(parser)   IS_SPACEZ_AT(parser,0)
658
659/*
660 * Check if the character is a line break, space, tab, or NUL.
661 */
662
663#define IS_BLANKZ_AT(parser,offset) \
664    (IS_BLANK_AT(parser,(offset)) || IS_BREAKZ_AT(parser,(offset)))
665
666#define IS_BLANKZ(parser)   IS_BLANKZ_AT(parser,0)
667
668/*
669 * Determine the width of the character.
670 */
671
672#define WIDTH_AT(parser,offset)                         \
673     ((parser->pointer[(offset)] & 0x80) == 0x00 ? 1 :  \
674      (parser->pointer[(offset)] & 0xE0) == 0xC0 ? 2 :  \
675      (parser->pointer[(offset)] & 0xF0) == 0xE0 ? 3 :  \
676      (parser->pointer[(offset)] & 0xF8) == 0xF0 ? 4 : 0)
677
678#define WIDTH(parser)   WIDTH_AT(parser,0)
679
680/*
681 * Advance the buffer pointer.
682 */
683
684#define FORWARD(parser)                             \
685     (parser->index ++,                             \
686      parser->column ++,                            \
687      parser->unread --,                            \
688      parser->pointer += WIDTH(parser))
689
690#define FORWARD_LINE(parser)                        \
691     (IS_CRLF(parser) ?                             \
692      (parser->index += 2,                          \
693       parser->column = 0,                          \
694       parser->unread -= 2,                         \
695       parser->pointer += 2) :                      \
696      IS_BREAK(parser) ?                            \
697      (parser->index ++,                            \
698       parser->column = 0,                          \
699       parser->unread --,                           \
700       parser->pointer += WIDTH(parser)) : 0)
701
702/*
703 * Resize a string if needed.
704 */
705
706#define RESIZE(parser,string)   \
707    (string.pointer-string.buffer+5 < string.size ? 1 :  \
708     yaml_parser_resize_string(parser, &string))
709
710/*
711 * Copy a character to a string buffer and advance pointers.
712 */
713
714#define COPY(parser,string)     \
715     (((*parser->pointer & 0x80) == 0x00 ?                  \
716       (*(string.pointer++) = *(parser->pointer++)) :       \
717       (*parser->pointer & 0xE0) == 0xC0 ?                  \
718       (*(string.pointer++) = *(parser->pointer++),         \
719        *(string.pointer++) = *(parser->pointer++)) :       \
720       (*parser->pointer & 0xF0) == 0xE0 ?                  \
721       (*(string.pointer++) = *(parser->pointer++),         \
722        *(string.pointer++) = *(parser->pointer++),         \
723        *(string.pointer++) = *(parser->pointer++)) :       \
724       (*parser->pointer & 0xF8) == 0xF0 ?                  \
725       (*(string.pointer++) = *(parser->pointer++),         \
726        *(string.pointer++) = *(parser->pointer++),         \
727        *(string.pointer++) = *(parser->pointer++),         \
728        *(string.pointer++) = *(parser->pointer++)) : 0),   \
729      parser->index ++,                                     \
730      parser->column ++,                                    \
731      parser->unread --)
732   
733
734/*
735 * Public API declarations.
736 */
737
738YAML_DECLARE(yaml_token_t *)
739yaml_parser_get_token(yaml_parser_t *parser);
740
741YAML_DECLARE(yaml_token_t *)
742yaml_parser_peek_token(yaml_parser_t *parser);
743
744/*
745 * Error handling.
746 */
747
748static int
749yaml_parser_set_scanner_error(yaml_parser_t *parser, const char *context,
750        yaml_mark_t context_mark, const char *problem);
751
752static yaml_mark_t
753yaml_parser_get_mark(yaml_parser_t *parser);
754
755/*
756 * Buffers and lists.
757 */
758
759typedef struct {
760    yaml_char_t *buffer;
761    yaml_char_t *pointer;
762    size_t size;
763} yaml_string_t;
764
765static yaml_string_t
766yaml_parser_new_string(yaml_parser_t *parser);
767
768static int
769yaml_parser_resize_string(yaml_parser_t *parser, yaml_string_t *string);
770
771static int
772yaml_parser_resize_list(yaml_parser_t *parser, void **buffer, size_t *size,
773        size_t item_size);
774
775/*
776 * High-level token API.
777 */
778
779static int
780yaml_parser_fetch_more_tokens(yaml_parser_t *parser);
781
782static int
783yaml_parser_fetch_next_token(yaml_parser_t *parser);
784
785/*
786 * Potential simple keys.
787 */
788
789static int
790yaml_parser_stale_simple_keys(yaml_parser_t *parser);
791
792static int
793yaml_parser_save_simple_key(yaml_parser_t *parser);
794
795static int
796yaml_parser_remove_simple_key(yaml_parser_t *parser);
797
798static int
799yaml_parser_increase_flow_level(yaml_parser_t *parser);
800
801static int
802yaml_parser_decrease_flow_level(yaml_parser_t *parser);
803
804/*
805 * Token manipulation.
806 */
807
808static int
809yaml_parser_append_token(yaml_parser_t *parser, yaml_token_t *token);
810
811static int
812yaml_parser_insert_token(yaml_parser_t *parser,
813        int number, yaml_token_t *token);
814
815/*
816 * Indentation treatment.
817 */
818
819static int
820yaml_parser_roll_indent(yaml_parser_t *parser, int column,
821        int number, yaml_token_type_t type, yaml_mark_t mark);
822
823static int
824yaml_parser_unroll_indent(yaml_parser_t *parser, int column);
825
826/*
827 * Token fetchers.
828 */
829
830static int
831yaml_parser_fetch_stream_start(yaml_parser_t *parser);
832
833static int
834yaml_parser_fetch_stream_end(yaml_parser_t *parser);
835
836static int
837yaml_parser_fetch_directive(yaml_parser_t *parser);
838
839static int
840yaml_parser_fetch_document_indicator(yaml_parser_t *parser,
841        yaml_token_type_t type);
842
843static int
844yaml_parser_fetch_flow_collection_start(yaml_parser_t *parser,
845        yaml_token_type_t type);
846
847static int
848yaml_parser_fetch_flow_collection_end(yaml_parser_t *parser,
849        yaml_token_type_t type);
850
851static int
852yaml_parser_fetch_flow_entry(yaml_parser_t *parser);
853
854static int
855yaml_parser_fetch_block_entry(yaml_parser_t *parser);
856
857static int
858yaml_parser_fetch_key(yaml_parser_t *parser);
859
860static int
861yaml_parser_fetch_value(yaml_parser_t *parser);
862
863static int
864yaml_parser_fetch_anchor(yaml_parser_t *parser, yaml_token_type_t type);
865
866static int
867yaml_parser_fetch_tag(yaml_parser_t *parser);
868
869static int
870yaml_parser_fetch_block_scalar(yaml_parser_t *parser, int literal);
871
872static int
873yaml_parser_fetch_flow_scalar(yaml_parser_t *parser, int single);
874
875static int
876yaml_parser_fetch_plain_scalar(yaml_parser_t *parser);
877
878/*
879 * Token scanners.
880 */
881
882static int
883yaml_parser_scan_to_next_token(yaml_parser_t *parser);
884
885static yaml_token_t *
886yaml_parser_scan_directive(yaml_parser_t *parser);
887
888static int
889yaml_parser_scan_directive_name(yaml_parser_t *parser,
890        yaml_mark_t start_mark, yaml_char_t **name);
891
892static int
893yaml_parser_scan_version_directive_value(yaml_parser_t *parser,
894        yaml_mark_t start_mark, int *major, int *minor);
895
896static int
897yaml_parser_scan_version_directive_number(yaml_parser_t *parser,
898        yaml_mark_t start_mark, int *number);
899
900static int
901yaml_parser_scan_tag_directive_value(yaml_parser_t *parser,
902        yaml_mark_t mark, yaml_char_t **handle, yaml_char_t **prefix);
903
904static yaml_token_t *
905yaml_parser_scan_anchor(yaml_parser_t *parser,
906        yaml_token_type_t type);
907
908static yaml_token_t *
909yaml_parser_scan_tag(yaml_parser_t *parser);
910
911static int
912yaml_parser_scan_tag_handle(yaml_parser_t *parser, int directive,
913        yaml_mark_t start_mark, yaml_char_t **handle);
914
915static int
916yaml_parser_scan_tag_uri(yaml_parser_t *parser, int directive,
917        yaml_char_t *head, yaml_mark_t start_mark, yaml_char_t **uri);
918
919static int
920yaml_parser_scan_uri_escapes(yaml_parser_t *parser, int directive,
921        yaml_mark_t start_mark, yaml_string_t *string);
922
923static yaml_token_t *
924yaml_parser_scan_block_scalar(yaml_parser_t *parser, int literal);
925
926static int
927yaml_parser_scan_block_scalar_indicators(yaml_parser_t *parser,
928        yaml_mark_t start_mark, int *chomping, int *increment);
929
930static yaml_token_t *
931yaml_parser_scan_flow_scalar(yaml_parser_t *parser, int single);
932
933static yaml_token_t *
934yaml_parser_scan_plain_scalar(yaml_parser_t *parser);
935
936/*
937 * Get the next token and remove it from the tokens queue.
938 */
939
940YAML_DECLARE(yaml_token_t *)
941yaml_parser_get_token(yaml_parser_t *parser)
942{
943    yaml_token_t *token;
944
945    assert(parser); /* Non-NULL parser object is expected. */
946    assert(!parser->stream_end_produced);   /* No tokens after STREAM-END. */
947
948    /* Ensure that the tokens queue contains enough tokens. */
949
950    if (!yaml_parser_fetch_more_tokens(parser)) return NULL;
951
952    /* Fetch the next token from the queue. */
953
954    token = parser->tokens[parser->tokens_head];
955
956    /* Move the queue head. */
957
958    parser->tokens[parser->tokens_head++] = NULL;
959    if (parser->tokens_head == parser->tokens_size)
960        parser->tokens_head = 0;
961
962    parser->tokens_parsed++;
963
964    return token;
965}
966
967/*
968 * Get the next token, but don't remove it from the queue.
969 */
970
971YAML_DECLARE(yaml_token_t *)
972yaml_parser_peek_token(yaml_parser_t *parser)
973{
974    assert(parser); /* Non-NULL parser object is expected. */
975    assert(!parser->stream_end_produced);   /* No tokens after STREAM-END. */
976
977    /* Ensure that the tokens queue contains enough tokens. */
978
979    if (!yaml_parser_fetch_more_tokens(parser)) return NULL;
980
981    /* Fetch the next token from the queue. */
982
983    return parser->tokens[parser->tokens_head];
984}
985
986/*
987 * Create a new string.
988 */
989
990static yaml_string_t
991yaml_parser_new_string(yaml_parser_t *parser)
992{
993    yaml_string_t string = { NULL, NULL, 0 };
994
995    string.buffer = yaml_malloc(YAML_DEFAULT_SIZE);
996    if (!string.buffer) {
997        parser->error = YAML_MEMORY_ERROR;
998        return string;
999    }
1000
1001    memset(string.buffer, 0, YAML_DEFAULT_SIZE);
1002    string.pointer = string.buffer;
1003    string.size = YAML_DEFAULT_SIZE;
1004
1005    return string;
1006}
1007
1008/*
1009 * Double the size of a string.
1010 */
1011
1012static int
1013yaml_parser_resize_string(yaml_parser_t *parser, yaml_string_t *string)
1014{
1015    yaml_char_t *new_buffer = yaml_realloc(string->buffer, string->size*2);
1016
1017    if (!new_buffer) {
1018        yaml_free(string->buffer);
1019        string->buffer = NULL;
1020        string->pointer = NULL;
1021        string->size = 0;
1022        parser->error = YAML_MEMORY_ERROR;
1023        return 0;
1024    }
1025
1026    memset(new_buffer+string->size, 0, string->size);
1027
1028    string->pointer = new_buffer + (string->buffer-string->pointer);
1029    string->buffer = new_buffer;
1030    string->size *= 2;
1031
1032    return 1;
1033}
1034
1035/*
1036 * Double a list.
1037 */
1038
1039static int
1040yaml_parser_resize_list(yaml_parser_t *parser, void **buffer, size_t *size,
1041        size_t item_size)
1042{
1043    void *new_buffer = yaml_realloc(*buffer, item_size*(*size)*2);
1044
1045    if (!new_buffer) {
1046        parser->error = YAML_MEMORY_ERROR;
1047        return 0;
1048    }
1049
1050    memset(new_buffer+(*size), 0, item_size*(*size));
1051
1052    *buffer = new_buffer;
1053    *size *= 2;
1054
1055    return 1;
1056}
1057
1058/*
1059 * Set the scanner error and return 0.
1060 */
1061
1062static int
1063yaml_parser_set_scanner_error(yaml_parser_t *parser, const char *context,
1064        yaml_mark_t context_mark, const char *problem)
1065{
1066    parser->error = YAML_SCANNER_ERROR;
1067    parser->context = context;
1068    parser->context_mark = context_mark;
1069    parser->problem = problem;
1070    parser->problem_mark = yaml_parser_get_mark(parser);
1071}
1072
1073/*
1074 * Get the mark for the current buffer position.
1075 */
1076
1077static yaml_mark_t
1078yaml_parser_get_mark(yaml_parser_t *parser)
1079{
1080    yaml_mark_t mark = { parser->index, parser->line, parser->column };
1081
1082    return mark;
1083}
1084
1085
1086/*
1087 * Ensure that the tokens queue contains at least one token which can be
1088 * returned to the Parser.
1089 */
1090
1091static int
1092yaml_parser_fetch_more_tokens(yaml_parser_t *parser)
1093{
1094    int need_more_tokens;
1095    int k;
1096
1097    /* While we need more tokens to fetch, do it. */
1098
1099    while (1)
1100    {
1101        /*
1102         * Check if we really need to fetch more tokens.
1103         */
1104
1105        need_more_tokens = 0;
1106
1107        if (parser->tokens_head == parser->tokens_tail)
1108        {
1109            /* Queue is empty. */
1110
1111            need_more_tokens = 1;
1112        }
1113        else
1114        {
1115            /* Check if any potential simple key may occupy the head position. */
1116
1117            for (k = 0; k <= parser->flow_level; k++) {
1118                yaml_simple_key_t *simple_key = parser->simple_keys[k];
1119                if (simple_key
1120                        && (simple_key->token_number == parser->tokens_parsed)) {
1121                    need_more_tokens = 1;
1122                    break;
1123                }
1124            }
1125        }
1126
1127        /* We are finished. */
1128
1129        if (!need_more_tokens)
1130            break;
1131
1132        /* Fetch the next token. */
1133
1134        if (!yaml_parser_fetch_next_token(parser))
1135            return 0;
1136    }
1137
1138    return 1;
1139}
1140
1141/*
1142 * The dispatcher for token fetchers.
1143 */
1144
1145static int
1146yaml_parser_fetch_next_token(yaml_parser_t *parser)
1147{
1148    /* Ensure that the buffer is initialized. */
1149
1150    if (!UPDATE(parser, 1))
1151        return 0;
1152
1153    /* Check if we just started scanning.  Fetch STREAM-START then. */
1154
1155    if (!parser->stream_start_produced)
1156        return yaml_parser_fetch_stream_start(parser);
1157
1158    /* Eat whitespaces and comments until we reach the next token. */
1159
1160    if (!yaml_parser_scan_to_next_token(parser))
1161        return 0;
1162
1163    /* Check the indentation level against the current column. */
1164
1165    if (!yaml_parser_unroll_indent(parser, parser->column))
1166        return 0;
1167
1168    /*
1169     * Ensure that the buffer contains at least 4 characters.  4 is the length
1170     * of the longest indicators ('--- ' and '... ').
1171     */
1172
1173    if (!UPDATE(parser, 4))
1174        return 0;
1175
1176    /* Is it the end of the stream? */
1177
1178    if (IS_Z(parser))
1179        return yaml_parser_fetch_stream_end(parser);
1180
1181    /* Is it a directive? */
1182
1183    if (parser->column == 0 && CHECK(parser, '%'))
1184        return yaml_parser_fetch_directive(parser);
1185
1186    /* Is it the document start indicator? */
1187
1188    if (parser->column == 0
1189            && CHECK_AT(parser, '-', 0)
1190            && CHECK_AT(parser, '-', 1)
1191            && CHECK_AT(parser, '-', 2)
1192            && IS_BLANKZ_AT(parser, 3))
1193        return yaml_parser_fetch_document_indicator(parser,
1194                YAML_DOCUMENT_START_TOKEN);
1195
1196    /* Is it the document end indicator? */
1197
1198    if (parser->column == 0
1199            && CHECK_AT(parser, '.', 0)
1200            && CHECK_AT(parser, '.', 1)
1201            && CHECK_AT(parser, '.', 2)
1202            && IS_BLANKZ_AT(parser, 3))
1203        return yaml_parser_fetch_document_indicator(parser,
1204                YAML_DOCUMENT_END_TOKEN);
1205
1206    /* Is it the flow sequence start indicator? */
1207
1208    if (CHECK(parser, '['))
1209        return yaml_parser_fetch_flow_collection_start(parser,
1210                YAML_FLOW_SEQUENCE_START_TOKEN);
1211
1212    /* Is it the flow mapping start indicator? */
1213
1214    if (CHECK(parser, '{'))
1215        return yaml_parser_fetch_flow_collection_start(parser,
1216                YAML_FLOW_MAPPING_START_TOKEN);
1217
1218    /* Is it the flow sequence end indicator? */
1219
1220    if (CHECK(parser, ']'))
1221        return yaml_parser_fetch_flow_collection_end(parser,
1222                YAML_FLOW_SEQUENCE_END_TOKEN);
1223
1224    /* Is it the flow mapping end indicator? */
1225
1226    if (CHECK(parser, '}'))
1227        return yaml_parser_fetch_flow_collection_end(parser,
1228                YAML_FLOW_MAPPING_END_TOKEN);
1229
1230    /* Is it the flow entry indicator? */
1231
1232    if (CHECK(parser, ','))
1233        return yaml_parser_fetch_flow_entry(parser);
1234
1235    /* Is it the block entry indicator? */
1236
1237    if (CHECK(parser, '-') && IS_BLANKZ_AT(parser, 1))
1238        return yaml_parser_fetch_block_entry(parser);
1239
1240    /* Is it the key indicator? */
1241
1242    if (CHECK(parser, '?') && (!parser->flow_level || IS_BLANKZ_AT(parser, 1)))
1243        return yaml_parser_fetch_key(parser);
1244
1245    /* Is it the value indicator? */
1246
1247    if (CHECK(parser, ':') && (!parser->flow_level || IS_BLANKZ_AT(parser, 1)))
1248        return yaml_parser_fetch_value(parser);
1249
1250    /* Is it an alias? */
1251
1252    if (CHECK(parser, '*'))
1253        return yaml_parser_fetch_anchor(parser, YAML_ALIAS_TOKEN);
1254
1255    /* Is it an anchor? */
1256
1257    if (CHECK(parser, '&'))
1258        return yaml_parser_fetch_anchor(parser, YAML_ANCHOR_TOKEN);
1259
1260    /* Is it a tag? */
1261
1262    if (CHECK(parser, '!'))
1263        return yaml_parser_fetch_tag(parser);
1264
1265    /* Is it a literal scalar? */
1266
1267    if (CHECK(parser, '|') && !parser->flow_level)
1268        return yaml_parser_fetch_block_scalar(parser, 1);
1269
1270    /* Is it a folded scalar? */
1271
1272    if (CHECK(parser, '>') && !parser->flow_level)
1273        return yaml_parser_fetch_block_scalar(parser, 0);
1274
1275    /* Is it a single-quoted scalar? */
1276
1277    if (CHECK(parser, '\''))
1278        return yaml_parser_fetch_flow_scalar(parser, 1);
1279
1280    /* Is it a double-quoted scalar? */
1281
1282    if (CHECK(parser, '"'))
1283        return yaml_parser_fetch_flow_scalar(parser, 0);
1284
1285    /*
1286     * Is it a plain scalar?
1287     *
1288     * A plain scalar may start with any non-blank characters except
1289     *
1290     *      '-', '?', ':', ',', '[', ']', '{', '}',
1291     *      '#', '&', '*', '!', '|', '>', '\'', '\"',
1292     *      '%', '@', '`'.
1293     *
1294     * In the block context, it may also start with the characters
1295     *
1296     *      '-', '?', ':'
1297     *
1298     * if it is followed by a non-space character.
1299     *
1300     * The last rule is more restrictive than the specification requires.
1301     */
1302
1303    if (!(IS_BLANKZ(parser) || CHECK(parser, '-') || CHECK(parser, '?')
1304                || CHECK(parser, ':') || CHECK(parser, ',') || CHECK(parser, '[')
1305                || CHECK(parser, ']') || CHECK(parser, '{') || CHECK(parser, '}')
1306                || CHECK(parser, '#') || CHECK(parser, '&') || CHECK(parser, '*')
1307                || CHECK(parser, '!') || CHECK(parser, '|') || CHECK(parser, '>')
1308                || CHECK(parser, '\'') || CHECK(parser, '"') || CHECK(parser, '%')
1309                || CHECK(parser, '@') || CHECK(parser, '`')) ||
1310            (!parser->flow_level &&
1311             (CHECK(parser, '-') || CHECK(parser, '?') || CHECK(parser, ':')) &&
1312             IS_BLANKZ_AT(parser, 1)))
1313        return yaml_parser_fetch_plain_scalar(parser);
1314
1315    /*
1316     * If we don't determine the token type so far, it is an error.
1317     */
1318
1319    return yaml_parser_set_scanner_error(parser, "while scanning for the next token",
1320            yaml_parser_get_mark(parser), "found character that cannot start any token");
1321}
1322
1323/*
1324 * Check the list of potential simple keys and remove the positions that
1325 * cannot contain simple keys anymore.
1326 */
1327
1328static int
1329yaml_parser_stale_simple_keys(yaml_parser_t *parser)
1330{
1331    int level;
1332
1333    /* Check for a potential simple key for each flow level. */
1334
1335    for (level = 0; level <= parser->flow_level; level++)
1336    {
1337        yaml_simple_key_t *simple_key = parser->simple_keys[level];
1338
1339        /*
1340         * The specification requires that a simple key
1341         *
1342         *  - is limited to a single line,
1343         *  - is shorter than 1024 characters.
1344         */
1345
1346        if (simple_key && (simple_key->line < parser->line ||
1347                    simple_key->index < parser->index+1024)) {
1348
1349            /* Check if the potential simple key to be removed is required. */
1350
1351            if (simple_key->required) {
1352                return yaml_parser_set_scanner_error(parser,
1353                        "while scanning a simple key", simple_key->mark,
1354                        "could not found expected ':'");
1355            }
1356
1357            yaml_free(simple_key);
1358            parser->simple_keys[level] = NULL;
1359        }
1360    }
1361
1362    return 1;
1363}
1364
1365/*
1366 * Check if a simple key may start at the current position and add it if
1367 * needed.
1368 */
1369
1370static int
1371yaml_parser_save_simple_key(yaml_parser_t *parser)
1372{
1373    /*
1374     * A simple key is required at the current position if the scanner is in
1375     * the block context and the current column coincides with the indentation
1376     * level.
1377     */
1378
1379    int required = (!parser->flow_level && parser->indent == parser->column);
1380
1381    /*
1382     * A simple key is required only when it is the first token in the current
1383     * line.  Therefore it is always allowed.  But we add a check anyway.
1384     */
1385
1386    assert(parser->simple_key_allowed || !required);    /* Impossible. */
1387
1388    /*
1389     * If the current position may start a simple key, save it.
1390     */
1391
1392    if (parser->simple_key_allowed)
1393    {
1394        yaml_simple_key_t simple_key = { required,
1395            parser->tokens_parsed + parser->tokens_tail - parser->tokens_head,
1396            parser->index, parser->line, parser->column,
1397            yaml_parser_get_mark(parser) };
1398
1399        if (!yaml_parser_remove_simple_key(parser)) return 0;
1400
1401        parser->simple_keys[parser->flow_level] =
1402            yaml_malloc(sizeof(yaml_simple_key_t));
1403        if (!parser->simple_keys[parser->flow_level]) {
1404            parser->error = YAML_MEMORY_ERROR;
1405            return 0;
1406        }
1407
1408        *(parser->simple_keys[parser->flow_level]) = simple_key;
1409    }
1410
1411    return 1;
1412}
1413
1414/*
1415 * Remove a potential simple key at the current flow level.
1416 */
1417
1418static int
1419yaml_parser_remove_simple_key(yaml_parser_t *parser)
1420{
1421    yaml_simple_key_t *simple_key = parser->simple_keys[parser->flow_level];
1422
1423    if (simple_key)
1424    {
1425        /* If the key is required, it is an error. */
1426
1427        if (simple_key->required) {
1428            return yaml_parser_set_scanner_error(parser,
1429                    "while scanning a simple key", simple_key->mark,
1430                    "could not found expected ':'");
1431        }
1432
1433        /* Remove the key from the list. */
1434
1435        yaml_free(simple_key);
1436        parser->simple_keys[parser->flow_level] = NULL;
1437    }
1438
1439    return 1;
1440}
1441
1442/*
1443 * Increase the flow level and resize the simple key list if needed.
1444 */
1445
1446static int
1447yaml_parser_increase_flow_level(yaml_parser_t *parser)
1448{
1449    /* Check if we need to resize the list. */
1450
1451    if (parser->flow_level == parser->simple_keys_size-1) {
1452        if (!yaml_parser_resize_list(parser, (void **)&parser->simple_keys,
1453                    &parser->simple_keys_size, sizeof(yaml_simple_key_t *)))
1454            return 0;
1455    }
1456
1457    /* Increase the flow level and reset the simple key. */
1458
1459    parser->simple_keys[++parser->flow_level] = NULL;
1460
1461    return 1;
1462}
1463
1464/*
1465 * Decrease the flow level.
1466 */
1467
1468static int
1469yaml_parser_decrease_flow_level(yaml_parser_t *parser)
1470{
1471    assert(parser->flow_level);                         /* Greater than 0. */
1472    assert(!parser->simple_keys[parser->flow_level]);   /* Must be removed. */
1473
1474    parser->flow_level --;
1475
1476    return 1;
1477}
1478
1479/*
1480 * Add a token to the tail of the tokens queue.
1481 */
1482
1483static int
1484yaml_parser_append_token(yaml_parser_t *parser, yaml_token_t *token)
1485{
1486    return yaml_parser_insert_token(parser, -1, token);
1487}
1488
1489/*
1490 * Insert the token into the tokens queue.  The number parameter is the
1491 * ordinal number of the token.  If the number is equal to -1, add the token
1492 * to the tail of the queue.
1493 */
1494
1495static int
1496yaml_parser_insert_token(yaml_parser_t *parser,
1497        int number, yaml_token_t *token)
1498{
1499    /* The index of the token in the queue. */
1500
1501    int index = (number == -1)
1502            ? parser->tokens_tail - parser->tokens_head
1503            : number - parser->tokens_parsed;
1504
1505    assert(index >= 0 && index <= (parser->tokens_tail-parser->tokens_head));
1506
1507    /* Check if we need to resize the queue. */
1508
1509    if (parser->tokens_head == 0 && parser->tokens_tail == parser->tokens_size) {
1510        if (!yaml_parser_resize_list(parser, (void **)&parser->tokens,
1511                    &parser->tokens_size, sizeof(yaml_token_t *)))
1512            return 0;
1513    }
1514
1515    /* Check if we need to move the queue to the beginning of the buffer. */
1516
1517    if (parser->tokens_tail == parser->tokens_size)
1518    {
1519        if (parser->tokens_head < parser->tokens_tail) {
1520            memmove(parser->tokens, parser->tokens+parser->tokens_head,
1521                    sizeof(yaml_token_t *)*(parser->tokens_tail-parser->tokens_head));
1522        }
1523        parser->tokens_tail -= parser->tokens_head;
1524        parser->tokens_head = 0;
1525    }
1526
1527    /* Check if we need to free space within the queue. */
1528
1529    if (index < (parser->tokens_tail-parser->tokens_head)) {
1530        memmove(parser->tokens+parser->tokens_head+index+1,
1531                parser->tokens+parser->tokens_head+index,
1532                sizeof(yaml_token_t *)*(parser->tokens_tail-parser->tokens_head-index));
1533    }
1534
1535    /* Insert the token. */
1536
1537    parser->tokens[parser->tokens_head+index] = token;
1538    parser->tokens_tail ++;
1539
1540    return 1;
1541}
1542
1543/*
1544 * Push the current indentation level to the stack and set the new level
1545 * the current column is greater than the indentation level.  In this case,
1546 * append or insert the specified token into the token queue.
1547 *
1548 */
1549
1550static int
1551yaml_parser_roll_indent(yaml_parser_t *parser, int column,
1552        int number, yaml_token_type_t type, yaml_mark_t mark)
1553{
1554    yaml_token_t *token;
1555
1556    /* In the flow context, do nothing. */
1557
1558    if (parser->flow_level)
1559        return 1;
1560
1561    if (parser->indent < column)
1562    {
1563        /* Check if we need to expand the indents stack. */
1564
1565        if (parser->indents_length == parser->indents_size) {
1566            if (!yaml_parser_resize_list(parser, (void **)&parser->indents,
1567                        &parser->indents_size, sizeof(int)))
1568                return 0;
1569        }
1570
1571        /*
1572         * Push the current indentation level to the stack and set the new
1573         * indentation level.
1574         */
1575
1576        parser->indents[parser->indents_length++] = parser->indent;
1577        parser->indent = column;
1578
1579        /* Create a token. */
1580
1581        token = yaml_token_new(type, mark, mark);
1582        if (!token) {
1583            parser->error = YAML_MEMORY_ERROR;
1584            return 0;
1585        }
1586
1587        /* Insert the token into the queue. */
1588
1589        if (!yaml_parser_insert_token(parser, number, token)) {
1590            yaml_token_delete(token);
1591            return 0;
1592        }
1593    }
1594
1595    return 1;
1596}
1597
1598/*
1599 * Pop indentation levels from the indents stack until the current level
1600 * becomes less or equal to the column.  For each intendation level, append
1601 * the BLOCK-END token.
1602 */
1603
1604
1605static int
1606yaml_parser_unroll_indent(yaml_parser_t *parser, int column)
1607{
1608    yaml_token_t *token;
1609
1610    /* In the flow context, do nothing. */
1611
1612    if (parser->flow_level)
1613        return 1;
1614
1615    /* Loop through the intendation levels in the stack. */
1616
1617    while (parser->indent > column)
1618    {
1619        yaml_mark_t mark = yaml_parser_get_mark(parser);
1620
1621        /* Create a token. */
1622
1623        token = yaml_token_new(YAML_BLOCK_END_TOKEN, mark, mark);
1624        if (!token) {
1625            parser->error = YAML_MEMORY_ERROR;
1626            return 0;
1627        }
1628
1629        /* Append the token to the queue. */
1630
1631        if (!yaml_parser_append_token(parser, token)) {
1632            yaml_token_delete(token);
1633            return 0;
1634        }
1635
1636        /* Pop the indentation level. */
1637
1638        assert(parser->indents_length);     /* Non-empty stack expected. */
1639
1640        parser->indent = parser->indents[--parser->indents_length];
1641    }
1642
1643    return 1;
1644}
1645
1646/*
1647 * Initialize the scanner and produce the STREAM-START token.
1648 */
1649
1650static int
1651yaml_parser_fetch_stream_start(yaml_parser_t *parser)
1652{
1653    yaml_mark_t mark = yaml_parser_get_mark(parser);
1654    yaml_token_t *token;
1655
1656    /* Set the initial indentation. */
1657
1658    parser->indent = -1;
1659
1660    /* A simple key is allowed at the beginning of the stream. */
1661
1662    parser->simple_key_allowed = 1;
1663
1664    /* We have started. */
1665
1666    parser->stream_start_produced = 1;
1667
1668    /* Create the STREAM-START token. */
1669
1670    token = yaml_stream_start_token_new(parser->encoding, mark, mark);
1671    if (!token) {
1672        parser->error = YAML_MEMORY_ERROR;
1673        return 0;
1674    }
1675
1676    /* Append the token to the queue. */
1677
1678    if (!yaml_parser_append_token(parser, token)) {
1679        yaml_token_delete(token);
1680        return 0;
1681    }
1682
1683    return 1;
1684}
1685
1686/*
1687 * Produce the STREAM-END token and shut down the scanner.
1688 */
1689
1690static int
1691yaml_parser_fetch_stream_end(yaml_parser_t *parser)
1692{
1693    yaml_mark_t mark = yaml_parser_get_mark(parser);
1694    yaml_token_t *token;
1695
1696    /* Reset the indentation level. */
1697
1698    if (!yaml_parser_unroll_indent(parser, -1))
1699        return 0;
1700
1701    /* We have finished. */
1702
1703    parser->stream_end_produced = 1;
1704
1705    /* Create the STREAM-END token. */
1706
1707    token = yaml_stream_end_token_new(mark, mark);
1708    if (!token) {
1709        parser->error = YAML_MEMORY_ERROR;
1710        return 0;
1711    }
1712
1713    /* Append the token to the queue. */
1714
1715    if (!yaml_parser_append_token(parser, token)) {
1716        yaml_token_delete(token);
1717        return 0;
1718    }
1719
1720    return 1;
1721}
1722
1723/*
1724 * Produce the YAML-DIRECTIVE or TAG-DIRECTIVE token.
1725 */
1726
1727static int
1728yaml_parser_fetch_directive(yaml_parser_t *parser)
1729{
1730    yaml_token_t *token;
1731
1732    /* Reset the indentation level. */
1733
1734    if (!yaml_parser_unroll_indent(parser, -1))
1735        return 0;
1736
1737    /* Reset simple keys. */
1738
1739    if (!yaml_parser_remove_simple_key(parser))
1740        return 0;
1741
1742    parser->simple_key_allowed = 0;
1743
1744    /* Create the YAML-DIRECTIVE or TAG-DIRECTIVE token. */
1745
1746    token = yaml_parser_scan_directive(parser);
1747    if (!token) return 0;
1748
1749    /* Append the token to the queue. */
1750
1751    if (!yaml_parser_append_token(parser, token)) {
1752        yaml_token_delete(token);
1753        return 0;
1754    }
1755
1756    return 1;
1757}
1758
1759/*
1760 * Produce the DOCUMENT-START or DOCUMENT-END token.
1761 */
1762
1763static int
1764yaml_parser_fetch_document_indicator(yaml_parser_t *parser,
1765        yaml_token_type_t type)
1766{
1767    yaml_mark_t start_mark, end_mark;
1768    yaml_token_t *token;
1769
1770    /* Reset the indentation level. */
1771
1772    if (!yaml_parser_unroll_indent(parser, -1))
1773        return 0;
1774
1775    /* Reset simple keys. */
1776
1777    if (!yaml_parser_remove_simple_key(parser))
1778        return 0;
1779
1780    parser->simple_key_allowed = 0;
1781
1782    /* Consume the token. */
1783
1784    start_mark = yaml_parser_get_mark(parser);
1785
1786    FORWARD(parser);
1787    FORWARD(parser);
1788    FORWARD(parser);
1789
1790    end_mark = yaml_parser_get_mark(parser);
1791
1792    /* Create the DOCUMENT-START or DOCUMENT-END token. */
1793
1794    token = yaml_token_new(type, start_mark, end_mark);
1795    if (!token) {
1796        parser->error = YAML_MEMORY_ERROR;
1797        return 0;
1798    }
1799
1800    /* Append the token to the queue. */
1801
1802    if (!yaml_parser_append_token(parser, token)) {
1803        yaml_token_delete(token);
1804        return 0;
1805    }
1806
1807    return 1;
1808}
1809
1810/*
1811 * Produce the FLOW-SEQUENCE-START or FLOW-MAPPING-START token.
1812 */
1813
1814static int
1815yaml_parser_fetch_flow_collection_start(yaml_parser_t *parser,
1816        yaml_token_type_t type)
1817{
1818    yaml_mark_t start_mark, end_mark;
1819    yaml_token_t *token;
1820
1821    /* The indicators '[' and '{' may start a simple key. */
1822
1823    if (!yaml_parser_save_simple_key(parser))
1824        return 0;
1825
1826    /* Increase the flow level. */
1827
1828    if (!yaml_parser_increase_flow_level(parser))
1829        return 0;
1830
1831    /* A simple key may follow the indicators '[' and '{'. */
1832
1833    parser->simple_key_allowed = 1;
1834
1835    /* Consume the token. */
1836
1837    start_mark = yaml_parser_get_mark(parser);
1838    FORWARD(parser);
1839    end_mark = yaml_parser_get_mark(parser);
1840
1841    /* Create the FLOW-SEQUENCE-START of FLOW-MAPPING-START token. */
1842
1843    token = yaml_token_new(type, start_mark, end_mark);
1844    if (!token) {
1845        parser->error = YAML_MEMORY_ERROR;
1846        return 0;
1847    }
1848
1849    /* Append the token to the queue. */
1850
1851    if (!yaml_parser_append_token(parser, token)) {
1852        yaml_token_delete(token);
1853        return 0;
1854    }
1855
1856    return 1;
1857}
1858
1859/*
1860 * Produce the FLOW-SEQUENCE-END or FLOW-MAPPING-END token.
1861 */
1862
1863static int
1864yaml_parser_fetch_flow_collection_end(yaml_parser_t *parser,
1865        yaml_token_type_t type)
1866{
1867    yaml_mark_t start_mark, end_mark;
1868    yaml_token_t *token;
1869
1870    /* Reset any potential simple key on the current flow level. */
1871
1872    if (!yaml_parser_remove_simple_key(parser))
1873        return 0;
1874
1875    /* Decrease the flow level. */
1876
1877    if (!yaml_parser_decrease_flow_level(parser))
1878        return 0;
1879
1880    /* No simple keys after the indicators ']' and '}'. */
1881
1882    parser->simple_key_allowed = 0;
1883
1884    /* Consume the token. */
1885
1886    start_mark = yaml_parser_get_mark(parser);
1887    FORWARD(parser);
1888    end_mark = yaml_parser_get_mark(parser);
1889
1890    /* Create the FLOW-SEQUENCE-END of FLOW-MAPPING-END token. */
1891
1892    token = yaml_token_new(type, start_mark, end_mark);
1893    if (!token) {
1894        parser->error = YAML_MEMORY_ERROR;
1895        return 0;
1896    }
1897
1898    /* Append the token to the queue. */
1899
1900    if (!yaml_parser_append_token(parser, token)) {
1901        yaml_token_delete(token);
1902        return 0;
1903    }
1904
1905    return 1;
1906}
1907
1908/*
1909 * Produce the FLOW-ENTRY token.
1910 */
1911
1912static int
1913yaml_parser_fetch_flow_entry(yaml_parser_t *parser)
1914{
1915    yaml_mark_t start_mark, end_mark;
1916    yaml_token_t *token;
1917
1918    /* Reset any potential simple keys on the current flow level. */
1919
1920    if (!yaml_parser_remove_simple_key(parser))
1921        return 0;
1922
1923    /* Simple keys are allowed after ','. */
1924
1925    parser->simple_key_allowed = 1;
1926
1927    /* Consume the token. */
1928
1929    start_mark = yaml_parser_get_mark(parser);
1930    FORWARD(parser);
1931    end_mark = yaml_parser_get_mark(parser);
1932
1933    /* Create the FLOW-ENTRY token. */
1934
1935    token = yaml_token_new(YAML_FLOW_ENTRY_TOKEN, start_mark, end_mark);
1936    if (!token) {
1937        parser->error = YAML_MEMORY_ERROR;
1938        return 0;
1939    }
1940
1941    /* Append the token to the queue. */
1942
1943    if (!yaml_parser_append_token(parser, token)) {
1944        yaml_token_delete(token);
1945        return 0;
1946    }
1947
1948    return 1;
1949}
1950
1951/*
1952 * Produce the BLOCK-ENTRY token.
1953 */
1954
1955static int
1956yaml_parser_fetch_block_entry(yaml_parser_t *parser)
1957{
1958    yaml_mark_t start_mark, end_mark;
1959    yaml_token_t *token;
1960
1961    /* Check if the scanner is in the block context. */
1962
1963    if (!parser->flow_level)
1964    {
1965        /* Check if we are allowed to start a new entry. */
1966
1967        if (!parser->simple_key_allowed) {
1968            return yaml_parser_set_scanner_error(parser, NULL,
1969                    yaml_parser_get_mark(parser),
1970                    "block sequence entries are not allowed in this context");
1971        }
1972
1973        /* Add the BLOCK-SEQUENCE-START token if needed. */
1974
1975        if (!yaml_parser_roll_indent(parser, parser->column, -1,
1976                    YAML_BLOCK_SEQUENCE_START_TOKEN, yaml_parser_get_mark(parser)))
1977            return 0;
1978    }
1979    else
1980    {
1981        /*
1982         * It is an error for the '-' indicator to occur in the flow context,
1983         * but we let the Parser detect and report about it because the Parser
1984         * is able to point to the context.
1985         */
1986    }
1987
1988    /* Reset any potential simple keys on the current flow level. */
1989
1990    if (!yaml_parser_remove_simple_key(parser))
1991        return 0;
1992
1993    /* Simple keys are allowed after '-'. */
1994
1995    parser->simple_key_allowed = 1;
1996
1997    /* Consume the token. */
1998
1999    start_mark = yaml_parser_get_mark(parser);
2000    FORWARD(parser);
2001    end_mark = yaml_parser_get_mark(parser);
2002
2003    /* Create the BLOCK-ENTRY token. */
2004
2005    token = yaml_token_new(YAML_BLOCK_ENTRY_TOKEN, start_mark, end_mark);
2006    if (!token) {
2007        parser->error = YAML_MEMORY_ERROR;
2008        return 0;
2009    }
2010
2011    /* Append the token to the queue. */
2012
2013    if (!yaml_parser_append_token(parser, token)) {
2014        yaml_token_delete(token);
2015        return 0;
2016    }
2017
2018    return 1;
2019}
2020
2021/*
2022 * Produce the KEY token.
2023 */
2024
2025static int
2026yaml_parser_fetch_key(yaml_parser_t *parser)
2027{
2028    yaml_mark_t start_mark, end_mark;
2029    yaml_token_t *token;
2030
2031    /* In the block context, additional checks are required. */
2032
2033    if (!parser->flow_level)
2034    {
2035        /* Check if we are allowed to start a new key (not nessesary simple). */
2036
2037        if (!parser->simple_key_allowed) {
2038            return yaml_parser_set_scanner_error(parser, NULL,
2039                    yaml_parser_get_mark(parser),
2040                    "mapping keys are not allowed in this context");
2041        }
2042
2043        /* Add the BLOCK-MAPPING-START token if needed. */
2044
2045        if (!yaml_parser_roll_indent(parser, parser->column, -1,
2046                    YAML_BLOCK_MAPPING_START_TOKEN, yaml_parser_get_mark(parser)))
2047            return 0;
2048    }
2049
2050    /* Reset any potential simple keys on the current flow level. */
2051
2052    if (!yaml_parser_remove_simple_key(parser))
2053        return 0;
2054
2055    /* Simple keys are allowed after '?' in the block context. */
2056
2057    parser->simple_key_allowed = (!parser->flow_level);
2058
2059    /* Consume the token. */
2060
2061    start_mark = yaml_parser_get_mark(parser);
2062    FORWARD(parser);
2063    end_mark = yaml_parser_get_mark(parser);
2064
2065    /* Create the KEY token. */
2066
2067    token = yaml_token_new(YAML_KEY_TOKEN, start_mark, end_mark);
2068    if (!token) {
2069        parser->error = YAML_MEMORY_ERROR;
2070        return 0;
2071    }
2072
2073    /* Append the token to the queue. */
2074
2075    if (!yaml_parser_append_token(parser, token)) {
2076        yaml_token_delete(token);
2077        return 0;
2078    }
2079
2080    return 1;
2081}
2082
2083/*
2084 * Produce the VALUE token.
2085 */
2086
2087static int
2088yaml_parser_fetch_value(yaml_parser_t *parser)
2089{
2090    yaml_mark_t start_mark, end_mark;
2091    yaml_token_t *token;
2092
2093    /* Have we found a simple key? */
2094
2095    if (parser->simple_keys[parser->flow_level])
2096    {
2097        yaml_simple_key_t *simple_key = parser->simple_keys[parser->flow_level];
2098
2099        /* Create the KEY token. */
2100
2101        token = yaml_token_new(YAML_KEY_TOKEN, simple_key->mark, simple_key->mark);
2102        if (!token) {
2103            parser->error = YAML_MEMORY_ERROR;
2104            return 0;
2105        }
2106
2107        /* Insert the token into the queue. */
2108
2109        if (!yaml_parser_insert_token(parser, simple_key->token_number, token)) {
2110            yaml_token_delete(token);
2111            return 0;
2112        }
2113
2114        /* In the block context, we may need to add the BLOCK-MAPPING-START token. */
2115
2116        if (!yaml_parser_roll_indent(parser, parser->column,
2117                    simple_key->token_number,
2118                    YAML_BLOCK_MAPPING_START_TOKEN, simple_key->mark))
2119            return 0;
2120
2121        /* Remove the simple key from the list. */
2122
2123        yaml_free(simple_key);
2124        parser->simple_keys[parser->flow_level] = NULL;
2125
2126        /* A simple key cannot follow another simple key. */
2127
2128        parser->simple_key_allowed = 0;
2129    }
2130    else
2131    {
2132        /* The ':' indicator follows a complex key. */
2133
2134        /* In the block context, extra checks are required. */
2135
2136        if (!parser->flow_level)
2137        {
2138            /* Check if we are allowed to start a complex value. */
2139
2140            if (!parser->simple_key_allowed) {
2141                return yaml_parser_set_scanner_error(parser, NULL,
2142                        yaml_parser_get_mark(parser),
2143                        "mapping values are not allowed in this context");
2144            }
2145
2146            /* Add the BLOCK-MAPPING-START token if needed. */
2147
2148            if (!yaml_parser_roll_indent(parser, parser->column, -1,
2149                        YAML_BLOCK_MAPPING_START_TOKEN, yaml_parser_get_mark(parser)))
2150                return 0;
2151        }
2152
2153        /* Simple keys after ':' are allowed in the block context. */
2154
2155        parser->simple_key_allowed = (!parser->flow_level);
2156    }
2157
2158    /* Consume the token. */
2159
2160    start_mark = yaml_parser_get_mark(parser);
2161    FORWARD(parser);
2162    end_mark = yaml_parser_get_mark(parser);
2163
2164    /* Create the VALUE token. */
2165
2166    token = yaml_token_new(YAML_VALUE_TOKEN, start_mark, end_mark);
2167    if (!token) {
2168        parser->error = YAML_MEMORY_ERROR;
2169        return 0;
2170    }
2171
2172    /* Append the token to the queue. */
2173
2174    if (!yaml_parser_append_token(parser, token)) {
2175        yaml_token_delete(token);
2176        return 0;
2177    }
2178
2179    return 1;
2180}
2181
2182/*
2183 * Produce the ALIAS or ANCHOR token.
2184 */
2185
2186static int
2187yaml_parser_fetch_anchor(yaml_parser_t *parser, yaml_token_type_t type)
2188{
2189    yaml_token_t *token;
2190
2191    /* An anchor or an alias could be a simple key. */
2192
2193    if (!yaml_parser_save_simple_key(parser))
2194        return 0;
2195
2196    /* A simple key cannot follow an anchor or an alias. */
2197
2198    parser->simple_key_allowed = 0;
2199
2200    /* Create the ALIAS or ANCHOR token. */
2201
2202    token = yaml_parser_scan_anchor(parser, type);
2203    if (!token) return 0;
2204
2205    /* Append the token to the queue. */
2206
2207    if (!yaml_parser_append_token(parser, token)) {
2208        yaml_token_delete(token);
2209        return 0;
2210    }
2211
2212    return 1;
2213}
2214
2215/*
2216 * Produce the TAG token.
2217 */
2218
2219static int
2220yaml_parser_fetch_tag(yaml_parser_t *parser)
2221{
2222    yaml_token_t *token;
2223
2224    /* A tag could be a simple key. */
2225
2226    if (!yaml_parser_save_simple_key(parser))
2227        return 0;
2228
2229    /* A simple key cannot follow a tag. */
2230
2231    parser->simple_key_allowed = 0;
2232
2233    /* Create the TAG token. */
2234
2235    token = yaml_parser_scan_tag(parser);
2236    if (!token) return 0;
2237
2238    /* Append the token to the queue. */
2239
2240    if (!yaml_parser_append_token(parser, token)) {
2241        yaml_token_delete(token);
2242        return 0;
2243    }
2244
2245    return 1;
2246}
2247
2248/*
2249 * Produce the SCALAR(...,literal) or SCALAR(...,folded) tokens.
2250 */
2251
2252static int
2253yaml_parser_fetch_block_scalar(yaml_parser_t *parser, int literal)
2254{
2255    yaml_token_t *token;
2256
2257    /* Remove any potential simple keys. */
2258
2259    if (!yaml_parser_remove_simple_key(parser))
2260        return 0;
2261
2262    /* A simple key may follow a block scalar. */
2263
2264    parser->simple_key_allowed = 1;
2265
2266    /* Create the SCALAR token. */
2267
2268    token = yaml_parser_scan_block_scalar(parser, literal);
2269    if (!token) return 0;
2270
2271    /* Append the token to the queue. */
2272
2273    if (!yaml_parser_append_token(parser, token)) {
2274        yaml_token_delete(token);
2275        return 0;
2276    }
2277
2278    return 1;
2279}
2280
2281/*
2282 * Produce the SCALAR(...,single-quoted) or SCALAR(...,double-quoted) tokens.
2283 */
2284
2285static int
2286yaml_parser_fetch_flow_scalar(yaml_parser_t *parser, int single)
2287{
2288    yaml_token_t *token;
2289
2290    /* A plain scalar could be a simple key. */
2291
2292    if (!yaml_parser_save_simple_key(parser))
2293        return 0;
2294
2295    /* A simple key cannot follow a flow scalar. */
2296
2297    parser->simple_key_allowed = 0;
2298
2299    /* Create the SCALAR token. */
2300
2301    token = yaml_parser_scan_flow_scalar(parser, single);
2302    if (!token) return 0;
2303
2304    /* Append the token to the queue. */
2305
2306    if (!yaml_parser_append_token(parser, token)) {
2307        yaml_token_delete(token);
2308        return 0;
2309    }
2310
2311    return 1;
2312}
2313
2314/*
2315 * Produce the SCALAR(...,plain) token.
2316 */
2317
2318static int
2319yaml_parser_fetch_plain_scalar(yaml_parser_t *parser)
2320{
2321    yaml_token_t *token;
2322
2323    /* A plain scalar could be a simple key. */
2324
2325    if (!yaml_parser_save_simple_key(parser))
2326        return 0;
2327
2328    /* A simple key cannot follow a flow scalar. */
2329
2330    parser->simple_key_allowed = 0;
2331
2332    /* Create the SCALAR token. */
2333
2334    token = yaml_parser_scan_plain_scalar(parser);
2335    if (!token) return 0;
2336
2337    /* Append the token to the queue. */
2338
2339    if (!yaml_parser_append_token(parser, token)) {
2340        yaml_token_delete(token);
2341        return 0;
2342    }
2343
2344    return 1;
2345}
2346
2347/*
2348 * Eat whitespaces and comments until the next token is found.
2349 */
2350
2351static int
2352yaml_parser_scan_to_next_token(yaml_parser_t *parser)
2353{
2354    /* Until the next token is not found. */
2355
2356    while (1)
2357    {
2358        /* Allow the BOM mark to start a line. */
2359
2360        if (!UPDATE(parser, 1)) return 0;
2361
2362        if (parser->column == 0 && IS_BOM(parser))
2363            FORWARD(parser);
2364
2365        /*
2366         * Eat whitespaces.
2367         *
2368         * Tabs are allowed:
2369         *
2370         *  - in the flow context;
2371         *  - in the block context, but not at the beginning of the line or
2372         *  after '-', '?', or ':' (complex value). 
2373         */
2374
2375        if (!UPDATE(parser, 1)) return 0;
2376
2377        while (CHECK(parser,' ') ||
2378                ((parser->flow_level || !parser->simple_key_allowed) &&
2379                 CHECK(parser, '\t'))) {
2380            FORWARD(parser);
2381            if (!UPDATE(parser, 1)) return 0;
2382        }
2383
2384        /* Eat a comment until a line break. */
2385
2386        if (CHECK(parser, '#')) {
2387            while (!IS_BREAKZ(parser)) {
2388                FORWARD(parser);
2389                if (!UPDATE(parser, 1)) return 0;
2390            }
2391        }
2392
2393        /* If it is a line break, eat it. */
2394
2395        if (IS_BREAK(parser))
2396        {
2397            if (!UPDATE(parser, 2)) return 0;
2398            FORWARD_LINE(parser);
2399
2400            /* In the block context, a new line may start a simple key. */
2401
2402            if (!parser->flow_level) {
2403                parser->simple_key_allowed = 1;
2404            }
2405        }
2406        else
2407        {
2408            /* We have found a token. */
2409
2410            break;
2411        }
2412    }
2413
2414    return 1;
2415}
2416
2417/*
2418 * Scan a YAML-DIRECTIVE or TAG-DIRECTIVE token.
2419 *
2420 * Scope:
2421 *      %YAML    1.1    # a comment \n
2422 *      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2423 *      %TAG    !yaml!  tag:yaml.org,2002:  \n
2424 *      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2425 */
2426
2427static yaml_token_t *
2428yaml_parser_scan_directive(yaml_parser_t *parser)
2429{
2430    yaml_mark_t start_mark, end_mark;
2431    yaml_char_t *name = NULL;
2432    int major, minor;
2433    yaml_char_t *handle = NULL, *prefix = NULL;
2434    yaml_token_t *token = NULL;
2435
2436    /* Eat '%'. */
2437
2438    start_mark = yaml_parser_get_mark(parser);
2439
2440    FORWARD(parser);
2441
2442    /* Scan the directive name. */
2443
2444    if (!yaml_parser_scan_directive_name(parser, start_mark, &name))
2445        goto error;
2446
2447    /* Is it a YAML directive? */
2448
2449    if (strcmp((char *)name, "YAML") == 0)
2450    {
2451        /* Scan the VERSION directive value. */
2452
2453        if (!yaml_parser_scan_version_directive_value(parser, start_mark,
2454                    &major, &minor))
2455            goto error;
2456
2457        end_mark = yaml_parser_get_mark(parser);
2458
2459        /* Create a VERSION-DIRECTIVE token. */
2460
2461        token = yaml_version_directive_token_new(major, minor,
2462                start_mark, end_mark);
2463        if (!token) goto error;
2464    }
2465
2466    /* Is it a TAG directive? */
2467
2468    else if (strcmp((char *)name, "TAG") == 0)
2469    {
2470        /* Scan the TAG directive value. */
2471
2472        if (!yaml_parser_scan_tag_directive_value(parser, start_mark,
2473                    &handle, &prefix))
2474            goto error;
2475
2476        end_mark = yaml_parser_get_mark(parser);
2477
2478        /* Create a TAG-DIRECTIVE token. */
2479
2480        token = yaml_tag_directive_token_new(handle, prefix,
2481                start_mark, end_mark);
2482        if (!token) goto error;
2483    }
2484
2485    /* Unknown directive. */
2486
2487    else
2488    {
2489        yaml_parser_set_scanner_error(parser, "While scanning a directive",
2490                start_mark, "found uknown directive name");
2491        goto error;
2492    }
2493
2494    /* Eat the rest of the line including any comments. */
2495
2496    while (IS_BLANK(parser)) {
2497        FORWARD(parser);
2498        if (!UPDATE(parser, 1)) goto error;
2499    }
2500
2501    if (CHECK(parser, '#')) {
2502        while (!IS_BREAKZ(parser)) {
2503            FORWARD(parser);
2504            if (!UPDATE(parser, 1)) goto error;
2505        }
2506    }
2507
2508    /* Check if we are at the end of the line. */
2509
2510    if (!IS_BREAKZ(parser)) {
2511        yaml_parser_set_scanner_error(parser, "While scanning a directive",
2512                start_mark, "did not found expected comment or line break");
2513        goto error;
2514    }
2515
2516    /* Eat a line break. */
2517
2518    if (IS_BREAK(parser)) {
2519        if (!UPDATE(parser, 2)) goto error;
2520        FORWARD_LINE(parser);
2521    }
2522
2523    yaml_free(name);
2524
2525    return token;
2526
2527error:
2528    yaml_free(token);
2529    yaml_free(prefix);
2530    yaml_free(handle);
2531    yaml_free(name);
2532    return NULL;
2533}
2534
2535/*
2536 * Scan the directive name.
2537 *
2538 * Scope:
2539 *      %YAML   1.1     # a comment \n
2540 *       ^^^^
2541 *      %TAG    !yaml!  tag:yaml.org,2002:  \n
2542 *       ^^^
2543 */
2544
2545static int
2546yaml_parser_scan_directive_name(yaml_parser_t *parser,
2547        yaml_mark_t start_mark, yaml_char_t **name)
2548{
2549    yaml_string_t string = yaml_parser_new_string(parser);
2550
2551    if (!string.buffer) goto error;
2552
2553    /* Consume the directive name. */
2554
2555    if (!UPDATE(parser, 1)) goto error;
2556
2557    while (IS_ALPHA(parser))
2558    {
2559        if (!RESIZE(parser, string)) goto error;
2560        COPY(parser, string);
2561        if (!UPDATE(parser, 1)) goto error;
2562    }
2563
2564    /* Check if the name is empty. */
2565
2566    if (string.buffer == string.pointer) {
2567        yaml_parser_set_scanner_error(parser, "while scanning a directive",
2568                start_mark, "cannot found expected directive name");
2569        goto error;
2570    }
2571
2572    /* Check for an blank character after the name. */
2573
2574    if (!IS_BLANKZ(parser)) {
2575        yaml_parser_set_scanner_error(parser, "while scanning a directive",
2576                start_mark, "found unexpected non-alphabetical character");
2577        goto error;
2578    }
2579
2580    *name = string.buffer;
2581
2582    return 1;
2583
2584error:
2585    yaml_free(string.buffer);
2586    return 0;
2587}
2588
2589/*
2590 * Scan the value of VERSION-DIRECTIVE.
2591 *
2592 * Scope:
2593 *      %YAML   1.1     # a comment \n
2594 *           ^^^^^^
2595 */
2596
2597static int
2598yaml_parser_scan_version_directive_value(yaml_parser_t *parser,
2599        yaml_mark_t start_mark, int *major, int *minor)
2600{
2601    /* Eat whitespaces. */
2602
2603    if (!UPDATE(parser, 1)) return 0;
2604
2605    while (IS_BLANK(parser)) {
2606        FORWARD(parser);
2607        if (!UPDATE(parser, 1)) return 0;
2608    }
2609
2610    /* Consume the major version number. */
2611
2612    if (!yaml_parser_scan_version_directive_number(parser, start_mark, major))
2613        return 0;
2614
2615    /* Eat '.'. */
2616
2617    if (!CHECK(parser, '.')) {
2618        return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
2619                start_mark, "did not find expected digit or '.' character");
2620    }
2621
2622    FORWARD(parser);
2623
2624    /* Consume the minor version number. */
2625
2626    if (!yaml_parser_scan_version_directive_number(parser, start_mark, minor))
2627        return 0;
2628}
2629
2630#define MAX_NUMBER_LENGTH   9
2631
2632/*
2633 * Scan the version number of VERSION-DIRECTIVE.
2634 *
2635 * Scope:
2636 *      %YAML   1.1     # a comment \n
2637 *              ^
2638 *      %YAML   1.1     # a comment \n
2639 *                ^
2640 */
2641
2642static int
2643yaml_parser_scan_version_directive_number(yaml_parser_t *parser,
2644        yaml_mark_t start_mark, int *number)
2645{
2646    int value = 0;
2647    size_t length = 0;
2648
2649    /* Repeat while the next character is digit. */
2650
2651    if (!UPDATE(parser, 1)) return 0;
2652
2653    while (IS_DIGIT(parser))
2654    {
2655        /* Check if the number is too long. */
2656
2657        if (++length > MAX_NUMBER_LENGTH) {
2658            return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
2659                    start_mark, "found extremely long version number");
2660        }
2661
2662        value = value*10 + AS_DIGIT(parser);
2663
2664        FORWARD(parser);
2665
2666        if (!UPDATE(parser, 1)) return 0;
2667    }
2668
2669    /* Check if the number was present. */
2670
2671    if (!length) {
2672        return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive",
2673                start_mark, "did not find expected version number");
2674    }
2675
2676    *number = value;
2677
2678    return 1;
2679}
2680
2681/*
2682 * Scan the value of a TAG-DIRECTIVE token.
2683 *
2684 * Scope:
2685 *      %TAG    !yaml!  tag:yaml.org,2002:  \n
2686 *          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2687 */
2688
2689static int
2690yaml_parser_scan_tag_directive_value(yaml_parser_t *parser,
2691        yaml_mark_t start_mark, yaml_char_t **handle, yaml_char_t **prefix)
2692{
2693    yaml_char_t *handle_value = NULL;
2694    yaml_char_t *prefix_value = NULL;
2695
2696    /* Eat whitespaces. */
2697
2698    if (!UPDATE(parser, 1)) goto error;
2699
2700    while (IS_BLANK(parser)) {
2701        FORWARD(parser);
2702        if (!UPDATE(parser, 1)) goto error;
2703    }
2704
2705    /* Scan a handle. */
2706
2707    if (!yaml_parser_scan_tag_handle(parser, 1, start_mark, &handle_value))
2708        goto error;
2709
2710    /* Expect a whitespace. */
2711
2712    if (!UPDATE(parser, 1)) goto error;
2713
2714    if (!IS_BLANK(parser)) {
2715        yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive",
2716                start_mark, "did not find expected whitespace");
2717        goto error;
2718    }
2719
2720    /* Eat whitespaces. */
2721
2722    while (IS_BLANK(parser)) {
2723        FORWARD(parser);
2724        if (!UPDATE(parser, 1)) goto error;
2725    }
2726
2727    /* Scan a prefix. */
2728
2729    if (!yaml_parser_scan_tag_uri(parser, 1, NULL, start_mark, &prefix_value))
2730        goto error;
2731
2732    /* Expect a whitespace or line break. */
2733
2734    if (!UPDATE(parser, 1)) goto error;
2735
2736    if (!IS_BLANKZ(parser)) {
2737        yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive",
2738                start_mark, "did not find expected whitespace or line break");
2739        goto error;
2740    }
2741
2742    *handle = handle_value;
2743    *prefix = prefix_value;
2744
2745    return 1;
2746
2747error:
2748    yaml_free(handle_value);
2749    yaml_free(prefix_value);
2750    return 0;
2751}
2752
2753static yaml_token_t *
2754yaml_parser_scan_anchor(yaml_parser_t *parser,
2755        yaml_token_type_t type)
2756{
2757    int length = 0;
2758    yaml_mark_t start_mark, end_mark;
2759    yaml_token_t *token = NULL;
2760    yaml_string_t string = yaml_parser_new_string(parser);
2761
2762    if (!string.buffer) goto error;
2763
2764    /* Eat the indicator character. */
2765
2766    start_mark = yaml_parser_get_mark(parser);
2767
2768    FORWARD(parser);
2769
2770    /* Consume the value. */
2771
2772    if (!UPDATE(parser, 1)) goto error;
2773
2774    while (IS_ALPHA(parser)) {
2775        if (!RESIZE(parser, string)) goto error;
2776        COPY(parser, string);
2777        if (!UPDATE(parser, 1)) goto error;
2778        length ++;
2779    }
2780
2781    end_mark = yaml_parser_get_mark(parser);
2782
2783    /*
2784     * Check if length of the anchor is greater than 0 and it is followed by
2785     * a whitespace character or one of the indicators:
2786     *
2787     *      '?', ':', ',', ']', '}', '%', '@', '`'.
2788     */
2789
2790    if (!length || !(IS_BLANKZ(parser) || CHECK(parser, '?') || CHECK(parser, ':') ||
2791                CHECK(parser, ',') || CHECK(parser, ']') || CHECK(parser, '}') ||
2792                CHECK(parser, '%') || CHECK(parser, '@') || CHECK(parser, '`'))) {
2793        yaml_parser_set_scanner_error(parser, type == YAML_ANCHOR_TOKEN ?
2794                "while scanning an anchor" : "while scanning an alias", start_mark,
2795                "did not find expected alphabetic or numeric character");
2796        goto error;
2797    }
2798
2799    /* Create a token. */
2800
2801    token = type == YAML_ANCHOR_TOKEN ?
2802        yaml_anchor_token_new(string.buffer, start_mark, end_mark) :
2803        yaml_alias_token_new(string.buffer, start_mark, end_mark);
2804    if (!token) goto error;
2805
2806    return token;
2807
2808error:
2809    yaml_free(string.buffer);
2810    yaml_free(token);
2811    return 0;
2812}
2813
2814/*
2815 * Scan a TAG token.
2816 */
2817
2818static yaml_token_t *
2819yaml_parser_scan_tag(yaml_parser_t *parser)
2820{
2821    yaml_char_t *handle = NULL;
2822    yaml_char_t *suffix = NULL;
2823    yaml_token_t *token = NULL;
2824    yaml_mark_t start_mark, end_mark;
2825
2826    start_mark = yaml_parser_get_mark(parser);
2827
2828    /* Check if the tag is in the canonical form. */
2829
2830    if (!UPDATE(parser, 2)) goto error;
2831
2832    if (CHECK_AT(parser, '<', 1))
2833    {
2834        /* Set the handle to '' */
2835
2836        handle = yaml_malloc(1);
2837        if (!handle) goto error;
2838        handle[0] = '\0';
2839
2840        /* Eat '!<' */
2841
2842        FORWARD(parser);
2843        FORWARD(parser);
2844
2845        /* Consume the tag value. */
2846
2847        if (!yaml_parser_scan_tag_uri(parser, 0, NULL, start_mark, &suffix))
2848            goto error;
2849
2850        /* Check for '>' and eat it. */
2851
2852        if (!CHECK(parser, '>')) {
2853            yaml_parser_set_scanner_error(parser, "while scanning a tag",
2854                    start_mark, "did not find the expected '>'");
2855            goto error;
2856        }
2857
2858        FORWARD(parser);
2859    }
2860    else
2861    {
2862        /* The tag has either the '!suffix' or the '!handle!suffix' form. */
2863
2864        /* First, try to scan a handle. */
2865
2866        if (!yaml_parser_scan_tag_handle(parser, 0, start_mark, &handle))
2867            goto error;
2868
2869        /* Check if it is, indeed, handle. */
2870
2871        if (handle[0] == '!' && handle[1] != '\0' && handle[strlen((char *)handle)-1] == '!')
2872        {
2873            /* Scan the suffix now. */
2874
2875            if (!yaml_parser_scan_tag_uri(parser, 0, NULL, start_mark, &suffix))
2876                goto error;
2877        }
2878        else
2879        {
2880            /* It wasn't a handle after all.  Scan the rest of the tag. */
2881
2882            if (!yaml_parser_scan_tag_uri(parser, 0, handle, start_mark, &suffix))
2883                goto error;
2884
2885            /* Set the handle to '!'. */
2886
2887            yaml_free(handle);
2888            handle = yaml_malloc(2);
2889            if (!handle) goto error;
2890            handle[0] = '!';
2891            handle[1] = '\0';
2892        }
2893    }
2894
2895    /* Check the character which ends the tag. */
2896
2897    if (!UPDATE(parser, 1)) goto error;
2898
2899    if (!IS_BLANKZ(parser)) {
2900        yaml_parser_set_scanner_error(parser, "while scanning a tag",
2901                start_mark, "did not found expected whitespace or line break");
2902        goto error;
2903    }
2904
2905    end_mark = yaml_parser_get_mark(parser);
2906
2907    /* Create a token. */
2908
2909    token = yaml_tag_token_new(handle, suffix, start_mark, end_mark);
2910    if (!token) goto error;
2911
2912    return token;
2913
2914error:
2915    yaml_free(handle);
2916    yaml_free(suffix);
2917    return NULL;
2918}
2919
2920/*
2921 * Scan a tag handle.
2922 */
2923
2924static int
2925yaml_parser_scan_tag_handle(yaml_parser_t *parser, int directive,
2926        yaml_mark_t start_mark, yaml_char_t **handle)
2927{
2928    yaml_string_t string = yaml_parser_new_string(parser);
2929
2930    if (!string.buffer) goto error;
2931
2932    /* Check the initial '!' character. */
2933
2934    if (!UPDATE(parser, 1)) goto error;
2935
2936    if (!CHECK(parser, '!')) {
2937        yaml_parser_set_scanner_error(parser, directive ?
2938                "while scanning a tag directive" : "while scanning a tag",
2939                start_mark, "did not find expected '!'");
2940        goto error;
2941    }
2942
2943    /* Copy the '!' character. */
2944
2945    COPY(parser, string);
2946
2947    /* Copy all subsequent alphabetical and numerical characters. */
2948
2949    if (!UPDATE(parser, 1)) goto error;
2950
2951    while (IS_ALPHA(parser))
2952    {
2953        if (!RESIZE(parser, string)) goto error;
2954        COPY(parser, string);
2955        if (!UPDATE(parser, 1)) goto error;
2956    }
2957
2958    /* Check if the trailing character is '!' and copy it. */
2959
2960    if (CHECK(parser, '!'))
2961    {
2962        if (!RESIZE(parser, string)) goto error;
2963        COPY(parser, string);
2964    }
2965    else
2966    {
2967        /*
2968         * It's not really a tag handle.  If it's a %TAG directive, it's an
2969         * error.  If it's a tag token, it must be a part of URI.
2970         */
2971
2972        if (directive) {
2973            yaml_parser_set_scanner_error(parser, "while parsing a directive",
2974                    start_mark, "did not find expected '!'");
2975            goto error;
2976        }
2977    }
2978
2979    *handle = string.buffer;
2980
2981    return 1;
2982
2983error:
2984    yaml_free(string.buffer);
2985    return 0;
2986}
2987
2988/*
2989 * Scan a tag.
2990 */
2991
2992static int
2993yaml_parser_scan_tag_uri(yaml_parser_t *parser, int directive,
2994        yaml_char_t *head, yaml_mark_t start_mark, yaml_char_t **uri)
2995{
2996    size_t length = head ? strlen((char *)head) : 0;
2997    yaml_string_t string = yaml_parser_new_string(parser);
2998
2999    if (!string.buffer) goto error;
3000
3001    /* Resize the string to include the head. */
3002
3003    while (string.size <= length) {
3004        if (!yaml_parser_resize_string(parser, &string)) goto error;
3005    }
3006
3007    /* Copy the head if needed. */
3008
3009    if (length) {
3010        memcpy(string.buffer, head, length);
3011        string.pointer += length;
3012    }
3013
3014    /* Scan the tag. */
3015
3016    if (!UPDATE(parser, 1)) goto error;
3017
3018    /*
3019     * The set of characters that may appear in URI is as follows:
3020     *
3021     *      '0'-'9', 'A'-'Z', 'a'-'z', '_', '-', ';', '/', '?', ':', '@', '&',
3022     *      '=', '+', '$', ',', '.', '!', '~', '*', '\'', '(', ')', '[', ']',
3023     *      '%'.
3024     */
3025
3026    while (IS_ALPHA(parser) || CHECK(parser, ';') || CHECK(parser, '/') ||
3027            CHECK(parser, '?') || CHECK(parser, ':') || CHECK(parser, '@') ||
3028            CHECK(parser, '&') || CHECK(parser, '=') || CHECK(parser, '+') ||
3029            CHECK(parser, '$') || CHECK(parser, ',') || CHECK(parser, '.') ||
3030            CHECK(parser, '!') || CHECK(parser, '~') || CHECK(parser, '*') ||
3031            CHECK(parser, '\'') || CHECK(parser, '(') || CHECK(parser, ')') ||
3032            CHECK(parser, '[') || CHECK(parser, ']') || CHECK(parser, '%'))
3033    {
3034        if (!RESIZE(parser, string)) goto error;
3035
3036        /* Check if it is a URI-escape sequence. */
3037
3038        if (CHECK(parser, '%')) {
3039            if (!yaml_parser_scan_uri_escapes(parser,
3040                        directive, start_mark, &string)) goto error;
3041        }
3042        else {
3043            COPY(parser, string);
3044        }
3045
3046        length ++;
3047        if (!UPDATE(parser, 1)) goto error;
3048    }
3049
3050    /* Check if the tag is non-empty. */
3051
3052    if (!length) {
3053        yaml_parser_set_scanner_error(parser, directive ?
3054                "while parsing a %TAG directive" : "while parsing a tag",
3055                start_mark, "did not find expected tag URI");
3056        goto error;
3057    }
3058
3059    *uri = string.buffer;
3060
3061    return 1;
3062
3063error:
3064    yaml_free(string.buffer);
3065    return 0;
3066}
3067
3068/*
3069 * Decode an URI-escape sequence corresponding to a single UTF-8 character.
3070 */
3071
3072static int
3073yaml_parser_scan_uri_escapes(yaml_parser_t *parser, int directive,
3074        yaml_mark_t start_mark, yaml_string_t *string)
3075{
3076    int width = 0;
3077
3078    /* Decode the required number of characters. */
3079
3080    do {
3081
3082        unsigned char octet = 0;
3083
3084        /* Check for a URI-escaped octet. */
3085
3086        if (!UPDATE(parser, 3)) return 0;
3087
3088        if (!(CHECK(parser, '%') && IS_HEX_AT(parser, 1) && IS_HEX_AT(parser, 2))) {
3089            return yaml_parser_set_scanner_error(parser, directive ?
3090                    "while parsing a %TAG directive" : "while parsing a tag",
3091                    start_mark, "did not find URI escaped octet");
3092        }
3093
3094        /* Get the octet. */
3095
3096        octet = (AS_HEX_AT(parser, 1) << 4) + AS_HEX_AT(parser, 2);
3097
3098        /* If it is the leading octet, determine the length of the UTF-8 sequence. */
3099
3100        if (!width)
3101        {
3102            width = (octet & 0x80) == 0x00 ? 1 :
3103                    (octet & 0xE0) == 0xC0 ? 2 :
3104                    (octet & 0xF0) == 0xE0 ? 3 :
3105                    (octet & 0xF8) == 0xF0 ? 4 : 0;
3106            if (!width) {
3107                return yaml_parser_set_scanner_error(parser, directive ?
3108                        "while parsing a %TAG directive" : "while parsing a tag",
3109                        start_mark, "found an incorrect leading UTF-8 octet");
3110            }
3111        }
3112        else
3113        {
3114            /* Check if the trailing octet is correct. */
3115
3116            if ((octet & 0xC0) != 0x80) {
3117                return yaml_parser_set_scanner_error(parser, directive ?
3118                        "while parsing a %TAG directive" : "while parsing a tag",
3119                        start_mark, "found an incorrect trailing UTF-8 octet");
3120            }
3121        }
3122
3123        /* Copy the octet and move the pointers. */
3124
3125        *(string->pointer++) = octet;
3126        FORWARD(parser);
3127        FORWARD(parser);
3128        FORWARD(parser);
3129
3130    } while (--width);
3131
3132    return 1;
3133}
3134
Note: See TracBrowser for help on using the repository browser.