Ruby 1.9.3p327(2012-11-10revision37606)
|
00001 /* 00002 * syck.c 00003 * 00004 * $Author: naruse $ 00005 * 00006 * Copyright (C) 2003 why the lucky stiff 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 * Custom assert 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 * Allocates and copies a string 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 * Default FILE IO function 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 * Default string IO function 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 /* Use exact string length */ 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 * Value to return on a parse error 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 * Allocate the parser 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 (int)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 * Free the anchor tables 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 * Free the adhoc symbol table 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 * Free tables, levels 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 /* The root level should never be popped */ 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