6 * Copyright (C) 2003 why the lucky stiff
15 void syck_parser_pop_level( SyckParser
* );
21 syck_assert( const char *file_name
, unsigned line_num
, const char *expr
)
24 fprintf( stderr
, "\nAssertion failed: %s, line %u: %s\n",
25 file_name
, line_num
, expr
);
31 * Allocates and copies a string
34 syck_strndup( const char *buf
, long len
)
36 char *new = S_ALLOC_N( char, len
+ 1 );
37 S_MEMZERO( new, char, len
+ 1 );
38 S_MEMCPY( new, buf
, char, len
);
43 * Default FILE IO function
46 syck_io_file_read( char *buf
, SyckIoFile
*file
, long max_size
, long skip
)
50 ASSERT( file
!= NULL
);
53 len
= fread( buf
+ skip
, sizeof( char ), max_size
, file
->ptr
);
61 * Default string IO function
64 syck_io_str_read( char *buf
, SyckIoStr
*str
, long max_size
, long skip
)
69 ASSERT( str
!= NULL
);
74 if ( max_size
<= 0 ) max_size
= 0;
75 else str
->ptr
+= max_size
;
77 if ( str
->ptr
> str
->end
)
84 /* Use exact string length */
85 while ( str
->ptr
< str
->end
) {
86 if (*(str
->ptr
++) == '\n') break;
91 len
= ( str
->ptr
- beg
);
92 S_MEMCPY( buf
+ skip
, beg
, char, len
);
101 syck_parser_reset_levels( SyckParser
*p
)
103 while ( p
->lvl_idx
> 1 )
105 syck_parser_pop_level( p
);
108 if ( p
->lvl_idx
< 1 )
111 p
->levels
[0].spaces
= -1;
112 p
->levels
[0].ncount
= 0;
113 p
->levels
[0].domain
= syck_strndup( "", 0 );
115 p
->levels
[0].status
= syck_lvl_header
;
119 syck_parser_reset_cursor( SyckParser
*p
)
121 if ( p
->buffer
== NULL
)
123 p
->buffer
= S_ALLOC_N( char, p
->bufsize
);
124 S_MEMZERO( p
->buffer
, char, p
->bufsize
);
137 p
->root_on_error
= 0;
145 * Value to return on a parse error
148 syck_parser_set_root_on_error( SyckParser
*p
, SYMID roer
)
150 p
->root_on_error
= roer
;
154 * Allocate the parser
157 syck_new_parser(void)
160 p
= S_ALLOC( SyckParser
);
161 S_MEMZERO( p
, SyckParser
, 1 );
162 p
->lvl_capa
= ALLOC_CT
;
163 p
->levels
= S_ALLOC_N( SyckLevel
, p
->lvl_capa
);
164 p
->input_type
= syck_yaml_utf8
;
165 p
->io_type
= syck_io_str
;
169 p
->bad_anchors
= NULL
;
170 p
->implicit_typing
= 1;
171 p
->taguri_expansion
= 0;
172 p
->bufsize
= SYCK_BUFFERSIZE
;
175 syck_parser_reset_levels( p
);
180 syck_add_sym( SyckParser
*p
, void *data
)
183 if ( p
->syms
== NULL
)
185 p
->syms
= st_init_numtable();
187 id
= p
->syms
->num_entries
+ 1;
188 st_insert( p
->syms
, id
, (st_data_t
)data
);
193 syck_lookup_sym( SyckParser
*p
, SYMID id
, void **datap
)
195 st_data_t data
= (st_data_t
)*datap
;
197 if ( p
->syms
== NULL
) return 0;
198 ret
= st_lookup( p
->syms
, id
, &data
);
199 *datap
= (void *)data
;
204 syck_st_free_nodes( char *key
, SyckNode
*n
, char *arg
)
206 if ( n
!= (void *)1 ) syck_free_node( n
);
212 syck_st_free( SyckParser
*p
)
215 * Free the anchor tables
217 if ( p
->anchors
!= NULL
)
219 st_foreach( p
->anchors
, syck_st_free_nodes
, 0 );
220 st_free_table( p
->anchors
);
224 if ( p
->bad_anchors
!= NULL
)
226 st_foreach( p
->bad_anchors
, syck_st_free_nodes
, 0 );
227 st_free_table( p
->bad_anchors
);
228 p
->bad_anchors
= NULL
;
241 syck_st_free_syms( void *key
, bytestring_t
*sav
, void *dummy
)
249 syck_free_parser( SyckParser
*p
)
252 * Free the adhoc symbol table
254 if ( p
->syms
!= NULL
)
256 st_foreach( p
->syms
, syck_st_free_syms
, 0 );
257 st_free_table( p
->syms
);
262 * Free tables, levels
265 syck_parser_reset_levels( p
);
266 S_FREE( p
->levels
[0].domain
);
269 if ( p
->buffer
!= NULL
)
278 syck_parser_handler( SyckParser
*p
, SyckNodeHandler hdlr
)
285 syck_parser_implicit_typing( SyckParser
*p
, int flag
)
287 p
->implicit_typing
= ( flag
== 0 ? 0 : 1 );
291 syck_parser_taguri_expansion( SyckParser
*p
, int flag
)
293 p
->taguri_expansion
= ( flag
== 0 ? 0 : 1 );
297 syck_parser_error_handler( SyckParser
*p
, SyckErrorHandler hdlr
)
300 p
->error_handler
= hdlr
;
304 syck_parser_bad_anchor_handler( SyckParser
*p
, SyckBadAnchorHandler hdlr
)
307 p
->bad_anchor_handler
= hdlr
;
311 syck_parser_set_input_type( SyckParser
*p
, enum syck_parser_input input_type
)
314 p
->input_type
= input_type
;
318 syck_parser_file( SyckParser
*p
, FILE *fp
, SyckIoFileRead read
)
322 syck_parser_reset_cursor( p
);
323 p
->io_type
= syck_io_file
;
324 p
->io
.file
= S_ALLOC( SyckIoFile
);
325 p
->io
.file
->ptr
= fp
;
328 p
->io
.file
->read
= read
;
332 p
->io
.file
->read
= syck_io_file_read
;
337 syck_parser_str( SyckParser
*p
, char *ptr
, long len
, SyckIoStrRead read
)
341 syck_parser_reset_cursor( p
);
342 p
->io_type
= syck_io_str
;
343 p
->io
.str
= S_ALLOC( SyckIoStr
);
344 p
->io
.str
->beg
= ptr
;
345 p
->io
.str
->ptr
= ptr
;
346 p
->io
.str
->end
= ptr
+ len
;
349 p
->io
.str
->read
= read
;
353 p
->io
.str
->read
= syck_io_str_read
;
358 syck_parser_str_auto( SyckParser
*p
, char *ptr
, SyckIoStrRead read
)
360 syck_parser_str( p
, ptr
, strlen( ptr
), read
);
364 syck_parser_current_level( SyckParser
*p
)
366 return &p
->levels
[p
->lvl_idx
-1];
370 syck_parser_pop_level( SyckParser
*p
)
374 /* The root level should never be popped */
375 if ( p
->lvl_idx
<= 1 ) return;
378 free( p
->levels
[p
->lvl_idx
].domain
);
382 syck_parser_add_level( SyckParser
*p
, int len
, enum syck_level_status status
)
385 if ( p
->lvl_idx
+ 1 > p
->lvl_capa
)
387 p
->lvl_capa
+= ALLOC_CT
;
388 S_REALLOC_N( p
->levels
, SyckLevel
, p
->lvl_capa
);
391 ASSERT( len
> p
->levels
[p
->lvl_idx
-1].spaces
);
392 p
->levels
[p
->lvl_idx
].spaces
= len
;
393 p
->levels
[p
->lvl_idx
].ncount
= 0;
394 p
->levels
[p
->lvl_idx
].domain
= syck_strndup( p
->levels
[p
->lvl_idx
-1].domain
, strlen( p
->levels
[p
->lvl_idx
-1].domain
) );
395 p
->levels
[p
->lvl_idx
].status
= status
;
400 free_any_io( SyckParser
*p
)
403 switch ( p
->io_type
)
406 if ( p
->io
.str
!= NULL
)
414 if ( p
->io
.file
!= NULL
)
416 S_FREE( p
->io
.file
);
424 syck_move_tokens( SyckParser
*p
)
427 ASSERT( p
->buffer
!= NULL
);
429 if ( p
->token
== NULL
)
432 skip
= p
->limit
- p
->token
;
433 if ( ( count
= p
->token
- p
->buffer
) )
436 S_MEMMOVE( p
->buffer
, p
->token
, char, skip
);
437 p
->token
= p
->buffer
;
443 p
->linectptr
-= count
;
449 syck_check_limit( SyckParser
*p
, long len
)
451 if ( p
->cursor
== NULL
)
453 p
->cursor
= p
->buffer
;
454 p
->lineptr
= p
->buffer
;
455 p
->linectptr
= p
->buffer
;
456 p
->marker
= p
->buffer
;
458 p
->limit
= p
->buffer
+ len
;
462 syck_parser_read( SyckParser
*p
)
467 switch ( p
->io_type
)
470 skip
= syck_move_tokens( p
);
471 len
= (p
->io
.str
->read
)( p
->buffer
, p
->io
.str
, SYCK_BUFFERSIZE
- 1, skip
);
475 skip
= syck_move_tokens( p
);
476 len
= (p
->io
.file
->read
)( p
->buffer
, p
->io
.file
, SYCK_BUFFERSIZE
- 1, skip
);
479 syck_check_limit( p
, len
);
484 syck_parser_readlen( SyckParser
*p
, long max_size
)
489 switch ( p
->io_type
)
492 skip
= syck_move_tokens( p
);
493 len
= (p
->io
.str
->read
)( p
->buffer
, p
->io
.str
, max_size
, skip
);
497 skip
= syck_move_tokens( p
);
498 len
= (p
->io
.file
->read
)( p
->buffer
, p
->io
.file
, max_size
, skip
);
501 syck_check_limit( p
, len
);
506 syck_parse( SyckParser
*p
)
511 syck_parser_reset_levels( p
);
517 syck_default_error_handler( SyckParser
*p
, const char *msg
)
519 printf( "Error at [Line %d, Col %"PRIdPTRDIFF
"]: %s\n",
521 p
->cursor
- p
->lineptr
,