Ruby
1.9.3p429(2013-05-15revision40747)
Main Page
Modules
Data Structures
Files
File List
Globals
ext
syck
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
15
void
syck_parser_pop_level
(
SyckParser
* );
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
101
syck_parser_reset_levels
(
SyckParser
*
p
)
102
{
103
while
( p->
lvl_idx
> 1 )
104
{
105
syck_parser_pop_level
( p );
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
119
syck_parser_reset_cursor
(
SyckParser
*
p
)
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
148
syck_parser_set_root_on_error
(
SyckParser
*
p
,
SYMID
roer )
149
{
150
p->
root_on_error
= roer;
151
}
152
153
/*
154
* Allocate the parser
155
*/
156
SyckParser
*
157
syck_new_parser
(
void
)
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
);
164
p->
input_type
=
syck_yaml_utf8
;
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;
172
p->
bufsize
=
SYCK_BUFFERSIZE
;
173
p->
buffer
=
NULL
;
174
p->
lvl_idx
= 0;
175
syck_parser_reset_levels
( p );
176
return
p
;
177
}
178
179
int
180
syck_add_sym
(
SyckParser
*
p
,
void
*
data
)
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
212
syck_st_free
(
SyckParser
*
p
)
213
{
214
/*
215
* Free the anchor tables
216
*/
217
if
( p->
anchors
!=
NULL
)
218
{
219
st_foreach
( p->
anchors
,
syck_st_free_nodes
, 0 );
220
st_free_table
( p->
anchors
);
221
p->
anchors
=
NULL
;
222
}
223
224
if
( p->
bad_anchors
!=
NULL
)
225
{
226
st_foreach
( p->
bad_anchors
,
syck_st_free_nodes
, 0 );
227
st_free_table
( p->
bad_anchors
);
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
249
syck_free_parser
(
SyckParser
*
p
)
250
{
251
/*
252
* Free the adhoc symbol table
253
*/
254
if
( p->
syms
!=
NULL
)
255
{
256
st_foreach
( p->
syms
,
syck_st_free_syms
, 0 );
257
st_free_table
( p->
syms
);
258
p->
syms
=
NULL
;
259
}
260
261
/*
262
* Free tables, levels
263
*/
264
syck_st_free
( p );
265
syck_parser_reset_levels
( 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
278
syck_parser_handler
(
SyckParser
*
p
,
SyckNodeHandler
hdlr )
279
{
280
ASSERT
( p !=
NULL
);
281
p->
handler
= hdlr;
282
}
283
284
void
285
syck_parser_implicit_typing
(
SyckParser
*
p
,
int
flag )
286
{
287
p->
implicit_typing
= ( flag == 0 ? 0 : 1 );
288
}
289
290
void
291
syck_parser_taguri_expansion
(
SyckParser
*
p
,
int
flag )
292
{
293
p->
taguri_expansion
= ( flag == 0 ? 0 : 1 );
294
}
295
296
void
297
syck_parser_error_handler
(
SyckParser
*
p
,
SyckErrorHandler
hdlr )
298
{
299
ASSERT
( p !=
NULL
);
300
p->
error_handler
= hdlr;
301
}
302
303
void
304
syck_parser_bad_anchor_handler
(
SyckParser
*
p
,
SyckBadAnchorHandler
hdlr )
305
{
306
ASSERT
( p !=
NULL
);
307
p->
bad_anchor_handler
= hdlr;
308
}
309
310
void
311
syck_parser_set_input_type
(
SyckParser
*
p
,
enum
syck_parser_input
input_type )
312
{
313
ASSERT
( p !=
NULL
);
314
p->
input_type
= input_type;
315
}
316
317
void
318
syck_parser_file
(
SyckParser
*
p
,
FILE
*fp,
SyckIoFileRead
read )
319
{
320
ASSERT
( p !=
NULL
);
321
free_any_io
( p );
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;
326
if
( read !=
NULL
)
327
{
328
p->
io
.
file
->
read
= read;
329
}
330
else
331
{
332
p->
io
.
file
->
read
=
syck_io_file_read
;
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 );
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
;
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
358
syck_parser_str_auto
(
SyckParser
*
p
,
char
*ptr,
SyckIoStrRead
read )
359
{
360
syck_parser_str
( p, ptr,
strlen
( ptr ), read );
361
}
362
363
SyckLevel
*
364
syck_parser_current_level
(
SyckParser
*
p
)
365
{
366
return
&p->
levels
[p->
lvl_idx
-1];
367
}
368
369
void
370
syck_parser_pop_level
(
SyckParser
*
p
)
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
382
syck_parser_add_level
(
SyckParser
*
p
,
int
len
,
enum
syck_level_status
status )
383
{
384
ASSERT
( p !=
NULL
);
385
if
( p->
lvl_idx
+ 1 > p->
lvl_capa
)
386
{
387
p->
lvl_capa
+=
ALLOC_CT
;
388
S_REALLOC_N
( p->
levels
,
SyckLevel
, p->
lvl_capa
);
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
400
free_any_io
(
SyckParser
*
p
)
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
424
syck_move_tokens
(
SyckParser
*
p
)
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
449
syck_check_limit
(
SyckParser
*
p
,
long
len
)
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
462
syck_parser_read
(
SyckParser
*
p
)
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
506
syck_parse
(
SyckParser
*
p
)
507
{
508
ASSERT
( p !=
NULL
);
509
510
syck_st_free
( p );
511
syck_parser_reset_levels
( p );
512
syckparse
( p );
513
return
p->
root
;
514
}
515
516
void
517
syck_default_error_handler
(
SyckParser
*
p
,
const
char
*
msg
)
518
{
519
printf(
"Error at [Line %d, Col %"
PRIdPTRDIFF
"]: %s\n"
,
520
p->
linect
,
521
p->
cursor
- p->
lineptr
,
522
msg );
523
}
524
525
Generated on Thu May 23 2013 20:33:07 for Ruby by
1.8.3