00001
00002
00003
00004
00005
00006
00007
00008 #include "ruby/ruby.h"
00009
00010 #include <stdio.h>
00011 #include <string.h>
00012
00013 #include "syck.h"
00014
00015 void syck_parser_pop_level( SyckParser * );
00016
00017
00018
00019
00020 void
00021 syck_assert( const char *file_name, unsigned line_num, const char *expr )
00022 {
00023 fflush( NULL );
00024 fprintf( stderr, "\nAssertion failed: %s, line %u: %s\n",
00025 file_name, line_num, expr );
00026 fflush( stderr );
00027 abort();
00028 }
00029
00030
00031
00032
00033 char *
00034 syck_strndup( const char *buf, long len )
00035 {
00036 char *new = S_ALLOC_N( char, len + 1 );
00037 S_MEMZERO( new, char, len + 1 );
00038 S_MEMCPY( new, buf, char, len );
00039 return new;
00040 }
00041
00042
00043
00044
00045 long
00046 syck_io_file_read( char *buf, SyckIoFile *file, long max_size, long skip )
00047 {
00048 long len = 0;
00049
00050 ASSERT( file != NULL );
00051
00052 max_size -= skip;
00053 len = fread( buf + skip, sizeof( char ), max_size, file->ptr );
00054 len += skip;
00055 buf[len] = '\0';
00056
00057 return len;
00058 }
00059
00060
00061
00062
00063 long
00064 syck_io_str_read( char *buf, SyckIoStr *str, long max_size, long skip )
00065 {
00066 char *beg;
00067 long len = 0;
00068
00069 ASSERT( str != NULL );
00070 beg = str->ptr;
00071 if ( max_size >= 0 )
00072 {
00073 max_size -= skip;
00074 if ( max_size <= 0 ) max_size = 0;
00075 else str->ptr += max_size;
00076
00077 if ( str->ptr > str->end )
00078 {
00079 str->ptr = str->end;
00080 }
00081 }
00082 else
00083 {
00084
00085 while ( str->ptr < str->end ) {
00086 if (*(str->ptr++) == '\n') break;
00087 }
00088 }
00089 if ( beg < str->ptr )
00090 {
00091 len = ( str->ptr - beg );
00092 S_MEMCPY( buf + skip, beg, char, len );
00093 }
00094 len += skip;
00095 buf[len] = '\0';
00096
00097 return len;
00098 }
00099
00100 void
00101 syck_parser_reset_levels( SyckParser *p )
00102 {
00103 while ( p->lvl_idx > 1 )
00104 {
00105 syck_parser_pop_level( p );
00106 }
00107
00108 if ( p->lvl_idx < 1 )
00109 {
00110 p->lvl_idx = 1;
00111 p->levels[0].spaces = -1;
00112 p->levels[0].ncount = 0;
00113 p->levels[0].domain = syck_strndup( "", 0 );
00114 }
00115 p->levels[0].status = syck_lvl_header;
00116 }
00117
00118 void
00119 syck_parser_reset_cursor( SyckParser *p )
00120 {
00121 if ( p->buffer == NULL )
00122 {
00123 p->buffer = S_ALLOC_N( char, p->bufsize );
00124 S_MEMZERO( p->buffer, char, p->bufsize );
00125 }
00126 p->buffer[0] = '\0';
00127
00128 p->cursor = NULL;
00129 p->lineptr = NULL;
00130 p->linectptr = NULL;
00131 p->token = NULL;
00132 p->toktmp = NULL;
00133 p->marker = NULL;
00134 p->limit = NULL;
00135
00136 p->root = 0;
00137 p->root_on_error = 0;
00138 p->linect = 0;
00139 p->eof = 0;
00140 p->last_token = 0;
00141 p->force_token = 0;
00142 }
00143
00144
00145
00146
00147 void
00148 syck_parser_set_root_on_error( SyckParser *p, SYMID roer )
00149 {
00150 p->root_on_error = roer;
00151 }
00152
00153
00154
00155
00156 SyckParser *
00157 syck_new_parser(void)
00158 {
00159 SyckParser *p;
00160 p = S_ALLOC( SyckParser );
00161 S_MEMZERO( p, SyckParser, 1 );
00162 p->lvl_capa = ALLOC_CT;
00163 p->levels = S_ALLOC_N( SyckLevel, p->lvl_capa );
00164 p->input_type = syck_yaml_utf8;
00165 p->io_type = syck_io_str;
00166 p->io.str = NULL;
00167 p->syms = NULL;
00168 p->anchors = NULL;
00169 p->bad_anchors = NULL;
00170 p->implicit_typing = 1;
00171 p->taguri_expansion = 0;
00172 p->bufsize = SYCK_BUFFERSIZE;
00173 p->buffer = NULL;
00174 p->lvl_idx = 0;
00175 syck_parser_reset_levels( p );
00176 return p;
00177 }
00178
00179 int
00180 syck_add_sym( SyckParser *p, void *data )
00181 {
00182 SYMID id = 0;
00183 if ( p->syms == NULL )
00184 {
00185 p->syms = st_init_numtable();
00186 }
00187 id = p->syms->num_entries + 1;
00188 st_insert( p->syms, id, (st_data_t)data );
00189 return id;
00190 }
00191
00192 int
00193 syck_lookup_sym( SyckParser *p, SYMID id, void **datap )
00194 {
00195 st_data_t data;
00196 int ret;
00197 if ( p->syms == NULL ) return 0;
00198 ret = st_lookup( p->syms, id, &data );
00199 if(ret) *datap = (void *)data;
00200 return ret;
00201 }
00202
00203 int
00204 syck_st_free_nodes( char *key, SyckNode *n, char *arg )
00205 {
00206 if ( n != (void *)1 ) syck_free_node( n );
00207 n = NULL;
00208 return ST_CONTINUE;
00209 }
00210
00211 void
00212 syck_st_free( SyckParser *p )
00213 {
00214
00215
00216
00217 if ( p->anchors != NULL )
00218 {
00219 st_foreach( p->anchors, syck_st_free_nodes, 0 );
00220 st_free_table( p->anchors );
00221 p->anchors = NULL;
00222 }
00223
00224 if ( p->bad_anchors != NULL )
00225 {
00226 st_foreach( p->bad_anchors, syck_st_free_nodes, 0 );
00227 st_free_table( p->bad_anchors );
00228 p->bad_anchors = NULL;
00229 }
00230 }
00231
00232 typedef struct {
00233 long hash;
00234 char *buffer;
00235 long length;
00236 long remaining;
00237 int printed;
00238 } bytestring_t;
00239
00240 int
00241 syck_st_free_syms( void *key, bytestring_t *sav, void *dummy )
00242 {
00243 S_FREE(sav->buffer);
00244 S_FREE(sav);
00245 return ST_CONTINUE;
00246 }
00247
00248 void
00249 syck_free_parser( SyckParser *p )
00250 {
00251
00252
00253
00254 if ( p->syms != NULL )
00255 {
00256 st_foreach( p->syms, syck_st_free_syms, 0 );
00257 st_free_table( p->syms );
00258 p->syms = NULL;
00259 }
00260
00261
00262
00263
00264 syck_st_free( p );
00265 syck_parser_reset_levels( p );
00266 S_FREE( p->levels[0].domain );
00267 S_FREE( p->levels );
00268
00269 if ( p->buffer != NULL )
00270 {
00271 S_FREE( p->buffer );
00272 }
00273 free_any_io( p );
00274 S_FREE( p );
00275 }
00276
00277 void
00278 syck_parser_handler( SyckParser *p, SyckNodeHandler hdlr )
00279 {
00280 ASSERT( p != NULL );
00281 p->handler = hdlr;
00282 }
00283
00284 void
00285 syck_parser_implicit_typing( SyckParser *p, int flag )
00286 {
00287 p->implicit_typing = ( flag == 0 ? 0 : 1 );
00288 }
00289
00290 void
00291 syck_parser_taguri_expansion( SyckParser *p, int flag )
00292 {
00293 p->taguri_expansion = ( flag == 0 ? 0 : 1 );
00294 }
00295
00296 void
00297 syck_parser_error_handler( SyckParser *p, SyckErrorHandler hdlr )
00298 {
00299 ASSERT( p != NULL );
00300 p->error_handler = hdlr;
00301 }
00302
00303 void
00304 syck_parser_bad_anchor_handler( SyckParser *p, SyckBadAnchorHandler hdlr )
00305 {
00306 ASSERT( p != NULL );
00307 p->bad_anchor_handler = hdlr;
00308 }
00309
00310 void
00311 syck_parser_set_input_type( SyckParser *p, enum syck_parser_input input_type )
00312 {
00313 ASSERT( p != NULL );
00314 p->input_type = input_type;
00315 }
00316
00317 void
00318 syck_parser_file( SyckParser *p, FILE *fp, SyckIoFileRead read )
00319 {
00320 ASSERT( p != NULL );
00321 free_any_io( p );
00322 syck_parser_reset_cursor( p );
00323 p->io_type = syck_io_file;
00324 p->io.file = S_ALLOC( SyckIoFile );
00325 p->io.file->ptr = fp;
00326 if ( read != NULL )
00327 {
00328 p->io.file->read = read;
00329 }
00330 else
00331 {
00332 p->io.file->read = syck_io_file_read;
00333 }
00334 }
00335
00336 void
00337 syck_parser_str( SyckParser *p, char *ptr, long len, SyckIoStrRead read )
00338 {
00339 ASSERT( p != NULL );
00340 free_any_io( p );
00341 syck_parser_reset_cursor( p );
00342 p->io_type = syck_io_str;
00343 p->io.str = S_ALLOC( SyckIoStr );
00344 p->io.str->beg = ptr;
00345 p->io.str->ptr = ptr;
00346 p->io.str->end = ptr + len;
00347 if ( read != NULL )
00348 {
00349 p->io.str->read = read;
00350 }
00351 else
00352 {
00353 p->io.str->read = syck_io_str_read;
00354 }
00355 }
00356
00357 void
00358 syck_parser_str_auto( SyckParser *p, char *ptr, SyckIoStrRead read )
00359 {
00360 syck_parser_str( p, ptr, strlen( ptr ), read );
00361 }
00362
00363 SyckLevel *
00364 syck_parser_current_level( SyckParser *p )
00365 {
00366 return &p->levels[p->lvl_idx-1];
00367 }
00368
00369 void
00370 syck_parser_pop_level( SyckParser *p )
00371 {
00372 ASSERT( p != NULL );
00373
00374
00375 if ( p->lvl_idx <= 1 ) return;
00376
00377 p->lvl_idx -= 1;
00378 free( p->levels[p->lvl_idx].domain );
00379 }
00380
00381 void
00382 syck_parser_add_level( SyckParser *p, int len, enum syck_level_status status )
00383 {
00384 ASSERT( p != NULL );
00385 if ( p->lvl_idx + 1 > p->lvl_capa )
00386 {
00387 p->lvl_capa += ALLOC_CT;
00388 S_REALLOC_N( p->levels, SyckLevel, p->lvl_capa );
00389 }
00390
00391 ASSERT( len > p->levels[p->lvl_idx-1].spaces );
00392 p->levels[p->lvl_idx].spaces = len;
00393 p->levels[p->lvl_idx].ncount = 0;
00394 p->levels[p->lvl_idx].domain = syck_strndup( p->levels[p->lvl_idx-1].domain, strlen( p->levels[p->lvl_idx-1].domain ) );
00395 p->levels[p->lvl_idx].status = status;
00396 p->lvl_idx += 1;
00397 }
00398
00399 void
00400 free_any_io( SyckParser *p )
00401 {
00402 ASSERT( p != NULL );
00403 switch ( p->io_type )
00404 {
00405 case syck_io_str:
00406 if ( p->io.str != NULL )
00407 {
00408 S_FREE( p->io.str );
00409 p->io.str = NULL;
00410 }
00411 break;
00412
00413 case syck_io_file:
00414 if ( p->io.file != NULL )
00415 {
00416 S_FREE( p->io.file );
00417 p->io.file = NULL;
00418 }
00419 break;
00420 }
00421 }
00422
00423 long
00424 syck_move_tokens( SyckParser *p )
00425 {
00426 long count, skip;
00427 ASSERT( p->buffer != NULL );
00428
00429 if ( p->token == NULL )
00430 return 0;
00431
00432 skip = p->limit - p->token;
00433 if ( ( count = p->token - p->buffer ) )
00434 {
00435 if (skip > 0)
00436 S_MEMMOVE( p->buffer, p->token, char, skip );
00437 p->token = p->buffer;
00438 p->marker -= count;
00439 p->cursor -= count;
00440 p->toktmp -= count;
00441 p->limit -= count;
00442 p->lineptr -= count;
00443 p->linectptr -= count;
00444 }
00445 return skip;
00446 }
00447
00448 void
00449 syck_check_limit( SyckParser *p, long len )
00450 {
00451 if ( p->cursor == NULL )
00452 {
00453 p->cursor = p->buffer;
00454 p->lineptr = p->buffer;
00455 p->linectptr = p->buffer;
00456 p->marker = p->buffer;
00457 }
00458 p->limit = p->buffer + len;
00459 }
00460
00461 long
00462 syck_parser_read( SyckParser *p )
00463 {
00464 long len = 0;
00465 long skip = 0;
00466 ASSERT( p != NULL );
00467 switch ( p->io_type )
00468 {
00469 case syck_io_str:
00470 skip = syck_move_tokens( p );
00471 len = (p->io.str->read)( p->buffer, p->io.str, SYCK_BUFFERSIZE - 1, skip );
00472 break;
00473
00474 case syck_io_file:
00475 skip = syck_move_tokens( p );
00476 len = (p->io.file->read)( p->buffer, p->io.file, SYCK_BUFFERSIZE - 1, skip );
00477 break;
00478 }
00479 syck_check_limit( p, len );
00480 return len;
00481 }
00482
00483 long
00484 syck_parser_readlen( SyckParser *p, long max_size )
00485 {
00486 long len = 0;
00487 long skip = 0;
00488 ASSERT( p != NULL );
00489 switch ( p->io_type )
00490 {
00491 case syck_io_str:
00492 skip = syck_move_tokens( p );
00493 len = (p->io.str->read)( p->buffer, p->io.str, max_size, skip );
00494 break;
00495
00496 case syck_io_file:
00497 skip = syck_move_tokens( p );
00498 len = (p->io.file->read)( p->buffer, p->io.file, max_size, skip );
00499 break;
00500 }
00501 syck_check_limit( p, len );
00502 return len;
00503 }
00504
00505 SYMID
00506 syck_parse( SyckParser *p )
00507 {
00508 ASSERT( p != NULL );
00509
00510 syck_st_free( p );
00511 syck_parser_reset_levels( p );
00512 syckparse( p );
00513 return p->root;
00514 }
00515
00516 void
00517 syck_default_error_handler( SyckParser *p, const char *msg )
00518 {
00519 printf( "Error at [Line %d, Col %"PRIdPTRDIFF"]: %s\n",
00520 p->linect,
00521 p->cursor - p->lineptr,
00522 msg );
00523 }
00524
00525