Ruby  1.9.3p484(2013-11-22revision43786)
syck.c
Go to the documentation of this file.
1 /*
2  * syck.c
3  *
4  * $Author: naruse $
5  *
6  * Copyright (C) 2003 why the lucky stiff
7  */
8 #include "ruby/ruby.h"
9 
10 #include <stdio.h>
11 #include <string.h>
12 
13 #include "syck.h"
14 
16 
17 /*
18  * Custom assert
19  */
20 void
21 syck_assert( const char *file_name, unsigned line_num, const char *expr )
22 {
23  fflush( NULL );
24  fprintf( stderr, "\nAssertion failed: %s, line %u: %s\n",
25  file_name, line_num, expr );
26  fflush( stderr );
27  abort();
28 }
29 
30 /*
31  * Allocates and copies a string
32  */
33 char *
34 syck_strndup( const char *buf, long len )
35 {
36  char *new = S_ALLOC_N( char, len + 1 );
37  S_MEMZERO( new, char, len + 1 );
38  S_MEMCPY( new, buf, char, len );
39  return new;
40 }
41 
42 /*
43  * Default FILE IO function
44  */
45 long
46 syck_io_file_read( char *buf, SyckIoFile *file, long max_size, long skip )
47 {
48  long len = 0;
49 
50  ASSERT( file != NULL );
51 
52  max_size -= skip;
53  len = fread( buf + skip, sizeof( char ), max_size, file->ptr );
54  len += skip;
55  buf[len] = '\0';
56 
57  return len;
58 }
59 
60 /*
61  * Default string IO function
62  */
63 long
64 syck_io_str_read( char *buf, SyckIoStr *str, long max_size, long skip )
65 {
66  char *beg;
67  long len = 0;
68 
69  ASSERT( str != NULL );
70  beg = str->ptr;
71  if ( max_size >= 0 )
72  {
73  max_size -= skip;
74  if ( max_size <= 0 ) max_size = 0;
75  else str->ptr += max_size;
76 
77  if ( str->ptr > str->end )
78  {
79  str->ptr = str->end;
80  }
81  }
82  else
83  {
84  /* Use exact string length */
85  while ( str->ptr < str->end ) {
86  if (*(str->ptr++) == '\n') break;
87  }
88  }
89  if ( beg < str->ptr )
90  {
91  len = ( str->ptr - beg );
92  S_MEMCPY( buf + skip, beg, char, len );
93  }
94  len += skip;
95  buf[len] = '\0';
96 
97  return len;
98 }
99 
100 void
102 {
103  while ( p->lvl_idx > 1 )
104  {
106  }
107 
108  if ( p->lvl_idx < 1 )
109  {
110  p->lvl_idx = 1;
111  p->levels[0].spaces = -1;
112  p->levels[0].ncount = 0;
113  p->levels[0].domain = syck_strndup( "", 0 );
114  }
115  p->levels[0].status = syck_lvl_header;
116 }
117 
118 void
120 {
121  if ( p->buffer == NULL )
122  {
123  p->buffer = S_ALLOC_N( char, p->bufsize );
124  S_MEMZERO( p->buffer, char, p->bufsize );
125  }
126  p->buffer[0] = '\0';
127 
128  p->cursor = NULL;
129  p->lineptr = NULL;
130  p->linectptr = NULL;
131  p->token = NULL;
132  p->toktmp = NULL;
133  p->marker = NULL;
134  p->limit = NULL;
135 
136  p->root = 0;
137  p->root_on_error = 0;
138  p->linect = 0;
139  p->eof = 0;
140  p->last_token = 0;
141  p->force_token = 0;
142 }
143 
144 /*
145  * Value to return on a parse error
146  */
147 void
149 {
150  p->root_on_error = roer;
151 }
152 
153 /*
154  * Allocate the parser
155  */
156 SyckParser *
158 {
159  SyckParser *p;
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 );
165  p->io_type = syck_io_str;
166  p->io.str = NULL;
167  p->syms = NULL;
168  p->anchors = NULL;
169  p->bad_anchors = NULL;
170  p->implicit_typing = 1;
171  p->taguri_expansion = 0;
173  p->buffer = NULL;
174  p->lvl_idx = 0;
176  return p;
177 }
178 
179 int
181 {
182  SYMID id = 0;
183  if ( p->syms == NULL )
184  {
185  p->syms = st_init_numtable();
186  }
187  id = p->syms->num_entries + 1;
188  st_insert( p->syms, id, (st_data_t)data );
189  return (int)id;
190 }
191 
192 int
193 syck_lookup_sym( SyckParser *p, SYMID id, void **datap )
194 {
195  st_data_t data;
196  int ret;
197  if ( p->syms == NULL ) return 0;
198  ret = st_lookup( p->syms, id, &data );
199  if(ret) *datap = (void *)data;
200  return ret;
201 }
202 
203 int
204 syck_st_free_nodes( char *key, SyckNode *n, char *arg )
205 {
206  if ( n != (void *)1 ) syck_free_node( n );
207  n = NULL;
208  return ST_CONTINUE;
209 }
210 
211 void
213 {
214  /*
215  * Free the anchor tables
216  */
217  if ( p->anchors != NULL )
218  {
220  st_free_table( p->anchors );
221  p->anchors = NULL;
222  }
223 
224  if ( p->bad_anchors != NULL )
225  {
228  p->bad_anchors = NULL;
229  }
230 }
231 
232 typedef struct {
233  long hash;
234  char *buffer;
235  long length;
236  long remaining;
237  int printed;
238 } bytestring_t;
239 
240 int
241 syck_st_free_syms( void *key, bytestring_t *sav, void *dummy )
242 {
243  S_FREE(sav->buffer);
244  S_FREE(sav);
245  return ST_CONTINUE;
246 }
247 
248 void
250 {
251  /*
252  * Free the adhoc symbol table
253  */
254  if ( p->syms != NULL )
255  {
257  st_free_table( p->syms );
258  p->syms = NULL;
259  }
260 
261  /*
262  * Free tables, levels
263  */
264  syck_st_free( p );
266  S_FREE( p->levels[0].domain );
267  S_FREE( p->levels );
268 
269  if ( p->buffer != NULL )
270  {
271  S_FREE( p->buffer );
272  }
273  free_any_io( p );
274  S_FREE( p );
275 }
276 
277 void
279 {
280  ASSERT( p != NULL );
281  p->handler = hdlr;
282 }
283 
284 void
286 {
287  p->implicit_typing = ( flag == 0 ? 0 : 1 );
288 }
289 
290 void
292 {
293  p->taguri_expansion = ( flag == 0 ? 0 : 1 );
294 }
295 
296 void
298 {
299  ASSERT( p != NULL );
300  p->error_handler = hdlr;
301 }
302 
303 void
305 {
306  ASSERT( p != NULL );
307  p->bad_anchor_handler = hdlr;
308 }
309 
310 void
312 {
313  ASSERT( p != NULL );
314  p->input_type = input_type;
315 }
316 
317 void
319 {
320  ASSERT( p != NULL );
321  free_any_io( p );
323  p->io_type = syck_io_file;
324  p->io.file = S_ALLOC( SyckIoFile );
325  p->io.file->ptr = fp;
326  if ( read != NULL )
327  {
328  p->io.file->read = read;
329  }
330  else
331  {
333  }
334 }
335 
336 void
337 syck_parser_str( SyckParser *p, char *ptr, long len, SyckIoStrRead read )
338 {
339  ASSERT( p != NULL );
340  free_any_io( 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;
347  if ( read != NULL )
348  {
349  p->io.str->read = read;
350  }
351  else
352  {
353  p->io.str->read = syck_io_str_read;
354  }
355 }
356 
357 void
359 {
360  syck_parser_str( p, ptr, strlen( ptr ), read );
361 }
362 
363 SyckLevel *
365 {
366  return &p->levels[p->lvl_idx-1];
367 }
368 
369 void
371 {
372  ASSERT( p != NULL );
373 
374  /* The root level should never be popped */
375  if ( p->lvl_idx <= 1 ) return;
376 
377  p->lvl_idx -= 1;
378  free( p->levels[p->lvl_idx].domain );
379 }
380 
381 void
383 {
384  ASSERT( p != NULL );
385  if ( p->lvl_idx + 1 > p->lvl_capa )
386  {
387  p->lvl_capa += ALLOC_CT;
389  }
390 
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;
396  p->lvl_idx += 1;
397 }
398 
399 void
401 {
402  ASSERT( p != NULL );
403  switch ( p->io_type )
404  {
405  case syck_io_str:
406  if ( p->io.str != NULL )
407  {
408  S_FREE( p->io.str );
409  p->io.str = NULL;
410  }
411  break;
412 
413  case syck_io_file:
414  if ( p->io.file != NULL )
415  {
416  S_FREE( p->io.file );
417  p->io.file = NULL;
418  }
419  break;
420  }
421 }
422 
423 long
425 {
426  long count, skip;
427  ASSERT( p->buffer != NULL );
428 
429  if ( p->token == NULL )
430  return 0;
431 
432  skip = p->limit - p->token;
433  if ( ( count = p->token - p->buffer ) )
434  {
435  if (skip > 0)
436  S_MEMMOVE( p->buffer, p->token, char, skip );
437  p->token = p->buffer;
438  p->marker -= count;
439  p->cursor -= count;
440  p->toktmp -= count;
441  p->limit -= count;
442  p->lineptr -= count;
443  p->linectptr -= count;
444  }
445  return skip;
446 }
447 
448 void
450 {
451  if ( p->cursor == NULL )
452  {
453  p->cursor = p->buffer;
454  p->lineptr = p->buffer;
455  p->linectptr = p->buffer;
456  p->marker = p->buffer;
457  }
458  p->limit = p->buffer + len;
459 }
460 
461 long
463 {
464  long len = 0;
465  long skip = 0;
466  ASSERT( p != NULL );
467  switch ( p->io_type )
468  {
469  case syck_io_str:
470  skip = syck_move_tokens( p );
471  len = (p->io.str->read)( p->buffer, p->io.str, SYCK_BUFFERSIZE - 1, skip );
472  break;
473 
474  case syck_io_file:
475  skip = syck_move_tokens( p );
476  len = (p->io.file->read)( p->buffer, p->io.file, SYCK_BUFFERSIZE - 1, skip );
477  break;
478  }
479  syck_check_limit( p, len );
480  return len;
481 }
482 
483 long
484 syck_parser_readlen( SyckParser *p, long max_size )
485 {
486  long len = 0;
487  long skip = 0;
488  ASSERT( p != NULL );
489  switch ( p->io_type )
490  {
491  case syck_io_str:
492  skip = syck_move_tokens( p );
493  len = (p->io.str->read)( p->buffer, p->io.str, max_size, skip );
494  break;
495 
496  case syck_io_file:
497  skip = syck_move_tokens( p );
498  len = (p->io.file->read)( p->buffer, p->io.file, max_size, skip );
499  break;
500  }
501  syck_check_limit( p, len );
502  return len;
503 }
504 
505 SYMID
507 {
508  ASSERT( p != NULL );
509 
510  syck_st_free( p );
512  syckparse( p );
513  return p->root;
514 }
515 
516 void
518 {
519  printf( "Error at [Line %d, Col %"PRIdPTRDIFF"]: %s\n",
520  p->linect,
521  p->cursor - p->lineptr,
522  msg );
523 }
524 
525