mkrf 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (186) hide show
  1. data/CHANGELOG +2 -0
  2. data/MIT-LICENSE +7 -0
  3. data/README +54 -0
  4. data/Rakefile +107 -0
  5. data/lib/mkrf.rb +4 -0
  6. data/lib/mkrf/availability.rb +219 -0
  7. data/lib/mkrf/generator.rb +146 -0
  8. data/test/abstract_unit.rb +4 -0
  9. data/test/fixtures/down_a_directory/header_down_a_directory.h +1 -0
  10. data/test/fixtures/stdmkrf.h +1 -0
  11. data/test/sample_files/libtrivial/Rakefile +31 -0
  12. data/test/sample_files/libtrivial/extconf.rb +3 -0
  13. data/test/sample_files/libtrivial/lib/libtrivial.c +5 -0
  14. data/test/sample_files/libtrivial/lib/libtrivial.o +0 -0
  15. data/test/sample_files/libtrivial/libtrivial_so.bundle +0 -0
  16. data/test/sample_files/libtrivial/mkrf.log +1 -0
  17. data/test/sample_files/libxml-ruby-0.3.8/CHANGELOG +74 -0
  18. data/test/sample_files/libxml-ruby-0.3.8/LICENSE +22 -0
  19. data/test/sample_files/libxml-ruby-0.3.8/README +144 -0
  20. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/cbg.c +76 -0
  21. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/extconf.rb +49 -0
  22. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/libxml.c +86 -0
  23. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/libxml.h +82 -0
  24. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/libxml.rb +107 -0
  25. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/mkrf.log +1 -0
  26. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/old_extconf.rb +95 -0
  27. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_attr.c +372 -0
  28. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_attr.h +21 -0
  29. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_attribute.c +224 -0
  30. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_attribute.h +21 -0
  31. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_document.c +1159 -0
  32. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_document.h +27 -0
  33. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_dtd.c +168 -0
  34. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_dtd.h +17 -0
  35. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_input_cbg.c +167 -0
  36. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_input_cbg.h +21 -0
  37. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_node.c +2139 -0
  38. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_node.h +28 -0
  39. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_node_set.c +248 -0
  40. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_node_set.h +26 -0
  41. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_ns.c +153 -0
  42. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_ns.h +21 -0
  43. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_parser.c +1417 -0
  44. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_parser.h +31 -0
  45. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_parser_context.c +715 -0
  46. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_parser_context.h +22 -0
  47. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_sax_parser.c +426 -0
  48. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_sax_parser.h +52 -0
  49. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_schema.c +142 -0
  50. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_schema.h +16 -0
  51. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_tree.c +43 -0
  52. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_tree.h +12 -0
  53. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_xinclude.c +20 -0
  54. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_xinclude.h +13 -0
  55. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_xpath.c +363 -0
  56. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_xpath.h +24 -0
  57. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_xpath_context.c +125 -0
  58. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_xpath_context.h +24 -0
  59. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_xpointer.c +100 -0
  60. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_xpointer.h +27 -0
  61. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_xpointer_context.c +21 -0
  62. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/ruby_xml_xpointer_context.h +18 -0
  63. data/test/sample_files/libxml-ruby-0.3.8/ext/xml/sax_parser_callbacks.inc +202 -0
  64. data/test/sample_files/syck-0.55/CHANGELOG +186 -0
  65. data/test/sample_files/syck-0.55/COPYING +54 -0
  66. data/test/sample_files/syck-0.55/Makefile +582 -0
  67. data/test/sample_files/syck-0.55/Makefile.am +5 -0
  68. data/test/sample_files/syck-0.55/Makefile.in +582 -0
  69. data/test/sample_files/syck-0.55/README +105 -0
  70. data/test/sample_files/syck-0.55/README.BYTECODE +484 -0
  71. data/test/sample_files/syck-0.55/README.EXT +444 -0
  72. data/test/sample_files/syck-0.55/RELEASE +123 -0
  73. data/test/sample_files/syck-0.55/TODO +25 -0
  74. data/test/sample_files/syck-0.55/aclocal.m4 +883 -0
  75. data/test/sample_files/syck-0.55/bootstrap +7 -0
  76. data/test/sample_files/syck-0.55/config.h +79 -0
  77. data/test/sample_files/syck-0.55/config.h.in +78 -0
  78. data/test/sample_files/syck-0.55/config.status +1197 -0
  79. data/test/sample_files/syck-0.55/config/README +14 -0
  80. data/test/sample_files/syck-0.55/config/depcomp +529 -0
  81. data/test/sample_files/syck-0.55/config/install-sh +323 -0
  82. data/test/sample_files/syck-0.55/config/missing +357 -0
  83. data/test/sample_files/syck-0.55/configure +6728 -0
  84. data/test/sample_files/syck-0.55/configure.in +36 -0
  85. data/test/sample_files/syck-0.55/ext/ruby/CHANGELOG +303 -0
  86. data/test/sample_files/syck-0.55/ext/ruby/README +400 -0
  87. data/test/sample_files/syck-0.55/ext/ruby/ext/syck/MANIFEST +1 -0
  88. data/test/sample_files/syck-0.55/ext/ruby/ext/syck/bytecode.c +1170 -0
  89. data/test/sample_files/syck-0.55/ext/ruby/ext/syck/emitter.c +1224 -0
  90. data/test/sample_files/syck-0.55/ext/ruby/ext/syck/extconf.rb +10 -0
  91. data/test/sample_files/syck-0.55/ext/ruby/ext/syck/gram.c +1894 -0
  92. data/test/sample_files/syck-0.55/ext/ruby/ext/syck/gram.h +79 -0
  93. data/test/sample_files/syck-0.55/ext/ruby/ext/syck/handler.c +174 -0
  94. data/test/sample_files/syck-0.55/ext/ruby/ext/syck/implicit.c +2989 -0
  95. data/test/sample_files/syck-0.55/ext/ruby/ext/syck/mkrf.log +1 -0
  96. data/test/sample_files/syck-0.55/ext/ruby/ext/syck/node.c +407 -0
  97. data/test/sample_files/syck-0.55/ext/ruby/ext/syck/rubyext.c +2385 -0
  98. data/test/sample_files/syck-0.55/ext/ruby/ext/syck/syck.c +504 -0
  99. data/test/sample_files/syck-0.55/ext/ruby/ext/syck/syck.h +458 -0
  100. data/test/sample_files/syck-0.55/ext/ruby/ext/syck/token.c +2707 -0
  101. data/test/sample_files/syck-0.55/ext/ruby/ext/syck/yaml2byte.c +250 -0
  102. data/test/sample_files/syck-0.55/ext/ruby/ext/syck/yamlbyte.h +170 -0
  103. data/test/sample_files/syck-0.55/ext/ruby/install.rb +1022 -0
  104. data/test/sample_files/syck-0.55/ext/ruby/lib/okay.rb +161 -0
  105. data/test/sample_files/syck-0.55/ext/ruby/lib/okay/news.rb +69 -0
  106. data/test/sample_files/syck-0.55/ext/ruby/lib/okay/rpc.rb +434 -0
  107. data/test/sample_files/syck-0.55/ext/ruby/lib/yaml.rb +436 -0
  108. data/test/sample_files/syck-0.55/ext/ruby/lib/yaml/baseemitter.rb +247 -0
  109. data/test/sample_files/syck-0.55/ext/ruby/lib/yaml/basenode.rb +216 -0
  110. data/test/sample_files/syck-0.55/ext/ruby/lib/yaml/compat.rb +26 -0
  111. data/test/sample_files/syck-0.55/ext/ruby/lib/yaml/constants.rb +45 -0
  112. data/test/sample_files/syck-0.55/ext/ruby/lib/yaml/dbm.rb +111 -0
  113. data/test/sample_files/syck-0.55/ext/ruby/lib/yaml/emitter.rb +107 -0
  114. data/test/sample_files/syck-0.55/ext/ruby/lib/yaml/encoding.rb +33 -0
  115. data/test/sample_files/syck-0.55/ext/ruby/lib/yaml/error.rb +34 -0
  116. data/test/sample_files/syck-0.55/ext/ruby/lib/yaml/rubytypes.rb +438 -0
  117. data/test/sample_files/syck-0.55/ext/ruby/lib/yaml/store.rb +29 -0
  118. data/test/sample_files/syck-0.55/ext/ruby/lib/yaml/stream.rb +40 -0
  119. data/test/sample_files/syck-0.55/ext/ruby/lib/yaml/stringio.rb +83 -0
  120. data/test/sample_files/syck-0.55/ext/ruby/lib/yaml/syck.rb +19 -0
  121. data/test/sample_files/syck-0.55/ext/ruby/lib/yaml/tag.rb +86 -0
  122. data/test/sample_files/syck-0.55/ext/ruby/lib/yaml/types.rb +188 -0
  123. data/test/sample_files/syck-0.55/ext/ruby/lib/yaml/yamlnode.rb +54 -0
  124. data/test/sample_files/syck-0.55/ext/ruby/lib/yaml/ypath.rb +52 -0
  125. data/test/sample_files/syck-0.55/ext/ruby/lib/yod.rb +1168 -0
  126. data/test/sample_files/syck-0.55/ext/ruby/samples/okayNews-modules.rb +27 -0
  127. data/test/sample_files/syck-0.55/ext/ruby/samples/okayNews-sample.rb +336 -0
  128. data/test/sample_files/syck-0.55/ext/ruby/samples/okayNews-validate.rb +341 -0
  129. data/test/sample_files/syck-0.55/ext/ruby/samples/okayRpc-client.rb +51 -0
  130. data/test/sample_files/syck-0.55/ext/ruby/samples/okayRpc-server.rb +85 -0
  131. data/test/sample_files/syck-0.55/ext/ruby/samples/yaml-sortHashKeys.rb +128 -0
  132. data/test/sample_files/syck-0.55/ext/ruby/tests/basic.rb +1653 -0
  133. data/test/sample_files/syck-0.55/ext/ruby/yts/YtsAnchorAlias.yml +51 -0
  134. data/test/sample_files/syck-0.55/ext/ruby/yts/YtsBasicTests.yml +282 -0
  135. data/test/sample_files/syck-0.55/ext/ruby/yts/YtsBlockMapping.yml +78 -0
  136. data/test/sample_files/syck-0.55/ext/ruby/yts/YtsBlockSequence.yml +0 -0
  137. data/test/sample_files/syck-0.55/ext/ruby/yts/YtsDocumentSeparator.yml +102 -0
  138. data/test/sample_files/syck-0.55/ext/ruby/yts/YtsErrorTests.yml +23 -0
  139. data/test/sample_files/syck-0.55/ext/ruby/yts/YtsFlowCollections.yml +73 -0
  140. data/test/sample_files/syck-0.55/ext/ruby/yts/YtsFoldedScalars.yml +215 -0
  141. data/test/sample_files/syck-0.55/ext/ruby/yts/YtsMapInSeq.yml +0 -0
  142. data/test/sample_files/syck-0.55/ext/ruby/yts/YtsNullsAndEmpties.yml +66 -0
  143. data/test/sample_files/syck-0.55/ext/ruby/yts/YtsRubyTests.yml +182 -0
  144. data/test/sample_files/syck-0.55/ext/ruby/yts/YtsSpecificationExamples.yml +2699 -0
  145. data/test/sample_files/syck-0.55/ext/ruby/yts/YtsTypeTransfers.yml +265 -0
  146. data/test/sample_files/syck-0.55/ext/ruby/yts/YtsYpath.yml +221 -0
  147. data/test/sample_files/syck-0.55/ext/ruby/yts/cookbook.rb +159 -0
  148. data/test/sample_files/syck-0.55/ext/ruby/yts/index.yml +10 -0
  149. data/test/sample_files/syck-0.55/ext/ruby/yts/yts.rb +193 -0
  150. data/test/sample_files/syck-0.55/lib/Makefile +497 -0
  151. data/test/sample_files/syck-0.55/lib/Makefile.am +27 -0
  152. data/test/sample_files/syck-0.55/lib/Makefile.in +497 -0
  153. data/test/sample_files/syck-0.55/lib/bytecode.c +1170 -0
  154. data/test/sample_files/syck-0.55/lib/bytecode.re +525 -0
  155. data/test/sample_files/syck-0.55/lib/emitter.c +1224 -0
  156. data/test/sample_files/syck-0.55/lib/gram.c +1894 -0
  157. data/test/sample_files/syck-0.55/lib/gram.h +79 -0
  158. data/test/sample_files/syck-0.55/lib/gram.output +2005 -0
  159. data/test/sample_files/syck-0.55/lib/gram.y +481 -0
  160. data/test/sample_files/syck-0.55/lib/handler.c +174 -0
  161. data/test/sample_files/syck-0.55/lib/implicit.c +2989 -0
  162. data/test/sample_files/syck-0.55/lib/implicit.re +206 -0
  163. data/test/sample_files/syck-0.55/lib/node.c +407 -0
  164. data/test/sample_files/syck-0.55/lib/syck.c +504 -0
  165. data/test/sample_files/syck-0.55/lib/syck.h +458 -0
  166. data/test/sample_files/syck-0.55/lib/syck_st.c +577 -0
  167. data/test/sample_files/syck-0.55/lib/syck_st.h +46 -0
  168. data/test/sample_files/syck-0.55/lib/token.c +2707 -0
  169. data/test/sample_files/syck-0.55/lib/token.re +1139 -0
  170. data/test/sample_files/syck-0.55/lib/yaml2byte.c +250 -0
  171. data/test/sample_files/syck-0.55/lib/yamlbyte.h +170 -0
  172. data/test/sample_files/syck-0.55/stamp-h1 +1 -0
  173. data/test/sample_files/syck-0.55/tests/Basic.c +141 -0
  174. data/test/sample_files/syck-0.55/tests/CuTest.c +294 -0
  175. data/test/sample_files/syck-0.55/tests/CuTest.h +84 -0
  176. data/test/sample_files/syck-0.55/tests/Emit.c +87 -0
  177. data/test/sample_files/syck-0.55/tests/Makefile +480 -0
  178. data/test/sample_files/syck-0.55/tests/Makefile.am +13 -0
  179. data/test/sample_files/syck-0.55/tests/Makefile.in +480 -0
  180. data/test/sample_files/syck-0.55/tests/Parse.c +208 -0
  181. data/test/sample_files/syck-0.55/tests/YTS.c +2310 -0
  182. data/test/sample_files/syck-0.55/tests/YTS.c.erb +326 -0
  183. data/test/sample_files/syck-0.55/tests/YTS.c.rb +44 -0
  184. data/test/test_availability.rb +68 -0
  185. data/test/test_generator.rb +74 -0
  186. metadata +252 -0
@@ -0,0 +1 @@
1
+ # Logfile created on Mon Jun 26 15:44:42 PDT 2006 by logger.rb/1.5.2.4
@@ -0,0 +1,407 @@
1
+ /*
2
+ * node.c
3
+ *
4
+ * $Author: why $
5
+ * $Date: 2005/04/13 06:27:54 $
6
+ *
7
+ * Copyright (C) 2003 why the lucky stiff
8
+ */
9
+
10
+ #include "syck.h"
11
+
12
+ /*
13
+ * Node allocation functions
14
+ */
15
+ SyckNode *
16
+ syck_alloc_node( enum syck_kind_tag type )
17
+ {
18
+ SyckNode *s;
19
+
20
+ s = S_ALLOC( SyckNode );
21
+ s->kind = type;
22
+ s->id = 0;
23
+ s->type_id = NULL;
24
+ s->anchor = NULL;
25
+ s->shortcut = NULL;
26
+
27
+ return s;
28
+ }
29
+
30
+ void
31
+ syck_free_node( SyckNode *n )
32
+ {
33
+ syck_free_members( n );
34
+ if ( n->type_id != NULL )
35
+ {
36
+ S_FREE( n->type_id );
37
+ n->type_id = NULL;
38
+ }
39
+ if ( n->anchor != NULL )
40
+ {
41
+ S_FREE( n->anchor );
42
+ n->anchor = NULL;
43
+ }
44
+ S_FREE( n );
45
+ }
46
+
47
+ SyckNode *
48
+ syck_alloc_map()
49
+ {
50
+ SyckNode *n;
51
+ struct SyckMap *m;
52
+
53
+ m = S_ALLOC( struct SyckMap );
54
+ m->style = map_none;
55
+ m->idx = 0;
56
+ m->capa = ALLOC_CT;
57
+ m->keys = S_ALLOC_N( SYMID, m->capa );
58
+ m->values = S_ALLOC_N( SYMID, m->capa );
59
+
60
+ n = syck_alloc_node( syck_map_kind );
61
+ n->data.pairs = m;
62
+
63
+ return n;
64
+ }
65
+
66
+ SyckNode *
67
+ syck_alloc_seq()
68
+ {
69
+ SyckNode *n;
70
+ struct SyckSeq *s;
71
+
72
+ s = S_ALLOC( struct SyckSeq );
73
+ s->style = seq_none;
74
+ s->idx = 0;
75
+ s->capa = ALLOC_CT;
76
+ s->items = S_ALLOC_N( SYMID, s->capa );
77
+
78
+ n = syck_alloc_node( syck_seq_kind );
79
+ n->data.list = s;
80
+
81
+ return n;
82
+ }
83
+
84
+ SyckNode *
85
+ syck_alloc_str()
86
+ {
87
+ SyckNode *n;
88
+ struct SyckStr *s;
89
+
90
+ s = S_ALLOC( struct SyckStr );
91
+ s->len = 0;
92
+ s->ptr = NULL;
93
+ s->style = scalar_none;
94
+
95
+ n = syck_alloc_node( syck_str_kind );
96
+ n->data.str = s;
97
+
98
+ return n;
99
+ }
100
+
101
+ SyckNode *
102
+ syck_new_str( char *str, enum scalar_style style )
103
+ {
104
+ return syck_new_str2( str, strlen( str ), style );
105
+ }
106
+
107
+ SyckNode *
108
+ syck_new_str2( char *str, long len, enum scalar_style style )
109
+ {
110
+ SyckNode *n;
111
+
112
+ n = syck_alloc_str();
113
+ n->data.str->ptr = S_ALLOC_N( char, len + 1 );
114
+ n->data.str->len = len;
115
+ n->data.str->style = style;
116
+ memcpy( n->data.str->ptr, str, len );
117
+ n->data.str->ptr[len] = '\0';
118
+
119
+ return n;
120
+ }
121
+
122
+ void
123
+ syck_replace_str( SyckNode *n, char *str, enum scalar_style style )
124
+ {
125
+ return syck_replace_str2( n, str, strlen( str ), style );
126
+ }
127
+
128
+ void
129
+ syck_replace_str2( SyckNode *n, char *str, long len, enum scalar_style style )
130
+ {
131
+ if ( n->data.str != NULL )
132
+ {
133
+ S_FREE( n->data.str->ptr );
134
+ n->data.str->ptr = NULL;
135
+ n->data.str->len = 0;
136
+ }
137
+ n->data.str->ptr = S_ALLOC_N( char, len + 1 );
138
+ n->data.str->len = len;
139
+ n->data.str->style = style;
140
+ memcpy( n->data.str->ptr, str, len );
141
+ n->data.str->ptr[len] = '\0';
142
+ }
143
+
144
+ void
145
+ syck_str_blow_away_commas( SyckNode *n )
146
+ {
147
+ char *go, *end;
148
+
149
+ go = n->data.str->ptr;
150
+ end = go + n->data.str->len;
151
+ while ( *(++go) != '\0' )
152
+ {
153
+ if ( *go == ',' )
154
+ {
155
+ n->data.str->len -= 1;
156
+ memmove( go, go + 1, end - go );
157
+ end -= 1;
158
+ }
159
+ }
160
+ }
161
+
162
+ char *
163
+ syck_str_read( SyckNode *n )
164
+ {
165
+ ASSERT( n != NULL );
166
+ return n->data.str->ptr;
167
+ }
168
+
169
+ SyckNode *
170
+ syck_new_map( SYMID key, SYMID value )
171
+ {
172
+ SyckNode *n;
173
+
174
+ n = syck_alloc_map();
175
+ syck_map_add( n, key, value );
176
+
177
+ return n;
178
+ }
179
+
180
+ void
181
+ syck_map_empty( SyckNode *n )
182
+ {
183
+ struct SyckMap *m;
184
+ ASSERT( n != NULL );
185
+ ASSERT( n->data.list != NULL );
186
+
187
+ S_FREE( n->data.pairs->keys );
188
+ S_FREE( n->data.pairs->values );
189
+ m = n->data.pairs;
190
+ m->idx = 0;
191
+ m->capa = ALLOC_CT;
192
+ m->keys = S_ALLOC_N( SYMID, m->capa );
193
+ m->values = S_ALLOC_N( SYMID, m->capa );
194
+ }
195
+
196
+ void
197
+ syck_map_add( SyckNode *map, SYMID key, SYMID value )
198
+ {
199
+ struct SyckMap *m;
200
+ long idx;
201
+
202
+ ASSERT( map != NULL );
203
+ ASSERT( map->data.pairs != NULL );
204
+
205
+ m = map->data.pairs;
206
+ idx = m->idx;
207
+ m->idx += 1;
208
+ if ( m->idx > m->capa )
209
+ {
210
+ m->capa += ALLOC_CT;
211
+ S_REALLOC_N( m->keys, SYMID, m->capa );
212
+ S_REALLOC_N( m->values, SYMID, m->capa );
213
+ }
214
+ m->keys[idx] = key;
215
+ m->values[idx] = value;
216
+ }
217
+
218
+ void
219
+ syck_map_update( SyckNode *map1, SyckNode *map2 )
220
+ {
221
+ struct SyckMap *m1, *m2;
222
+ long new_idx, new_capa;
223
+ ASSERT( map1 != NULL );
224
+ ASSERT( map2 != NULL );
225
+
226
+ m1 = map1->data.pairs;
227
+ m2 = map2->data.pairs;
228
+ if ( m2->idx < 1 ) return;
229
+
230
+ new_idx = m1->idx;
231
+ new_idx += m2->idx;
232
+ new_capa = m1->capa;
233
+ while ( new_idx > new_capa )
234
+ {
235
+ new_capa += ALLOC_CT;
236
+ }
237
+ if ( new_capa > m1->capa )
238
+ {
239
+ m1->capa = new_capa;
240
+ S_REALLOC_N( m1->keys, SYMID, m1->capa );
241
+ S_REALLOC_N( m1->values, SYMID, m1->capa );
242
+ }
243
+ for ( new_idx = 0; new_idx < m2->idx; m1->idx++, new_idx++ )
244
+ {
245
+ m1->keys[m1->idx] = m2->keys[new_idx];
246
+ m1->values[m1->idx] = m2->values[new_idx];
247
+ }
248
+ }
249
+
250
+ long
251
+ syck_map_count( SyckNode *map )
252
+ {
253
+ ASSERT( map != NULL );
254
+ ASSERT( map->data.pairs != NULL );
255
+ return map->data.pairs->idx;
256
+ }
257
+
258
+ void
259
+ syck_map_assign( SyckNode *map, enum map_part p, long idx, SYMID id )
260
+ {
261
+ struct SyckMap *m;
262
+
263
+ ASSERT( map != NULL );
264
+ m = map->data.pairs;
265
+ ASSERT( m != NULL );
266
+ if ( p == map_key )
267
+ {
268
+ m->keys[idx] = id;
269
+ }
270
+ else
271
+ {
272
+ m->values[idx] = id;
273
+ }
274
+ }
275
+
276
+ SYMID
277
+ syck_map_read( SyckNode *map, enum map_part p, long idx )
278
+ {
279
+ struct SyckMap *m;
280
+
281
+ ASSERT( map != NULL );
282
+ m = map->data.pairs;
283
+ ASSERT( m != NULL );
284
+ if ( p == map_key )
285
+ {
286
+ return m->keys[idx];
287
+ }
288
+ else
289
+ {
290
+ return m->values[idx];
291
+ }
292
+ }
293
+
294
+ SyckNode *
295
+ syck_new_seq( SYMID value )
296
+ {
297
+ SyckNode *n;
298
+
299
+ n = syck_alloc_seq();
300
+ syck_seq_add( n, value );
301
+
302
+ return n;
303
+ }
304
+
305
+ void
306
+ syck_seq_empty( SyckNode *n )
307
+ {
308
+ struct SyckSeq *s;
309
+ ASSERT( n != NULL );
310
+ ASSERT( n->data.list != NULL );
311
+
312
+ S_FREE( n->data.list->items );
313
+ s = n->data.list;
314
+ s->idx = 0;
315
+ s->capa = ALLOC_CT;
316
+ s->items = S_ALLOC_N( SYMID, s->capa );
317
+ }
318
+
319
+ void
320
+ syck_seq_add( SyckNode *arr, SYMID value )
321
+ {
322
+ struct SyckSeq *s;
323
+ long idx;
324
+
325
+ ASSERT( arr != NULL );
326
+ ASSERT( arr->data.list != NULL );
327
+
328
+ s = arr->data.list;
329
+ idx = s->idx;
330
+ s->idx += 1;
331
+ if ( s->idx > s->capa )
332
+ {
333
+ s->capa += ALLOC_CT;
334
+ S_REALLOC_N( s->items, SYMID, s->capa );
335
+ }
336
+ s->items[idx] = value;
337
+ }
338
+
339
+ long
340
+ syck_seq_count( SyckNode *seq )
341
+ {
342
+ ASSERT( seq != NULL );
343
+ ASSERT( seq->data.list != NULL );
344
+ return seq->data.list->idx;
345
+ }
346
+
347
+ void
348
+ syck_seq_assign( SyckNode *seq, long idx, SYMID id )
349
+ {
350
+ struct SyckSeq *s;
351
+
352
+ ASSERT( map != NULL );
353
+ s = seq->data.list;
354
+ ASSERT( m != NULL );
355
+ s->items[idx] = id;
356
+ }
357
+
358
+ SYMID
359
+ syck_seq_read( SyckNode *seq, long idx )
360
+ {
361
+ struct SyckSeq *s;
362
+
363
+ ASSERT( seq != NULL );
364
+ s = seq->data.list;
365
+ ASSERT( s != NULL );
366
+ return s->items[idx];
367
+ }
368
+
369
+ void
370
+ syck_free_members( SyckNode *n )
371
+ {
372
+ if ( n == NULL ) return;
373
+
374
+ switch ( n->kind )
375
+ {
376
+ case syck_str_kind:
377
+ if ( n->data.str != NULL )
378
+ {
379
+ S_FREE( n->data.str->ptr );
380
+ n->data.str->ptr = NULL;
381
+ n->data.str->len = 0;
382
+ S_FREE( n->data.str );
383
+ n->data.str = NULL;
384
+ }
385
+ break;
386
+
387
+ case syck_seq_kind:
388
+ if ( n->data.list != NULL )
389
+ {
390
+ S_FREE( n->data.list->items );
391
+ S_FREE( n->data.list );
392
+ n->data.list = NULL;
393
+ }
394
+ break;
395
+
396
+ case syck_map_kind:
397
+ if ( n->data.pairs != NULL )
398
+ {
399
+ S_FREE( n->data.pairs->keys );
400
+ S_FREE( n->data.pairs->values );
401
+ S_FREE( n->data.pairs );
402
+ n->data.pairs = NULL;
403
+ }
404
+ break;
405
+ }
406
+ }
407
+
@@ -0,0 +1,2385 @@
1
+ /* -*- indent-tabs-mode: nil -*- */
2
+ /*
3
+ * rubyext.c
4
+ *
5
+ * $Author: why $
6
+ * $Date: 2005/05/19 06:07:42 $
7
+ *
8
+ * Copyright (C) 2003-2005 why the lucky stiff
9
+ */
10
+
11
+ #include "ruby.h"
12
+ #include "syck.h"
13
+ #include <sys/types.h>
14
+ #include <time.h>
15
+
16
+ typedef struct RVALUE {
17
+ union {
18
+ #if 0
19
+ struct {
20
+ unsigned long flags; /* always 0 for freed obj */
21
+ struct RVALUE *next;
22
+ } free;
23
+ #endif
24
+ struct RBasic basic;
25
+ struct RObject object;
26
+ struct RClass klass;
27
+ /*struct RFloat flonum;*/
28
+ /*struct RString string;*/
29
+ struct RArray array;
30
+ /*struct RRegexp regexp;*/
31
+ struct RHash hash;
32
+ /*struct RData data;*/
33
+ struct RStruct rstruct;
34
+ /*struct RBignum bignum;*/
35
+ /*struct RFile file;*/
36
+ } as;
37
+ } RVALUE;
38
+
39
+ typedef struct {
40
+ long hash;
41
+ char *buffer;
42
+ long length;
43
+ long remaining;
44
+ int printed;
45
+ } bytestring_t;
46
+
47
+ #define RUBY_DOMAIN "ruby.yaml.org,2002"
48
+
49
+ #ifndef StringValue
50
+ #define StringValue(v) (v)
51
+ #endif
52
+ #ifndef rb_attr_get
53
+ #define rb_attr_get(o, i) rb_ivar_get(o, i)
54
+ #endif
55
+
56
+ /*
57
+ * symbols and constants
58
+ */
59
+ static ID s_new, s_utc, s_at, s_to_f, s_to_i, s_read, s_binmode, s_call, s_cmp, s_transfer, s_update, s_dup, s_haskey, s_match, s_keys, s_unpack, s_tr_bang, s_default_set, s_tag_read_class, s_tag_subclasses, s_resolver, s_push, s_emitter, s_level, s_detect_implicit, s_node_import, s_out, s_input, s_intern, s_transform, s_yaml_new, s_yaml_initialize, s_node_export, s_to_yaml, s_write, s_set_resolver;
60
+ static ID s_tags, s_domain, s_kind, s_name, s_options, s_type_id, s_type_id_set, s_style, s_style_set, s_value, s_value_set;
61
+ static VALUE sym_model, sym_generic, sym_input, sym_bytecode;
62
+ static VALUE sym_scalar, sym_seq, sym_map;
63
+ static VALUE sym_1quote, sym_2quote, sym_fold, sym_literal, sym_plain, sym_inline;
64
+ static VALUE cDate, cNode, cMap, cSeq, cScalar, cOut, cParser, cResolver, cPrivateType, cDomainType, cYObject, cBadAlias, cDefaultKey, cMergeKey, cEmitter;
65
+ static VALUE oDefaultResolver, oGenericResolver;
66
+
67
+ /*
68
+ * my private collection of numerical oddities.
69
+ */
70
+ static double S_zero() { return 0.0; }
71
+ static double S_one() { return 1.0; }
72
+ static double S_inf() { return S_one() / S_zero(); }
73
+ static double S_nan() { return S_zero() / S_zero(); }
74
+
75
+ static VALUE syck_node_transform( VALUE );
76
+
77
+ /*
78
+ * handler prototypes
79
+ */
80
+ SYMID rb_syck_load_handler _((SyckParser *, SyckNode *));
81
+ void rb_syck_err_handler _((SyckParser *, char *));
82
+ SyckNode * rb_syck_bad_anchor_handler _((SyckParser *, char *));
83
+ void rb_syck_output_handler _((SyckEmitter *, char *, long));
84
+ void rb_syck_emitter_handler _((SyckEmitter *, st_data_t));
85
+ int syck_parser_assign_io _((SyckParser *, VALUE));
86
+
87
+ struct parser_xtra {
88
+ VALUE data; /* Borrowed this idea from marshal.c to fix [ruby-core:8067] problem */
89
+ VALUE proc;
90
+ VALUE resolver;
91
+ int taint;
92
+ };
93
+
94
+ struct emitter_xtra {
95
+ VALUE oid;
96
+ VALUE data;
97
+ VALUE port;
98
+ };
99
+
100
+ /*
101
+ * Convert YAML to bytecode
102
+ */
103
+ VALUE
104
+ rb_syck_compile(self, port)
105
+ VALUE self, port;
106
+ {
107
+ SYMID oid;
108
+ int taint;
109
+ char *ret;
110
+ VALUE bc;
111
+ bytestring_t *sav;
112
+
113
+ SyckParser *parser = syck_new_parser();
114
+ taint = syck_parser_assign_io(parser, port);
115
+ syck_parser_handler( parser, syck_yaml2byte_handler );
116
+ syck_parser_error_handler( parser, NULL );
117
+ syck_parser_implicit_typing( parser, 0 );
118
+ syck_parser_taguri_expansion( parser, 0 );
119
+ oid = syck_parse( parser );
120
+ syck_lookup_sym( parser, oid, (char **)&sav );
121
+
122
+ ret = S_ALLOC_N( char, strlen( sav->buffer ) + 3 );
123
+ ret[0] = '\0';
124
+ strcat( ret, "D\n" );
125
+ strcat( ret, sav->buffer );
126
+
127
+ syck_free_parser( parser );
128
+
129
+ bc = rb_str_new2( ret );
130
+ if ( taint ) OBJ_TAINT( bc );
131
+ return bc;
132
+ }
133
+
134
+ /*
135
+ * read from io.
136
+ */
137
+ long
138
+ rb_syck_io_str_read( char *buf, SyckIoStr *str, long max_size, long skip )
139
+ {
140
+ long len = 0;
141
+
142
+ ASSERT( str != NULL );
143
+ max_size -= skip;
144
+
145
+ if ( max_size <= 0 ) max_size = 0;
146
+ else
147
+ {
148
+ /*
149
+ * call io#read.
150
+ */
151
+ VALUE src = (VALUE)str->ptr;
152
+ VALUE n = LONG2NUM(max_size);
153
+ VALUE str2 = rb_funcall2(src, s_read, 1, &n);
154
+ if (!NIL_P(str2))
155
+ {
156
+ StringValue(str2);
157
+ len = RSTRING(str2)->len;
158
+ memcpy( buf + skip, RSTRING(str2)->ptr, len );
159
+ }
160
+ }
161
+ len += skip;
162
+ buf[len] = '\0';
163
+ return len;
164
+ }
165
+
166
+ /*
167
+ * determine: are we reading from a string or io?
168
+ * (returns tainted? boolean)
169
+ */
170
+ int
171
+ syck_parser_assign_io(parser, port)
172
+ SyckParser *parser;
173
+ VALUE port;
174
+ {
175
+ int taint = Qtrue;
176
+ VALUE tmp;
177
+ if (!NIL_P(tmp = rb_check_string_type(port))) {
178
+ taint = OBJ_TAINTED(port); /* original taintedness */
179
+ port = tmp;
180
+ syck_parser_str( parser, RSTRING(port)->ptr, RSTRING(port)->len, NULL );
181
+ }
182
+ else if (rb_respond_to(port, s_read)) {
183
+ if (rb_respond_to(port, s_binmode)) {
184
+ rb_funcall2(port, s_binmode, 0, 0);
185
+ }
186
+ syck_parser_str( parser, (char *)port, 0, rb_syck_io_str_read );
187
+ }
188
+ else {
189
+ rb_raise(rb_eTypeError, "instance of IO needed");
190
+ }
191
+ return taint;
192
+ }
193
+
194
+ /*
195
+ * Get value in hash by key, forcing an empty hash if nil.
196
+ */
197
+ VALUE
198
+ syck_get_hash_aref(hsh, key)
199
+ VALUE hsh, key;
200
+ {
201
+ VALUE val = rb_hash_aref( hsh, key );
202
+ if ( NIL_P( val ) )
203
+ {
204
+ val = rb_hash_new();
205
+ rb_hash_aset(hsh, key, val);
206
+ }
207
+ return val;
208
+ }
209
+
210
+ /*
211
+ * creating timestamps
212
+ */
213
+ SYMID
214
+ rb_syck_mktime(str, len)
215
+ char *str;
216
+ long len;
217
+ {
218
+ VALUE time;
219
+ char *ptr = str;
220
+ VALUE year = INT2FIX(0);
221
+ VALUE mon = INT2FIX(0);
222
+ VALUE day = INT2FIX(0);
223
+ VALUE hour = INT2FIX(0);
224
+ VALUE min = INT2FIX(0);
225
+ VALUE sec = INT2FIX(0);
226
+ long usec;
227
+
228
+ /* Year*/
229
+ if ( ptr[0] != '\0' && len > 0 ) {
230
+ year = INT2FIX(strtol(ptr, NULL, 10));
231
+ }
232
+
233
+ /* Month*/
234
+ ptr += 4;
235
+ if ( ptr[0] != '\0' && len > ptr - str ) {
236
+ while ( !ISDIGIT( *ptr ) ) ptr++;
237
+ mon = INT2FIX(strtol(ptr, NULL, 10));
238
+ }
239
+
240
+ /* Day*/
241
+ ptr += 2;
242
+ if ( ptr[0] != '\0' && len > ptr - str ) {
243
+ while ( !ISDIGIT( *ptr ) ) ptr++;
244
+ day = INT2FIX(strtol(ptr, NULL, 10));
245
+ }
246
+
247
+ /* Hour*/
248
+ ptr += 2;
249
+ if ( ptr[0] != '\0' && len > ptr - str ) {
250
+ while ( !ISDIGIT( *ptr ) ) ptr++;
251
+ hour = INT2FIX(strtol(ptr, NULL, 10));
252
+ }
253
+
254
+ /* Minute */
255
+ ptr += 2;
256
+ if ( ptr[0] != '\0' && len > ptr - str ) {
257
+ while ( !ISDIGIT( *ptr ) ) ptr++;
258
+ min = INT2FIX(strtol(ptr, NULL, 10));
259
+ }
260
+
261
+ /* Second */
262
+ ptr += 2;
263
+ if ( ptr[0] != '\0' && len > ptr - str ) {
264
+ while ( !ISDIGIT( *ptr ) ) ptr++;
265
+ sec = INT2FIX(strtol(ptr, NULL, 10));
266
+ }
267
+
268
+ /* Millisecond */
269
+ ptr += 2;
270
+ if ( len > ptr - str && *ptr == '.' )
271
+ {
272
+ char *padded = syck_strndup( "000000", 6 );
273
+ char *end = ptr + 1;
274
+ while ( isdigit( *end ) ) end++;
275
+ MEMCPY(padded, ptr + 1, char, end - (ptr + 1));
276
+ usec = strtol(padded, NULL, 10);
277
+ S_FREE(padded);
278
+ }
279
+ else
280
+ {
281
+ usec = 0;
282
+ }
283
+
284
+ /* Time Zone*/
285
+ while ( len > ptr - str && *ptr != 'Z' && *ptr != '+' && *ptr != '-' && *ptr != '\0' ) ptr++;
286
+ if ( len > ptr - str && ( *ptr == '-' || *ptr == '+' ) )
287
+ {
288
+ time_t tz_offset = strtol(ptr, NULL, 10) * 3600;
289
+ time_t tmp;
290
+
291
+ while ( *ptr != ':' && *ptr != '\0' ) ptr++;
292
+ if ( *ptr == ':' )
293
+ {
294
+ ptr += 1;
295
+ if ( tz_offset < 0 )
296
+ {
297
+ tz_offset -= strtol(ptr, NULL, 10) * 60;
298
+ }
299
+ else
300
+ {
301
+ tz_offset += strtol(ptr, NULL, 10) * 60;
302
+ }
303
+ }
304
+
305
+ /* Make TZ time*/
306
+ time = rb_funcall(rb_cTime, s_utc, 6, year, mon, day, hour, min, sec);
307
+ tmp = NUM2LONG(rb_funcall(time, s_to_i, 0)) - tz_offset;
308
+ return rb_funcall(rb_cTime, s_at, 2, LONG2NUM(tmp), LONG2NUM(usec));
309
+ }
310
+ else
311
+ {
312
+ /* Make UTC time*/
313
+ return rb_funcall(rb_cTime, s_utc, 7, year, mon, day, hour, min, sec, LONG2NUM(usec));
314
+ }
315
+ }
316
+
317
+ /*
318
+ * handles merging of an array of hashes
319
+ * (see http://www.yaml.org/type/merge/)
320
+ */
321
+ VALUE
322
+ syck_merge_i( entry, hsh )
323
+ VALUE entry, hsh;
324
+ {
325
+ VALUE tmp;
326
+ if ( !NIL_P(tmp = rb_check_convert_type(entry, T_HASH, "Hash", "to_hash")) )
327
+ {
328
+ entry = tmp;
329
+ rb_funcall( hsh, s_update, 1, entry );
330
+ }
331
+ return Qnil;
332
+ }
333
+
334
+ /*
335
+ * default handler for ruby.yaml.org types
336
+ */
337
+ int
338
+ yaml_org_handler( n, ref )
339
+ SyckNode *n;
340
+ VALUE *ref;
341
+ {
342
+ char *type_id = n->type_id;
343
+ int transferred = 0;
344
+ long i = 0;
345
+ VALUE obj = Qnil;
346
+
347
+ if ( type_id != NULL && strncmp( type_id, "tag:yaml.org,2002:", 18 ) == 0 )
348
+ {
349
+ type_id += 18;
350
+ }
351
+
352
+ switch (n->kind)
353
+ {
354
+ case syck_str_kind:
355
+ transferred = 1;
356
+ if ( type_id == NULL )
357
+ {
358
+ obj = rb_str_new( n->data.str->ptr, n->data.str->len );
359
+ }
360
+ else if ( strcmp( type_id, "null" ) == 0 )
361
+ {
362
+ obj = Qnil;
363
+ }
364
+ else if ( strcmp( type_id, "binary" ) == 0 )
365
+ {
366
+ VALUE arr;
367
+ obj = rb_str_new( n->data.str->ptr, n->data.str->len );
368
+ rb_funcall( obj, s_tr_bang, 2, rb_str_new2( "\n\t " ), rb_str_new2( "" ) );
369
+ arr = rb_funcall( obj, s_unpack, 1, rb_str_new2( "m" ) );
370
+ obj = rb_ary_shift( arr );
371
+ }
372
+ else if ( strcmp( type_id, "bool#yes" ) == 0 )
373
+ {
374
+ obj = Qtrue;
375
+ }
376
+ else if ( strcmp( type_id, "bool#no" ) == 0 )
377
+ {
378
+ obj = Qfalse;
379
+ }
380
+ else if ( strcmp( type_id, "int#hex" ) == 0 )
381
+ {
382
+ syck_str_blow_away_commas( n );
383
+ obj = rb_cstr2inum( n->data.str->ptr, 16 );
384
+ }
385
+ else if ( strcmp( type_id, "int#oct" ) == 0 )
386
+ {
387
+ syck_str_blow_away_commas( n );
388
+ obj = rb_cstr2inum( n->data.str->ptr, 8 );
389
+ }
390
+ else if ( strcmp( type_id, "int#base60" ) == 0 )
391
+ {
392
+ char *ptr, *end;
393
+ long sixty = 1;
394
+ long total = 0;
395
+ syck_str_blow_away_commas( n );
396
+ ptr = n->data.str->ptr;
397
+ end = n->data.str->ptr + n->data.str->len;
398
+ while ( end > ptr )
399
+ {
400
+ long bnum = 0;
401
+ char *colon = end - 1;
402
+ while ( colon >= ptr && *colon != ':' )
403
+ {
404
+ colon--;
405
+ }
406
+ if ( *colon == ':' ) *colon = '\0';
407
+
408
+ bnum = strtol( colon + 1, NULL, 10 );
409
+ total += bnum * sixty;
410
+ sixty *= 60;
411
+ end = colon;
412
+ }
413
+ obj = INT2FIX(total);
414
+ }
415
+ else if ( strncmp( type_id, "int", 3 ) == 0 )
416
+ {
417
+ syck_str_blow_away_commas( n );
418
+ obj = rb_cstr2inum( n->data.str->ptr, 10 );
419
+ }
420
+ else if ( strcmp( type_id, "float#base60" ) == 0 )
421
+ {
422
+ char *ptr, *end;
423
+ long sixty = 1;
424
+ double total = 0.0;
425
+ syck_str_blow_away_commas( n );
426
+ ptr = n->data.str->ptr;
427
+ end = n->data.str->ptr + n->data.str->len;
428
+ while ( end > ptr )
429
+ {
430
+ double bnum = 0;
431
+ char *colon = end - 1;
432
+ while ( colon >= ptr && *colon != ':' )
433
+ {
434
+ colon--;
435
+ }
436
+ if ( *colon == ':' ) *colon = '\0';
437
+
438
+ bnum = strtod( colon + 1, NULL );
439
+ total += bnum * sixty;
440
+ sixty *= 60;
441
+ end = colon;
442
+ }
443
+ obj = rb_float_new( total );
444
+ }
445
+ else if ( strcmp( type_id, "float#nan" ) == 0 )
446
+ {
447
+ obj = rb_float_new( S_nan() );
448
+ }
449
+ else if ( strcmp( type_id, "float#inf" ) == 0 )
450
+ {
451
+ obj = rb_float_new( S_inf() );
452
+ }
453
+ else if ( strcmp( type_id, "float#neginf" ) == 0 )
454
+ {
455
+ obj = rb_float_new( -S_inf() );
456
+ }
457
+ else if ( strncmp( type_id, "float", 5 ) == 0 )
458
+ {
459
+ double f;
460
+ syck_str_blow_away_commas( n );
461
+ f = strtod( n->data.str->ptr, NULL );
462
+ obj = rb_float_new( f );
463
+ }
464
+ else if ( strcmp( type_id, "timestamp#iso8601" ) == 0 )
465
+ {
466
+ obj = rb_syck_mktime( n->data.str->ptr, n->data.str->len );
467
+ }
468
+ else if ( strcmp( type_id, "timestamp#spaced" ) == 0 )
469
+ {
470
+ obj = rb_syck_mktime( n->data.str->ptr, n->data.str->len );
471
+ }
472
+ else if ( strcmp( type_id, "timestamp#ymd" ) == 0 )
473
+ {
474
+ char *ptr = n->data.str->ptr;
475
+ VALUE year, mon, day;
476
+
477
+ /* Year*/
478
+ ptr[4] = '\0';
479
+ year = INT2FIX(strtol(ptr, NULL, 10));
480
+
481
+ /* Month*/
482
+ ptr += 4;
483
+ while ( !ISDIGIT( *ptr ) ) ptr++;
484
+ mon = INT2FIX(strtol(ptr, NULL, 10));
485
+
486
+ /* Day*/
487
+ ptr += 2;
488
+ while ( !ISDIGIT( *ptr ) ) ptr++;
489
+ day = INT2FIX(strtol(ptr, NULL, 10));
490
+
491
+ if ( !cDate ) {
492
+ /*
493
+ * Load Date module
494
+ */
495
+ rb_require( "date" );
496
+ cDate = rb_const_get( rb_cObject, rb_intern("Date") );
497
+ }
498
+
499
+ obj = rb_funcall( cDate, s_new, 3, year, mon, day );
500
+ }
501
+ else if ( strncmp( type_id, "timestamp", 9 ) == 0 )
502
+ {
503
+ obj = rb_syck_mktime( n->data.str->ptr, n->data.str->len );
504
+ }
505
+ else if ( strncmp( type_id, "merge", 5 ) == 0 )
506
+ {
507
+ obj = rb_funcall( cMergeKey, s_new, 0 );
508
+ }
509
+ else if ( strncmp( type_id, "default", 7 ) == 0 )
510
+ {
511
+ obj = rb_funcall( cDefaultKey, s_new, 0 );
512
+ }
513
+ else if ( n->data.str->style == scalar_plain &&
514
+ n->data.str->len > 1 &&
515
+ strncmp( n->data.str->ptr, ":", 1 ) == 0 )
516
+ {
517
+ obj = rb_funcall( oDefaultResolver, s_transfer, 2,
518
+ rb_str_new2( "tag:ruby.yaml.org,2002:sym" ),
519
+ rb_str_new( n->data.str->ptr + 1, n->data.str->len - 1 ) );
520
+ }
521
+ else if ( strcmp( type_id, "str" ) == 0 )
522
+ {
523
+ obj = rb_str_new( n->data.str->ptr, n->data.str->len );
524
+ }
525
+ else
526
+ {
527
+ transferred = 0;
528
+ obj = rb_str_new( n->data.str->ptr, n->data.str->len );
529
+ }
530
+ break;
531
+
532
+ case syck_seq_kind:
533
+ if ( type_id == NULL || strcmp( type_id, "seq" ) == 0 )
534
+ {
535
+ transferred = 1;
536
+ }
537
+ obj = rb_ary_new2( n->data.list->idx );
538
+ for ( i = 0; i < n->data.list->idx; i++ )
539
+ {
540
+ rb_ary_store( obj, i, syck_seq_read( n, i ) );
541
+ }
542
+ break;
543
+
544
+ case syck_map_kind:
545
+ if ( type_id == NULL || strcmp( type_id, "map" ) == 0 )
546
+ {
547
+ transferred = 1;
548
+ }
549
+ obj = rb_hash_new();
550
+ for ( i = 0; i < n->data.pairs->idx; i++ )
551
+ {
552
+ VALUE k = syck_map_read( n, map_key, i );
553
+ VALUE v = syck_map_read( n, map_value, i );
554
+ int skip_aset = 0;
555
+
556
+ /*
557
+ * Handle merge keys
558
+ */
559
+ if ( rb_obj_is_kind_of( k, cMergeKey ) )
560
+ {
561
+ VALUE tmp;
562
+ if ( !NIL_P(tmp = rb_check_convert_type(v, T_HASH, "Hash", "to_hash")) )
563
+ {
564
+ VALUE dup = rb_funcall( tmp, s_dup, 0 );
565
+ rb_funcall( dup, s_update, 1, obj );
566
+ obj = dup;
567
+ skip_aset = 1;
568
+ }
569
+ else if ( !NIL_P(tmp = rb_check_array_type(v)) )
570
+ {
571
+ VALUE end = rb_ary_pop( tmp );
572
+ VALUE tmph = rb_check_convert_type(end, T_HASH, "Hash", "to_hash");
573
+ if ( !NIL_P(tmph) )
574
+ {
575
+ VALUE dup = rb_funcall( tmph, s_dup, 0 );
576
+ tmp = rb_ary_reverse( tmp );
577
+ rb_ary_push( tmp, obj );
578
+ rb_iterate( rb_each, tmp, syck_merge_i, dup );
579
+ obj = dup;
580
+ skip_aset = 1;
581
+ }
582
+ }
583
+ }
584
+ else if ( rb_obj_is_kind_of( k, cDefaultKey ) )
585
+ {
586
+ rb_funcall( obj, s_default_set, 1, v );
587
+ skip_aset = 1;
588
+ }
589
+
590
+ if ( ! skip_aset )
591
+ {
592
+ rb_hash_aset( obj, k, v );
593
+ }
594
+ }
595
+ break;
596
+ }
597
+
598
+ *ref = obj;
599
+ return transferred;
600
+ }
601
+
602
+ /*
603
+ * {native mode} node handler
604
+ * - Converts data into native Ruby types
605
+ */
606
+ SYMID
607
+ rb_syck_load_handler(p, n)
608
+ SyckParser *p;
609
+ SyckNode *n;
610
+ {
611
+ VALUE obj = Qnil;
612
+ struct parser_xtra *bonus = (struct parser_xtra *)p->bonus;
613
+ VALUE resolver = bonus->resolver;
614
+ if ( NIL_P( resolver ) )
615
+ {
616
+ resolver = oDefaultResolver;
617
+ }
618
+
619
+ /*
620
+ * Create node,
621
+ */
622
+ obj = rb_funcall( resolver, s_node_import, 1, Data_Wrap_Struct( cNode, NULL, NULL, n ) );
623
+
624
+ /*
625
+ * ID already set, let's alter the symbol table to accept the new object
626
+ */
627
+ if (n->id > 0 && !NIL_P(obj))
628
+ {
629
+ MEMCPY((void *)n->id, (void *)obj, RVALUE, 1);
630
+ MEMZERO((void *)obj, RVALUE, 1);
631
+ obj = n->id;
632
+ }
633
+
634
+ if ( bonus->taint) OBJ_TAINT( obj );
635
+ if ( bonus->proc != 0 ) rb_funcall(bonus->proc, s_call, 1, obj);
636
+
637
+ rb_hash_aset(bonus->data, INT2FIX(RHASH(bonus->data)->tbl->num_entries), obj);
638
+ return obj;
639
+ }
640
+
641
+ /*
642
+ * friendly errors.
643
+ */
644
+ void
645
+ rb_syck_err_handler(p, msg)
646
+ SyckParser *p;
647
+ char *msg;
648
+ {
649
+ char *endl = p->cursor;
650
+
651
+ while ( *endl != '\0' && *endl != '\n' )
652
+ endl++;
653
+
654
+ endl[0] = '\0';
655
+ rb_raise(rb_eArgError, "%s on line %d, col %d: `%s'",
656
+ msg,
657
+ p->linect,
658
+ p->cursor - p->lineptr,
659
+ p->lineptr);
660
+ }
661
+
662
+ /*
663
+ * provide bad anchor object to the parser.
664
+ */
665
+ SyckNode *
666
+ rb_syck_bad_anchor_handler(p, a)
667
+ SyckParser *p;
668
+ char *a;
669
+ {
670
+ VALUE anchor_name = rb_str_new2( a );
671
+ SyckNode *badanc = syck_new_map( rb_str_new2( "name" ), anchor_name );
672
+ badanc->type_id = syck_strndup( "tag:ruby.yaml.org,2002:object:YAML::Syck::BadAlias", 53 );
673
+ return badanc;
674
+ }
675
+
676
+ /*
677
+ * data loaded based on the model requested.
678
+ */
679
+ void
680
+ syck_set_model( p, input, model )
681
+ VALUE p, input, model;
682
+ {
683
+ SyckParser *parser;
684
+ Data_Get_Struct(p, SyckParser, parser);
685
+ syck_parser_handler( parser, rb_syck_load_handler );
686
+ /* WARN: gonna be obsoleted soon!! */
687
+ if ( model == sym_generic )
688
+ {
689
+ rb_funcall( p, s_set_resolver, 1, oGenericResolver );
690
+ }
691
+ syck_parser_implicit_typing( parser, 1 );
692
+ syck_parser_taguri_expansion( parser, 1 );
693
+
694
+ if ( NIL_P( input ) )
695
+ {
696
+ input = rb_ivar_get( p, s_input );
697
+ }
698
+ if ( input == sym_bytecode )
699
+ {
700
+ syck_parser_set_input_type( parser, syck_bytecode_utf8 );
701
+ }
702
+ else
703
+ {
704
+ syck_parser_set_input_type( parser, syck_yaml_utf8 );
705
+ }
706
+ syck_parser_error_handler( parser, rb_syck_err_handler );
707
+ syck_parser_bad_anchor_handler( parser, rb_syck_bad_anchor_handler );
708
+ }
709
+
710
+ /*
711
+ * mark parser nodes
712
+ */
713
+ static void
714
+ syck_mark_parser(parser)
715
+ SyckParser *parser;
716
+ {
717
+ struct parser_xtra *bonus;
718
+ rb_gc_mark(parser->root);
719
+ rb_gc_mark(parser->root_on_error);
720
+ if ( parser->bonus != NULL )
721
+ {
722
+ bonus = (struct parser_xtra *)parser->bonus;
723
+ rb_gc_mark( bonus->data );
724
+ rb_gc_mark( bonus->proc );
725
+ }
726
+ }
727
+
728
+ /*
729
+ * Free the parser and any bonus attachment.
730
+ */
731
+ void
732
+ rb_syck_free_parser(p)
733
+ SyckParser *p;
734
+ {
735
+ struct parser_xtra *bonus = (struct parser_xtra *)p->bonus;
736
+ if ( bonus != NULL ) S_FREE( bonus );
737
+ syck_free_parser(p);
738
+ }
739
+
740
+ /*
741
+ * YAML::Syck::Parser.allocate
742
+ */
743
+ VALUE syck_parser_s_alloc _((VALUE));
744
+ VALUE
745
+ syck_parser_s_alloc(class)
746
+ VALUE class;
747
+ {
748
+ VALUE pobj;
749
+ SyckParser *parser = syck_new_parser();
750
+
751
+ pobj = Data_Wrap_Struct( class, syck_mark_parser, rb_syck_free_parser, parser );
752
+
753
+ syck_parser_set_root_on_error( parser, Qnil );
754
+
755
+ return pobj;
756
+ }
757
+
758
+ /*
759
+ * YAML::Syck::Parser.initialize( resolver, options )
760
+ */
761
+ static VALUE
762
+ syck_parser_initialize(argc, argv, self)
763
+ int argc;
764
+ VALUE *argv;
765
+ VALUE self;
766
+ {
767
+ VALUE options;
768
+ if (rb_scan_args(argc, argv, "01", &options) == 0)
769
+ {
770
+ options = rb_hash_new();
771
+ }
772
+ else
773
+ {
774
+ Check_Type(options, T_HASH);
775
+ }
776
+ rb_ivar_set(self, s_options, options);
777
+ return self;
778
+ }
779
+
780
+ /*
781
+ * YAML::Syck::Parser.bufsize = Integer
782
+ */
783
+ static VALUE
784
+ syck_parser_bufsize_set( self, size )
785
+ VALUE self, size;
786
+ {
787
+ SyckParser *parser;
788
+
789
+ if ( rb_respond_to( size, s_to_i ) ) {
790
+ int n = NUM2INT(rb_funcall(size, s_to_i, 0));
791
+ Data_Get_Struct(self, SyckParser, parser);
792
+ parser->bufsize = n;
793
+ }
794
+ return self;
795
+ }
796
+
797
+ /*
798
+ * YAML::Syck::Parser.bufsize => Integer
799
+ */
800
+ static VALUE
801
+ syck_parser_bufsize_get( self )
802
+ VALUE self;
803
+ {
804
+ SyckParser *parser;
805
+
806
+ Data_Get_Struct(self, SyckParser, parser);
807
+ return INT2FIX( parser->bufsize );
808
+ }
809
+
810
+ /*
811
+ * YAML::Syck::Parser.load( IO or String )
812
+ */
813
+ VALUE
814
+ syck_parser_load(argc, argv, self)
815
+ int argc;
816
+ VALUE *argv;
817
+ VALUE self;
818
+ {
819
+ VALUE port, proc, model, input;
820
+ SyckParser *parser;
821
+ struct parser_xtra *bonus = S_ALLOC_N( struct parser_xtra, 1 );
822
+ volatile VALUE hash; /* protect from GC */
823
+
824
+ rb_scan_args(argc, argv, "11", &port, &proc);
825
+
826
+ input = rb_hash_aref( rb_attr_get( self, s_options ), sym_input );
827
+ model = rb_hash_aref( rb_attr_get( self, s_options ), sym_model );
828
+ Data_Get_Struct(self, SyckParser, parser);
829
+ syck_set_model( self, input, model );
830
+
831
+ bonus->taint = syck_parser_assign_io(parser, port);
832
+ bonus->data = hash = rb_hash_new();
833
+ bonus->resolver = rb_attr_get( self, s_resolver );
834
+ if ( NIL_P( proc ) ) bonus->proc = 0;
835
+ else bonus->proc = proc;
836
+
837
+ parser->bonus = (void *)bonus;
838
+
839
+ return syck_parse( parser );
840
+ }
841
+
842
+ /*
843
+ * YAML::Syck::Parser.load_documents( IO or String ) { |doc| }
844
+ */
845
+ VALUE
846
+ syck_parser_load_documents(argc, argv, self)
847
+ int argc;
848
+ VALUE *argv;
849
+ VALUE self;
850
+ {
851
+ VALUE port, proc, v, input, model;
852
+ SyckParser *parser;
853
+ struct parser_xtra *bonus = S_ALLOC_N( struct parser_xtra, 1 );
854
+ volatile VALUE hash;
855
+
856
+ rb_scan_args(argc, argv, "1&", &port, &proc);
857
+
858
+ input = rb_hash_aref( rb_attr_get( self, s_options ), sym_input );
859
+ model = rb_hash_aref( rb_attr_get( self, s_options ), sym_model );
860
+ Data_Get_Struct(self, SyckParser, parser);
861
+ syck_set_model( self, input, model );
862
+
863
+ bonus->taint = syck_parser_assign_io(parser, port);
864
+ bonus->resolver = rb_attr_get( self, s_resolver );
865
+ bonus->proc = 0;
866
+ parser->bonus = (void *)bonus;
867
+
868
+ while ( 1 )
869
+ {
870
+ /* Reset hash for tracking nodes */
871
+ bonus->data = hash = rb_hash_new();
872
+
873
+ /* Parse a document */
874
+ v = syck_parse( parser );
875
+ if ( parser->eof == 1 )
876
+ {
877
+ break;
878
+ }
879
+
880
+ /* Pass document to block */
881
+ rb_funcall( proc, s_call, 1, v );
882
+ }
883
+
884
+ return Qnil;
885
+ }
886
+
887
+ /*
888
+ * YAML::Syck::Parser#set_resolver
889
+ */
890
+ VALUE
891
+ syck_parser_set_resolver( self, resolver )
892
+ VALUE self, resolver;
893
+ {
894
+ rb_ivar_set( self, s_resolver, resolver );
895
+ return self;
896
+ }
897
+
898
+ /*
899
+ * YAML::Syck::Resolver.initialize
900
+ */
901
+ static VALUE
902
+ syck_resolver_initialize( self )
903
+ VALUE self;
904
+ {
905
+ VALUE tags = rb_hash_new();
906
+ rb_ivar_set(self, s_tags, rb_hash_new());
907
+ return self;
908
+ }
909
+
910
+ /*
911
+ * YAML::Syck::Resolver#add_type
912
+ */
913
+ VALUE
914
+ syck_resolver_add_type( self, taguri, cls )
915
+ VALUE self, taguri, cls;
916
+ {
917
+ VALUE tags = rb_attr_get(self, s_tags);
918
+ rb_hash_aset( tags, taguri, cls );
919
+ return Qnil;
920
+ }
921
+
922
+ /*
923
+ * YAML::Syck::Resolver#use_types_at
924
+ */
925
+ VALUE
926
+ syck_resolver_use_types_at( self, hsh )
927
+ VALUE self, hsh;
928
+ {
929
+ rb_ivar_set( self, s_tags, hsh );
930
+ return Qnil;
931
+ }
932
+
933
+ /*
934
+ * YAML::Syck::Resolver#detect_implicit
935
+ */
936
+ VALUE
937
+ syck_resolver_detect_implicit( self, val )
938
+ VALUE self, val;
939
+ {
940
+ char *type_id;
941
+ return rb_str_new2( "" );
942
+ }
943
+
944
+ /*
945
+ * YAML::Syck::Resolver#node_import
946
+ */
947
+ VALUE
948
+ syck_resolver_node_import( self, node )
949
+ VALUE self, node;
950
+ {
951
+ SyckNode *n;
952
+ VALUE obj;
953
+ int i = 0;
954
+ Data_Get_Struct(node, SyckNode, n);
955
+
956
+ switch (n->kind)
957
+ {
958
+ case syck_str_kind:
959
+ obj = rb_str_new( n->data.str->ptr, n->data.str->len );
960
+ break;
961
+
962
+ case syck_seq_kind:
963
+ obj = rb_ary_new2( n->data.list->idx );
964
+ for ( i = 0; i < n->data.list->idx; i++ )
965
+ {
966
+ rb_ary_store( obj, i, syck_seq_read( n, i ) );
967
+ }
968
+ break;
969
+
970
+ case syck_map_kind:
971
+ obj = rb_hash_new();
972
+ for ( i = 0; i < n->data.pairs->idx; i++ )
973
+ {
974
+ VALUE k = syck_map_read( n, map_key, i );
975
+ VALUE v = syck_map_read( n, map_value, i );
976
+ int skip_aset = 0;
977
+
978
+ /*
979
+ * Handle merge keys
980
+ */
981
+ if ( rb_obj_is_kind_of( k, cMergeKey ) )
982
+ {
983
+ if ( rb_obj_is_kind_of( v, rb_cHash ) )
984
+ {
985
+ VALUE dup = rb_funcall( v, s_dup, 0 );
986
+ rb_funcall( dup, s_update, 1, obj );
987
+ obj = dup;
988
+ skip_aset = 1;
989
+ }
990
+ else if ( rb_obj_is_kind_of( v, rb_cArray ) )
991
+ {
992
+ VALUE end = rb_ary_pop( v );
993
+ if ( rb_obj_is_kind_of( end, rb_cHash ) )
994
+ {
995
+ VALUE dup = rb_funcall( end, s_dup, 0 );
996
+ v = rb_ary_reverse( v );
997
+ rb_ary_push( v, obj );
998
+ rb_iterate( rb_each, v, syck_merge_i, dup );
999
+ obj = dup;
1000
+ skip_aset = 1;
1001
+ }
1002
+ }
1003
+ }
1004
+ else if ( rb_obj_is_kind_of( k, cDefaultKey ) )
1005
+ {
1006
+ rb_funcall( obj, s_default_set, 1, v );
1007
+ skip_aset = 1;
1008
+ }
1009
+
1010
+ if ( ! skip_aset )
1011
+ {
1012
+ rb_hash_aset( obj, k, v );
1013
+ }
1014
+ }
1015
+ break;
1016
+ }
1017
+
1018
+ if ( n->type_id != NULL )
1019
+ {
1020
+ obj = rb_funcall( self, s_transfer, 2, rb_str_new2( n->type_id ), obj );
1021
+ }
1022
+ return obj;
1023
+ }
1024
+
1025
+ /*
1026
+ * Set instance variables
1027
+ */
1028
+ VALUE
1029
+ syck_set_ivars( vars, obj )
1030
+ VALUE vars, obj;
1031
+ {
1032
+ VALUE ivname = rb_ary_entry( vars, 0 );
1033
+ char *ivn;
1034
+ StringValue( ivname );
1035
+ ivn = S_ALLOC_N( char, RSTRING(ivname)->len + 2 );
1036
+ ivn[0] = '@';
1037
+ ivn[1] = '\0';
1038
+ strncat( ivn, RSTRING(ivname)->ptr, RSTRING(ivname)->len );
1039
+ rb_iv_set( obj, ivn, rb_ary_entry( vars, 1 ) );
1040
+ S_FREE( ivn );
1041
+ return Qnil;
1042
+ }
1043
+
1044
+ /*
1045
+ * YAML::Syck::Resolver#const_find
1046
+ */
1047
+ VALUE
1048
+ syck_const_find( const_name )
1049
+ VALUE const_name;
1050
+ {
1051
+ VALUE tclass = rb_cObject;
1052
+ VALUE tparts = rb_str_split( const_name, "::" );
1053
+ int i = 0;
1054
+ for ( i = 0; i < RARRAY(tparts)->len; i++ ) {
1055
+ VALUE tpart = rb_to_id( rb_ary_entry( tparts, i ) );
1056
+ if ( !rb_const_defined( tclass, tpart ) ) return Qnil;
1057
+ tclass = rb_const_get( tclass, tpart );
1058
+ }
1059
+ return tclass;
1060
+ }
1061
+
1062
+ /*
1063
+ * YAML::Syck::Resolver#transfer
1064
+ */
1065
+ VALUE
1066
+ syck_resolver_transfer( self, type, val )
1067
+ VALUE self, type, val;
1068
+ {
1069
+ if (NIL_P(type) || RSTRING(StringValue(type))->len == 0)
1070
+ {
1071
+ type = rb_funcall( self, s_detect_implicit, 1, val );
1072
+ }
1073
+
1074
+ if ( ! (NIL_P(type) || RSTRING(StringValue(type))->len == 0) )
1075
+ {
1076
+ VALUE str_xprivate = rb_str_new2( "x-private" );
1077
+ VALUE colon = rb_str_new2( ":" );
1078
+ VALUE tags = rb_attr_get(self, s_tags);
1079
+ VALUE target_class = rb_hash_aref( tags, type );
1080
+ VALUE subclass = target_class;
1081
+ VALUE obj = Qnil;
1082
+
1083
+ /*
1084
+ * Should no tag match exactly, check for subclass format
1085
+ */
1086
+ if ( NIL_P( target_class ) )
1087
+ {
1088
+ VALUE subclass_parts = rb_ary_new();
1089
+ VALUE parts = rb_str_split( type, ":" );
1090
+
1091
+ while ( RARRAY(parts)->len > 1 )
1092
+ {
1093
+ VALUE partial;
1094
+ rb_ary_unshift( subclass_parts, rb_ary_pop( parts ) );
1095
+ partial = rb_ary_join( parts, colon );
1096
+ target_class = rb_hash_aref( tags, partial );
1097
+ if ( NIL_P( target_class ) )
1098
+ {
1099
+ rb_str_append( partial, colon );
1100
+ target_class = rb_hash_aref( tags, partial );
1101
+ }
1102
+
1103
+ /*
1104
+ * Possible subclass found, see if it supports subclassing
1105
+ */
1106
+ if ( ! NIL_P( target_class ) )
1107
+ {
1108
+ subclass = target_class;
1109
+ if ( RARRAY(subclass_parts)->len > 0 && rb_respond_to( target_class, s_tag_subclasses ) &&
1110
+ RTEST( rb_funcall( target_class, s_tag_subclasses, 0 ) ) )
1111
+ {
1112
+ VALUE subclass_v;
1113
+ subclass = rb_ary_join( subclass_parts, colon );
1114
+ subclass = rb_funcall( target_class, s_tag_read_class, 1, subclass );
1115
+ subclass_v = syck_const_find( subclass );
1116
+
1117
+ if ( subclass_v != Qnil )
1118
+ {
1119
+ subclass = subclass_v;
1120
+ }
1121
+ else if ( rb_cObject == target_class && subclass_v == Qnil )
1122
+ {
1123
+ // StringValue(subclass);
1124
+ // printf( "No class: %s\n", RSTRING(subclass)->ptr );
1125
+ target_class = cYObject;
1126
+ type = subclass;
1127
+ subclass = cYObject;
1128
+ }
1129
+ }
1130
+ break;
1131
+ }
1132
+ }
1133
+ }
1134
+
1135
+ /* rb_raise(rb_eTypeError, "invalid typing scheme: %s given",
1136
+ * scheme);
1137
+ */
1138
+
1139
+ if ( rb_respond_to( target_class, s_call ) )
1140
+ {
1141
+ obj = rb_funcall( target_class, s_call, 2, type, val );
1142
+ }
1143
+ else
1144
+ {
1145
+ if ( rb_respond_to( target_class, s_yaml_new ) )
1146
+ {
1147
+ obj = rb_funcall( target_class, s_yaml_new, 3, subclass, type, val );
1148
+ }
1149
+ else if ( !NIL_P( target_class ) )
1150
+ {
1151
+ obj = rb_obj_alloc( subclass );
1152
+ if ( rb_respond_to( obj, s_yaml_initialize ) )
1153
+ {
1154
+ rb_funcall( obj, s_yaml_initialize, 2, type, val );
1155
+ }
1156
+ else if ( !NIL_P( obj ) && rb_obj_is_instance_of( val, rb_cHash ) )
1157
+ {
1158
+ rb_iterate( rb_each, val, syck_set_ivars, obj );
1159
+ }
1160
+ }
1161
+ else
1162
+ {
1163
+ VALUE parts = rb_str_split( type, ":" );
1164
+ VALUE scheme = rb_ary_shift( parts );
1165
+ if ( rb_str_cmp( scheme, str_xprivate ) == 0 )
1166
+ {
1167
+ VALUE name = rb_ary_join( parts, colon );
1168
+ obj = rb_funcall( cPrivateType, s_new, 2, name, val );
1169
+ }
1170
+ else
1171
+ {
1172
+ VALUE domain = rb_ary_shift( parts );
1173
+ VALUE name = rb_ary_join( parts, colon );
1174
+ obj = rb_funcall( cDomainType, s_new, 3, domain, name, val );
1175
+ }
1176
+ }
1177
+ }
1178
+ val = obj;
1179
+ }
1180
+
1181
+ return val;
1182
+ }
1183
+
1184
+ /*
1185
+ * YAML::Syck::Resolver#tagurize
1186
+ */
1187
+ VALUE
1188
+ syck_resolver_tagurize( self, val )
1189
+ VALUE self, val;
1190
+ {
1191
+ VALUE tmp = rb_check_string_type(val);
1192
+
1193
+ if ( !NIL_P(tmp) )
1194
+ {
1195
+ char *taguri;
1196
+ val = tmp;
1197
+ taguri = syck_type_id_to_uri( RSTRING(val)->ptr );
1198
+ return rb_str_new2( taguri );
1199
+ }
1200
+
1201
+ return val;
1202
+ }
1203
+
1204
+ /*
1205
+ * YAML::Syck::DefaultResolver#detect_implicit
1206
+ */
1207
+ VALUE
1208
+ syck_defaultresolver_detect_implicit( self, val )
1209
+ VALUE self, val;
1210
+ {
1211
+ char *type_id;
1212
+ VALUE tmp = rb_check_string_type(val);
1213
+
1214
+ if ( !NIL_P(tmp) )
1215
+ {
1216
+ val = tmp;
1217
+ type_id = syck_match_implicit( RSTRING(val)->ptr, RSTRING(val)->len );
1218
+ return rb_str_new2( type_id );
1219
+ }
1220
+
1221
+ return rb_str_new2( "" );
1222
+ }
1223
+
1224
+ /*
1225
+ * YAML::Syck::DefaultResolver#node_import
1226
+ */
1227
+ VALUE
1228
+ syck_defaultresolver_node_import( self, node )
1229
+ VALUE self, node;
1230
+ {
1231
+ SyckNode *n;
1232
+ VALUE obj;
1233
+ Data_Get_Struct( node, SyckNode, n );
1234
+ if ( !yaml_org_handler( n, &obj ) )
1235
+ {
1236
+ obj = rb_funcall( self, s_transfer, 2, rb_str_new2( n->type_id ), obj );
1237
+ }
1238
+ return obj;
1239
+ }
1240
+
1241
+ /*
1242
+ * YAML::Syck::GenericResolver#node_import
1243
+ */
1244
+ VALUE
1245
+ syck_genericresolver_node_import( self, node )
1246
+ VALUE self, node;
1247
+ {
1248
+ SyckNode *n;
1249
+ int i = 0;
1250
+ VALUE t = Qnil, obj = Qnil, v = Qnil, style = Qnil;
1251
+ Data_Get_Struct(node, SyckNode, n);
1252
+
1253
+ if ( n->type_id != NULL )
1254
+ {
1255
+ t = rb_str_new2(n->type_id);
1256
+ }
1257
+
1258
+ switch (n->kind)
1259
+ {
1260
+ case syck_str_kind:
1261
+ {
1262
+ v = rb_str_new( n->data.str->ptr, n->data.str->len );
1263
+ if ( n->data.str->style == scalar_1quote )
1264
+ {
1265
+ style = sym_1quote;
1266
+ }
1267
+ else if ( n->data.str->style == scalar_2quote )
1268
+ {
1269
+ style = sym_2quote;
1270
+ }
1271
+ else if ( n->data.str->style == scalar_fold )
1272
+ {
1273
+ style = sym_fold;
1274
+ }
1275
+ else if ( n->data.str->style == scalar_literal )
1276
+ {
1277
+ style = sym_literal;
1278
+ }
1279
+ else if ( n->data.str->style == scalar_plain )
1280
+ {
1281
+ style = sym_plain;
1282
+ }
1283
+ obj = rb_funcall( cScalar, s_new, 3, t, v, style );
1284
+ }
1285
+ break;
1286
+
1287
+ case syck_seq_kind:
1288
+ rb_iv_set(obj, "@kind", sym_seq);
1289
+ v = rb_ary_new2( syck_seq_count( n ) );
1290
+ for ( i = 0; i < syck_seq_count( n ); i++ )
1291
+ {
1292
+ rb_ary_store( v, i, syck_seq_read( n, i ) );
1293
+ }
1294
+ if ( n->data.list->style == seq_inline )
1295
+ {
1296
+ style = sym_inline;
1297
+ }
1298
+ obj = rb_funcall( cSeq, s_new, 3, t, v, style );
1299
+ break;
1300
+
1301
+ case syck_map_kind:
1302
+ rb_iv_set(obj, "@kind", sym_map);
1303
+ v = rb_hash_new();
1304
+ for ( i = 0; i < syck_map_count( n ); i++ )
1305
+ {
1306
+ rb_hash_aset( v, syck_map_read( n, map_key, i ), syck_map_read( n, map_value, i ) );
1307
+ }
1308
+ if ( n->data.pairs->style == map_inline )
1309
+ {
1310
+ style = sym_inline;
1311
+ }
1312
+ obj = rb_funcall( cMap, s_new, 3, t, v, style );
1313
+ break;
1314
+ }
1315
+
1316
+ return obj;
1317
+ }
1318
+
1319
+ /*
1320
+ * YAML::Syck::BadAlias.initialize
1321
+ */
1322
+ VALUE
1323
+ syck_badalias_initialize( self, val )
1324
+ VALUE self, val;
1325
+ {
1326
+ rb_iv_set( self, "@name", val );
1327
+ return self;
1328
+ }
1329
+
1330
+ /*
1331
+ * YAML::Syck::BadAlias.<=>
1332
+ */
1333
+ VALUE
1334
+ syck_badalias_cmp( alias1, alias2 )
1335
+ VALUE alias1, alias2;
1336
+ {
1337
+ VALUE str1 = rb_ivar_get( alias1, s_name );
1338
+ VALUE str2 = rb_ivar_get( alias2, s_name );
1339
+ VALUE val = rb_funcall( str1, s_cmp, 1, str2 );
1340
+ return val;
1341
+ }
1342
+
1343
+ /*
1344
+ * YAML::DomainType.initialize
1345
+ */
1346
+ VALUE
1347
+ syck_domaintype_initialize( self, domain, type_id, val )
1348
+ VALUE self, type_id, val;
1349
+ {
1350
+ rb_iv_set( self, "@domain", domain );
1351
+ rb_iv_set( self, "@type_id", type_id );
1352
+ rb_iv_set( self, "@value", val );
1353
+ return self;
1354
+ }
1355
+
1356
+ /*
1357
+ * YAML::Object.initialize
1358
+ */
1359
+ VALUE
1360
+ syck_yobject_initialize( self, klass, ivars )
1361
+ VALUE self, klass, ivars;
1362
+ {
1363
+ rb_iv_set( self, "@class", klass );
1364
+ rb_iv_set( self, "@ivars", ivars );
1365
+ return self;
1366
+ }
1367
+
1368
+ /*
1369
+ * YAML::PrivateType.initialize
1370
+ */
1371
+ VALUE
1372
+ syck_privatetype_initialize( self, type_id, val )
1373
+ VALUE self, type_id, val;
1374
+ {
1375
+ rb_iv_set( self, "@type_id", type_id );
1376
+ rb_iv_set( self, "@value", val );
1377
+ return self;
1378
+ }
1379
+
1380
+ /*
1381
+ * Mark node contents.
1382
+ */
1383
+ static void
1384
+ syck_node_mark( n )
1385
+ SyckNode *n;
1386
+ {
1387
+ int i;
1388
+ switch ( n->kind )
1389
+ {
1390
+ case syck_seq_kind:
1391
+ for ( i = 0; i < n->data.list->idx; i++ )
1392
+ {
1393
+ rb_gc_mark( syck_seq_read( n, i ) );
1394
+ }
1395
+ break;
1396
+
1397
+ case syck_map_kind:
1398
+ for ( i = 0; i < n->data.pairs->idx; i++ )
1399
+ {
1400
+ rb_gc_mark( syck_map_read( n, map_key, i ) );
1401
+ rb_gc_mark( syck_map_read( n, map_value, i ) );
1402
+ }
1403
+ break;
1404
+ }
1405
+ }
1406
+
1407
+ /*
1408
+ * Don't free Ruby data, Ruby will do that
1409
+ */
1410
+ void
1411
+ rb_syck_free_node( SyckNode *n )
1412
+ {
1413
+ switch ( n->kind )
1414
+ {
1415
+ case syck_str_kind:
1416
+ S_FREE( n->data.str );
1417
+ n->data.str = NULL;
1418
+ break;
1419
+
1420
+ case syck_seq_kind:
1421
+ if ( n->data.list != NULL )
1422
+ {
1423
+ S_FREE( n->data.list->items );
1424
+ S_FREE( n->data.list );
1425
+ n->data.list = NULL;
1426
+ }
1427
+ break;
1428
+
1429
+ case syck_map_kind:
1430
+ if ( n->data.pairs != NULL )
1431
+ {
1432
+ S_FREE( n->data.pairs->keys );
1433
+ S_FREE( n->data.pairs->values );
1434
+ S_FREE( n->data.pairs );
1435
+ n->data.pairs = NULL;
1436
+ }
1437
+ break;
1438
+ }
1439
+
1440
+ S_FREE( n );
1441
+ }
1442
+
1443
+ /*
1444
+ * YAML::Syck::Scalar.allocate
1445
+ */
1446
+ VALUE
1447
+ syck_scalar_alloc( class )
1448
+ VALUE class;
1449
+ {
1450
+ SyckNode *node = syck_alloc_str();
1451
+ VALUE obj = Data_Wrap_Struct( class, syck_node_mark, rb_syck_free_node, node );
1452
+ node->id = obj;
1453
+ return obj;
1454
+ }
1455
+
1456
+ /*
1457
+ * YAML::Syck::Scalar.initialize
1458
+ */
1459
+ VALUE
1460
+ syck_scalar_initialize( self, type_id, val, style )
1461
+ VALUE self, type_id, val, style;
1462
+ {
1463
+ rb_iv_set( self, "@kind", sym_scalar );
1464
+ rb_funcall( self, s_type_id_set, 1, type_id );
1465
+ rb_funcall( self, s_value_set, 1, val );
1466
+ rb_funcall( self, s_style_set, 1, style );
1467
+ return self;
1468
+ }
1469
+
1470
+ /*
1471
+ * YAML::Syck::Scalar.style=
1472
+ */
1473
+ VALUE
1474
+ syck_scalar_style_set( self, style )
1475
+ VALUE self, style;
1476
+ {
1477
+ SyckNode *node;
1478
+ Data_Get_Struct( self, SyckNode, node );
1479
+
1480
+ if ( NIL_P( style ) )
1481
+ {
1482
+ node->data.str->style = scalar_none;
1483
+ }
1484
+ else if ( style == sym_1quote )
1485
+ {
1486
+ node->data.str->style = scalar_1quote;
1487
+ }
1488
+ else if ( style == sym_2quote )
1489
+ {
1490
+ node->data.str->style = scalar_2quote;
1491
+ }
1492
+ else if ( style == sym_fold )
1493
+ {
1494
+ node->data.str->style = scalar_fold;
1495
+ }
1496
+ else if ( style == sym_literal )
1497
+ {
1498
+ node->data.str->style = scalar_literal;
1499
+ }
1500
+ else if ( style == sym_plain )
1501
+ {
1502
+ node->data.str->style = scalar_plain;
1503
+ }
1504
+
1505
+ rb_iv_set( self, "@style", style );
1506
+ return self;
1507
+ }
1508
+
1509
+ /*
1510
+ * YAML::Syck::Scalar.value=
1511
+ */
1512
+ VALUE
1513
+ syck_scalar_value_set( self, val )
1514
+ VALUE self, val;
1515
+ {
1516
+ SyckNode *node;
1517
+ Data_Get_Struct( self, SyckNode, node );
1518
+
1519
+ StringValue( val );
1520
+ node->data.str->ptr = RSTRING(val)->ptr;
1521
+ node->data.str->len = RSTRING(val)->len;
1522
+ node->data.str->style = scalar_none;
1523
+
1524
+ rb_iv_set( self, "@value", val );
1525
+ return val;
1526
+ }
1527
+
1528
+ /*
1529
+ * YAML::Syck::Seq.allocate
1530
+ */
1531
+ VALUE
1532
+ syck_seq_alloc( class )
1533
+ VALUE class;
1534
+ {
1535
+ SyckNode *node;
1536
+ VALUE obj;
1537
+ node = syck_alloc_seq();
1538
+ obj = Data_Wrap_Struct( class, syck_node_mark, rb_syck_free_node, node );
1539
+ node->id = obj;
1540
+ return obj;
1541
+ }
1542
+
1543
+ /*
1544
+ * YAML::Syck::Seq.initialize
1545
+ */
1546
+ VALUE
1547
+ syck_seq_initialize( self, type_id, val, style )
1548
+ VALUE self, type_id, val, style;
1549
+ {
1550
+ SyckNode *node;
1551
+ Data_Get_Struct( self, SyckNode, node );
1552
+
1553
+ rb_iv_set( self, "@kind", sym_seq );
1554
+ rb_funcall( self, s_type_id_set, 1, type_id );
1555
+ rb_funcall( self, s_value_set, 1, val );
1556
+ rb_funcall( self, s_style_set, 1, style );
1557
+ return self;
1558
+ }
1559
+
1560
+ /*
1561
+ * YAML::Syck::Seq.value=
1562
+ */
1563
+ VALUE
1564
+ syck_seq_value_set( self, val )
1565
+ VALUE self, val;
1566
+ {
1567
+ SyckNode *node;
1568
+ Data_Get_Struct( self, SyckNode, node );
1569
+
1570
+ val = rb_check_array_type( val );
1571
+ if ( !NIL_P( val ) ) {
1572
+ int i;
1573
+ syck_seq_empty( node );
1574
+ for ( i = 0; i < RARRAY( val )->len; i++ )
1575
+ {
1576
+ syck_seq_add( node, rb_ary_entry(val, i) );
1577
+ }
1578
+ }
1579
+
1580
+ rb_iv_set( self, "@value", val );
1581
+ return val;
1582
+ }
1583
+
1584
+ /*
1585
+ * YAML::Syck::Seq.add
1586
+ */
1587
+ VALUE
1588
+ syck_seq_add_m( self, val )
1589
+ VALUE self, val;
1590
+ {
1591
+ SyckNode *node;
1592
+ VALUE emitter = rb_ivar_get( self, s_emitter );
1593
+ Data_Get_Struct( self, SyckNode, node );
1594
+
1595
+ if ( rb_respond_to( emitter, s_node_export ) ) {
1596
+ val = rb_funcall( emitter, s_node_export, 1, val );
1597
+ }
1598
+ syck_seq_add( node, val );
1599
+ rb_ary_push( rb_ivar_get( self, s_value ), val );
1600
+
1601
+ return self;
1602
+ }
1603
+
1604
+ /*
1605
+ * YAML::Syck::Seq.style=
1606
+ */
1607
+ VALUE
1608
+ syck_seq_style_set( self, style )
1609
+ VALUE self, style;
1610
+ {
1611
+ SyckNode *node;
1612
+ Data_Get_Struct( self, SyckNode, node );
1613
+
1614
+ if ( style == sym_inline )
1615
+ {
1616
+ node->data.list->style = seq_inline;
1617
+ }
1618
+ else
1619
+ {
1620
+ node->data.list->style = seq_none;
1621
+ }
1622
+
1623
+ rb_iv_set( self, "@style", style );
1624
+ return self;
1625
+ }
1626
+
1627
+ /*
1628
+ * YAML::Syck::Map.allocate
1629
+ */
1630
+ VALUE
1631
+ syck_map_alloc( class )
1632
+ VALUE class;
1633
+ {
1634
+ SyckNode *node;
1635
+ VALUE obj;
1636
+ node = syck_alloc_map();
1637
+ obj = Data_Wrap_Struct( class, syck_node_mark, rb_syck_free_node, node );
1638
+ node->id = obj;
1639
+ return obj;
1640
+ }
1641
+
1642
+ /*
1643
+ * YAML::Syck::Map.initialize
1644
+ */
1645
+ VALUE
1646
+ syck_map_initialize( self, type_id, val, style )
1647
+ VALUE self, type_id, val, style;
1648
+ {
1649
+ SyckNode *node;
1650
+ Data_Get_Struct( self, SyckNode, node );
1651
+
1652
+ if ( !NIL_P( val ) )
1653
+ {
1654
+ VALUE hsh = rb_check_convert_type(val, T_HASH, "Hash", "to_hash");
1655
+ VALUE keys;
1656
+ int i;
1657
+ if ( NIL_P(hsh) )
1658
+ {
1659
+ rb_raise( rb_eTypeError, "wrong argument type" );
1660
+ }
1661
+
1662
+ keys = rb_funcall( hsh, s_keys, 0 );
1663
+ for ( i = 0; i < RARRAY(keys)->len; i++ )
1664
+ {
1665
+ VALUE key = rb_ary_entry(keys, i);
1666
+ syck_map_add( node, key, rb_hash_aref(hsh, key) );
1667
+ }
1668
+ }
1669
+
1670
+ rb_iv_set( self, "@kind", sym_seq );
1671
+ rb_funcall( self, s_type_id_set, 1, type_id );
1672
+ rb_funcall( self, s_value_set, 1, val );
1673
+ rb_funcall( self, s_style_set, 1, style );
1674
+ return self;
1675
+ }
1676
+
1677
+ /*
1678
+ * YAML::Syck::Map.value=
1679
+ */
1680
+ VALUE
1681
+ syck_map_value_set( self, val )
1682
+ VALUE self, val;
1683
+ {
1684
+ SyckNode *node;
1685
+ Data_Get_Struct( self, SyckNode, node );
1686
+
1687
+ if ( !NIL_P( val ) )
1688
+ {
1689
+ VALUE hsh = rb_check_convert_type(val, T_HASH, "Hash", "to_hash");
1690
+ VALUE keys;
1691
+ int i;
1692
+ if ( NIL_P(hsh) )
1693
+ {
1694
+ rb_raise( rb_eTypeError, "wrong argument type" );
1695
+ }
1696
+
1697
+ syck_map_empty( node );
1698
+ keys = rb_funcall( hsh, s_keys, 0 );
1699
+ for ( i = 0; i < RARRAY(keys)->len; i++ )
1700
+ {
1701
+ VALUE key = rb_ary_entry(keys, i);
1702
+ syck_map_add( node, key, rb_hash_aref(hsh, key) );
1703
+ }
1704
+ }
1705
+
1706
+ rb_iv_set( self, "@value", val );
1707
+ return val;
1708
+ }
1709
+
1710
+ /*
1711
+ * YAML::Syck::Map.add
1712
+ */
1713
+ VALUE
1714
+ syck_map_add_m( self, key, val )
1715
+ VALUE self, key, val;
1716
+ {
1717
+ SyckNode *node;
1718
+ VALUE emitter = rb_ivar_get( self, s_emitter );
1719
+ Data_Get_Struct( self, SyckNode, node );
1720
+
1721
+ if ( rb_respond_to( emitter, s_node_export ) ) {
1722
+ key = rb_funcall( emitter, s_node_export, 1, key );
1723
+ val = rb_funcall( emitter, s_node_export, 1, val );
1724
+ }
1725
+ syck_map_add( node, key, val );
1726
+ rb_hash_aset( rb_ivar_get( self, s_value ), key, val );
1727
+
1728
+ return self;
1729
+ }
1730
+
1731
+ /*
1732
+ * YAML::Syck::Map.style=
1733
+ */
1734
+ VALUE
1735
+ syck_map_style_set( self, style )
1736
+ VALUE self, style;
1737
+ {
1738
+ SyckNode *node;
1739
+ Data_Get_Struct( self, SyckNode, node );
1740
+
1741
+ if ( style == sym_inline )
1742
+ {
1743
+ node->data.pairs->style = map_inline;
1744
+ }
1745
+ else
1746
+ {
1747
+ node->data.pairs->style = map_none;
1748
+ }
1749
+
1750
+ rb_iv_set( self, "@style", style );
1751
+ return self;
1752
+ }
1753
+
1754
+ /*
1755
+ * Cloning method for all node types
1756
+ */
1757
+ VALUE
1758
+ syck_node_init_copy( copy, orig )
1759
+ VALUE copy, orig;
1760
+ {
1761
+ SyckNode *copy_n;
1762
+ SyckNode *orig_n;
1763
+
1764
+ if ( copy == orig )
1765
+ return copy;
1766
+
1767
+ if ( TYPE( orig ) != T_DATA ||
1768
+ RDATA( orig )->dfree != ( RUBY_DATA_FUNC )rb_syck_free_node )
1769
+ {
1770
+ rb_raise( rb_eTypeError, "wrong argument type" );
1771
+ }
1772
+
1773
+ Data_Get_Struct( orig, SyckNode, orig_n );
1774
+ Data_Get_Struct( copy, SyckNode, copy_n );
1775
+ MEMCPY( copy_n, orig_n, SyckNode, 1 );
1776
+ return copy;
1777
+ }
1778
+
1779
+ /*
1780
+ * YAML::Syck::Node#type_id=
1781
+ */
1782
+ VALUE
1783
+ syck_node_type_id_set( self, type_id )
1784
+ VALUE self, type_id;
1785
+ {
1786
+ SyckNode *node;
1787
+ Data_Get_Struct( self, SyckNode, node );
1788
+
1789
+ if ( node->type_id != NULL ) S_FREE( node->type_id );
1790
+
1791
+ if ( NIL_P( type_id ) ) {
1792
+ node->type_id = NULL;
1793
+ } else {
1794
+ node->type_id = StringValuePtr( type_id );
1795
+ }
1796
+
1797
+ rb_iv_set( self, "@type_id", type_id );
1798
+ return type_id;
1799
+ }
1800
+
1801
+ /*
1802
+ * YAML::Syck::Node.transform
1803
+ */
1804
+ VALUE
1805
+ syck_node_transform( self )
1806
+ VALUE self;
1807
+ {
1808
+ VALUE t;
1809
+ SyckNode *n;
1810
+ SyckNode *orig_n;
1811
+ Data_Get_Struct(self, SyckNode, orig_n);
1812
+
1813
+ switch (orig_n->kind)
1814
+ {
1815
+ case syck_map_kind:
1816
+ {
1817
+ int i;
1818
+ n = syck_alloc_map();
1819
+ for ( i = 0; i < orig_n->data.pairs->idx; i++ )
1820
+ {
1821
+ syck_map_add( n, rb_funcall( syck_map_read( orig_n, map_key, i ), s_transform, 0 ),
1822
+ rb_funcall( syck_map_read( orig_n, map_value, i ), s_transform, 0 ) );
1823
+ }
1824
+ }
1825
+ break;
1826
+
1827
+ case syck_seq_kind:
1828
+ {
1829
+ int i;
1830
+ n = syck_alloc_seq();
1831
+ for ( i = 0; i < orig_n->data.list->idx; i++ )
1832
+ {
1833
+ syck_seq_add( n, rb_funcall( syck_seq_read( orig_n, i ), s_transform, 0 ) );
1834
+ }
1835
+ }
1836
+ break;
1837
+
1838
+ case syck_str_kind:
1839
+ n = syck_new_str2( orig_n->data.str->ptr, orig_n->data.str->len, orig_n->data.str->style );
1840
+ break;
1841
+ }
1842
+
1843
+ if ( orig_n->type_id != NULL )
1844
+ {
1845
+ n->type_id = syck_strndup( orig_n->type_id, strlen( orig_n->type_id ) );
1846
+ }
1847
+ if ( orig_n->anchor != NULL )
1848
+ {
1849
+ n->anchor = syck_strndup( orig_n->anchor, strlen( orig_n->anchor ) );
1850
+ }
1851
+ t = Data_Wrap_Struct( cNode, NULL, NULL, n );
1852
+ n->id = t;
1853
+ t = rb_funcall( oDefaultResolver, s_node_import, 1, t );
1854
+ syck_free_node( n );
1855
+ return t;
1856
+ }
1857
+
1858
+ /*
1859
+ * Emitter callback: assembles YAML document events from
1860
+ * Ruby symbols. This is a brilliant way to do it.
1861
+ * No one could possibly object.
1862
+ */
1863
+ void
1864
+ rb_syck_emitter_handler(e, data)
1865
+ SyckEmitter *e;
1866
+ st_data_t data;
1867
+ {
1868
+ SyckNode *n;
1869
+ Data_Get_Struct((VALUE)data, SyckNode, n);
1870
+
1871
+ switch (n->kind)
1872
+ {
1873
+ case syck_map_kind:
1874
+ {
1875
+ int i;
1876
+ syck_emit_map( e, n->type_id, n->data.pairs->style );
1877
+ for ( i = 0; i < n->data.pairs->idx; i++ )
1878
+ {
1879
+ syck_emit_item( e, syck_map_read( n, map_key, i ) );
1880
+ syck_emit_item( e, syck_map_read( n, map_value, i ) );
1881
+ }
1882
+ syck_emit_end( e );
1883
+ }
1884
+ break;
1885
+
1886
+ case syck_seq_kind:
1887
+ {
1888
+ int i;
1889
+ syck_emit_seq( e, n->type_id, n->data.list->style );
1890
+ for ( i = 0; i < n->data.list->idx; i++ )
1891
+ {
1892
+ syck_emit_item( e, syck_seq_read( n, i ) );
1893
+ }
1894
+ syck_emit_end( e );
1895
+ }
1896
+ break;
1897
+
1898
+ case syck_str_kind:
1899
+ {
1900
+ syck_emit_scalar( e, n->type_id, n->data.str->style, 0, 0, 0, n->data.str->ptr, n->data.str->len );
1901
+ }
1902
+ break;
1903
+ }
1904
+ }
1905
+
1906
+ /*
1907
+ * Handle output from the emitter
1908
+ */
1909
+ void
1910
+ rb_syck_output_handler( emitter, str, len )
1911
+ SyckEmitter *emitter;
1912
+ char *str;
1913
+ long len;
1914
+ {
1915
+ struct emitter_xtra *bonus = (struct emitter_xtra *)emitter->bonus;
1916
+ VALUE dest = bonus->port;
1917
+ if (TYPE(dest) == T_STRING) {
1918
+ rb_str_cat( dest, str, len );
1919
+ } else {
1920
+ rb_io_write( dest, rb_str_new( str, len ) );
1921
+ }
1922
+ }
1923
+
1924
+ /*
1925
+ * Helper function for marking nodes in the anchor
1926
+ * symbol table.
1927
+ */
1928
+ void
1929
+ syck_out_mark( emitter, node )
1930
+ VALUE emitter, node;
1931
+ {
1932
+ SyckEmitter *emitterPtr;
1933
+ struct emitter_xtra *bonus;
1934
+ Data_Get_Struct(emitter, SyckEmitter, emitterPtr);
1935
+ bonus = (struct emitter_xtra *)emitterPtr->bonus;
1936
+ rb_ivar_set( node, s_emitter, emitter );
1937
+ /* syck_emitter_mark_node( emitterPtr, (st_data_t)node ); */
1938
+ if ( !NIL_P( bonus->oid ) ) {
1939
+ rb_hash_aset( bonus->data, bonus->oid, node );
1940
+ }
1941
+ }
1942
+
1943
+ /*
1944
+ * Mark emitter values.
1945
+ */
1946
+ static void
1947
+ syck_mark_emitter(emitter)
1948
+ SyckEmitter *emitter;
1949
+ {
1950
+ struct emitter_xtra *bonus;
1951
+ if ( emitter->bonus != NULL )
1952
+ {
1953
+ bonus = (struct emitter_xtra *)emitter->bonus;
1954
+ rb_gc_mark( bonus->data );
1955
+ rb_gc_mark( bonus->port );
1956
+ }
1957
+ }
1958
+
1959
+ /*
1960
+ * Free the emitter and any bonus attachment.
1961
+ */
1962
+ void
1963
+ rb_syck_free_emitter(e)
1964
+ SyckEmitter *e;
1965
+ {
1966
+ struct emitter_xtra *bonus = (struct emitter_xtra *)e->bonus;
1967
+ if ( bonus != NULL ) S_FREE( bonus );
1968
+ syck_free_emitter(e);
1969
+ }
1970
+
1971
+ /*
1972
+ * YAML::Syck::Emitter.allocate
1973
+ */
1974
+ VALUE syck_emitter_s_alloc _((VALUE));
1975
+ VALUE
1976
+ syck_emitter_s_alloc(class)
1977
+ VALUE class;
1978
+ {
1979
+ VALUE pobj;
1980
+ SyckEmitter *emitter = syck_new_emitter();
1981
+
1982
+ pobj = Data_Wrap_Struct( class, syck_mark_emitter, rb_syck_free_emitter, emitter );
1983
+ syck_emitter_handler( emitter, rb_syck_emitter_handler );
1984
+ syck_output_handler( emitter, rb_syck_output_handler );
1985
+
1986
+ rb_ivar_set( pobj, s_out, rb_funcall( cOut, s_new, 1, pobj ) );
1987
+ return pobj;
1988
+ }
1989
+
1990
+ /*
1991
+ * YAML::Syck::Emitter.reset( options )
1992
+ */
1993
+ VALUE
1994
+ syck_emitter_reset( argc, argv, self )
1995
+ int argc;
1996
+ VALUE *argv;
1997
+ VALUE self;
1998
+ {
1999
+ VALUE options, tmp;
2000
+ SyckEmitter *emitter;
2001
+ struct emitter_xtra *bonus;
2002
+ volatile VALUE hash; /* protect from GC */
2003
+
2004
+ Data_Get_Struct(self, SyckEmitter, emitter);
2005
+ bonus = (struct emitter_xtra *)emitter->bonus;
2006
+ if ( bonus != NULL ) S_FREE( bonus );
2007
+
2008
+ bonus = S_ALLOC_N( struct emitter_xtra, 1 );
2009
+ bonus->port = rb_str_new2( "" );
2010
+ bonus->data = hash = rb_hash_new();
2011
+
2012
+ if (rb_scan_args(argc, argv, "01", &options) == 0)
2013
+ {
2014
+ options = rb_hash_new();
2015
+ rb_ivar_set(self, s_options, options);
2016
+ }
2017
+ else if ( !NIL_P(tmp = rb_check_string_type(options)) )
2018
+ {
2019
+ bonus->port = tmp;
2020
+ }
2021
+ else if ( rb_respond_to( options, s_write ) )
2022
+ {
2023
+ bonus->port = options;
2024
+ }
2025
+ else
2026
+ {
2027
+ Check_Type(options, T_HASH);
2028
+ rb_ivar_set(self, s_options, options);
2029
+ }
2030
+
2031
+ emitter->bonus = (void *)bonus;
2032
+ rb_ivar_set(self, s_level, INT2FIX(0));
2033
+ rb_ivar_set(self, s_resolver, Qnil);
2034
+ return self;
2035
+ }
2036
+
2037
+ /*
2038
+ * YAML::Syck::Emitter.emit( object_id ) { |out| ... }
2039
+ */
2040
+ VALUE
2041
+ syck_emitter_emit( argc, argv, self )
2042
+ int argc;
2043
+ VALUE *argv;
2044
+ VALUE self;
2045
+ {
2046
+ VALUE oid, proc;
2047
+ char *anchor_name;
2048
+ SyckEmitter *emitter;
2049
+ struct emitter_xtra *bonus;
2050
+ SYMID symple;
2051
+ int level = FIX2INT(rb_ivar_get(self, s_level)) + 1;
2052
+ rb_ivar_set(self, s_level, INT2FIX(level));
2053
+
2054
+ rb_scan_args(argc, argv, "1&", &oid, &proc);
2055
+ Data_Get_Struct(self, SyckEmitter, emitter);
2056
+ bonus = (struct emitter_xtra *)emitter->bonus;
2057
+
2058
+ /* Calculate anchors, normalize nodes, build a simpler symbol table */
2059
+ bonus->oid = oid;
2060
+ if ( !NIL_P( oid ) && RTEST( rb_funcall( bonus->data, s_haskey, 1, oid ) ) ) {
2061
+ symple = rb_hash_aref( bonus->data, oid );
2062
+ } else {
2063
+ symple = rb_funcall( proc, s_call, 1, rb_ivar_get( self, s_out ) );
2064
+ }
2065
+ syck_emitter_mark_node( emitter, (st_data_t)symple );
2066
+
2067
+ /* Second pass, build emitted string */
2068
+ level -= 1;
2069
+ rb_ivar_set(self, s_level, INT2FIX(level));
2070
+ if ( level == 0 )
2071
+ {
2072
+ syck_emit(emitter, (st_data_t)symple);
2073
+ syck_emitter_flush(emitter, 0);
2074
+
2075
+ return bonus->port;
2076
+ }
2077
+
2078
+ return symple;
2079
+ }
2080
+
2081
+ /*
2082
+ * YAML::Syck::Emitter#node_export
2083
+ */
2084
+ VALUE
2085
+ syck_emitter_node_export( self, node )
2086
+ VALUE self, node;
2087
+ {
2088
+ return rb_funcall( node, s_to_yaml, 1, self );
2089
+ }
2090
+
2091
+ /*
2092
+ * YAML::Syck::Emitter#set_resolver
2093
+ */
2094
+ VALUE
2095
+ syck_emitter_set_resolver( self, resolver )
2096
+ VALUE self, resolver;
2097
+ {
2098
+ rb_ivar_set( self, s_resolver, resolver );
2099
+ return self;
2100
+ }
2101
+
2102
+ /*
2103
+ * YAML::Syck::Out::initialize
2104
+ */
2105
+ VALUE
2106
+ syck_out_initialize( self, emitter )
2107
+ VALUE self, emitter;
2108
+ {
2109
+ rb_ivar_set( self, s_emitter, emitter );
2110
+ return self;
2111
+ }
2112
+
2113
+ /*
2114
+ * YAML::Syck::Out::map
2115
+ */
2116
+ VALUE
2117
+ syck_out_map( argc, argv, self )
2118
+ int argc;
2119
+ VALUE *argv;
2120
+ VALUE self;
2121
+ {
2122
+ VALUE type_id, style, map;
2123
+ if (rb_scan_args(argc, argv, "11", &type_id, &style) == 1) {
2124
+ style = Qnil;
2125
+ }
2126
+ map = rb_funcall( cMap, s_new, 3, type_id, rb_hash_new(), style );
2127
+ syck_out_mark( rb_ivar_get( self, s_emitter ), map );
2128
+ rb_yield( map );
2129
+ return map;
2130
+ }
2131
+
2132
+ /*
2133
+ * YAML::Syck::Out::seq
2134
+ */
2135
+ VALUE
2136
+ syck_out_seq( argc, argv, self )
2137
+ int argc;
2138
+ VALUE *argv;
2139
+ VALUE self;
2140
+ {
2141
+ VALUE type_id, style, seq;
2142
+ if (rb_scan_args(argc, argv, "11", &type_id, &style) == 1) {
2143
+ style = Qnil;
2144
+ }
2145
+ seq = rb_funcall( cSeq, s_new, 3, type_id, rb_ary_new(), style );
2146
+ syck_out_mark( rb_ivar_get( self, s_emitter ), seq );
2147
+ rb_yield( seq );
2148
+ return seq;
2149
+ }
2150
+
2151
+ /*
2152
+ * YAML::Syck::Out::scalar
2153
+ syck_out_scalar( self, type_id, str, style )
2154
+ VALUE self, type_id, str, style;
2155
+ */
2156
+ VALUE
2157
+ syck_out_scalar( argc, argv, self )
2158
+ int argc;
2159
+ VALUE *argv;
2160
+ VALUE self;
2161
+ {
2162
+ VALUE type_id, str, style, scalar;
2163
+ if (rb_scan_args(argc, argv, "21", &type_id, &str, &style) == 2) {
2164
+ style = Qnil;
2165
+ }
2166
+ scalar = rb_funcall( cScalar, s_new, 3, type_id, str, style );
2167
+ syck_out_mark( rb_ivar_get( self, s_emitter ), scalar );
2168
+ return scalar;
2169
+ }
2170
+
2171
+ /*
2172
+ * Initialize Syck extension
2173
+ */
2174
+ void
2175
+ Init_syck()
2176
+ {
2177
+ VALUE rb_yaml = rb_define_module( "YAML" );
2178
+ VALUE rb_syck = rb_define_module_under( rb_yaml, "Syck" );
2179
+ rb_define_const( rb_syck, "VERSION", rb_str_new2( SYCK_VERSION ) );
2180
+ rb_define_module_function( rb_syck, "compile", rb_syck_compile, 1 );
2181
+
2182
+ /*
2183
+ * Global symbols
2184
+ */
2185
+ s_new = rb_intern("new");
2186
+ s_utc = rb_intern("utc");
2187
+ s_at = rb_intern("at");
2188
+ s_to_f = rb_intern("to_f");
2189
+ s_to_i = rb_intern("to_i");
2190
+ s_read = rb_intern("read");
2191
+ s_binmode = rb_intern("binmode");
2192
+ s_transfer = rb_intern("transfer");
2193
+ s_call = rb_intern("call");
2194
+ s_cmp = rb_intern("<=>");
2195
+ s_intern = rb_intern("intern");
2196
+ s_update = rb_intern("update");
2197
+ s_detect_implicit = rb_intern("detect_implicit");
2198
+ s_dup = rb_intern("dup");
2199
+ s_default_set = rb_intern("default=");
2200
+ s_match = rb_intern("match");
2201
+ s_push = rb_intern("push");
2202
+ s_haskey = rb_intern("has_key?");
2203
+ s_keys = rb_intern("keys");
2204
+ s_node_import = rb_intern("node_import");
2205
+ s_tr_bang = rb_intern("tr!");
2206
+ s_unpack = rb_intern("unpack");
2207
+ s_write = rb_intern("write");
2208
+ s_tag_read_class = rb_intern( "tag_read_class" );
2209
+ s_tag_subclasses = rb_intern( "tag_subclasses?" );
2210
+ s_emitter = rb_intern( "emitter" );
2211
+ s_set_resolver = rb_intern( "set_resolver" );
2212
+ s_node_export = rb_intern( "node_export" );
2213
+ s_to_yaml = rb_intern( "to_yaml" );
2214
+ s_transform = rb_intern( "transform" );
2215
+ s_yaml_new = rb_intern("yaml_new");
2216
+ s_yaml_initialize = rb_intern("yaml_initialize");
2217
+
2218
+ s_tags = rb_intern("@tags");
2219
+ s_name = rb_intern("@name");
2220
+ s_options = rb_intern("@options");
2221
+ s_kind = rb_intern("@kind");
2222
+ s_type_id = rb_intern("@type_id");
2223
+ s_type_id_set = rb_intern("type_id=");
2224
+ s_resolver = rb_intern("@resolver");
2225
+ s_level = rb_intern( "@level" );
2226
+ s_style = rb_intern("@style");
2227
+ s_style_set = rb_intern("style=");
2228
+ s_value = rb_intern("@value");
2229
+ s_value_set = rb_intern("value=");
2230
+ s_out = rb_intern("@out");
2231
+ s_input = rb_intern("@input");
2232
+
2233
+ sym_model = ID2SYM(rb_intern("Model"));
2234
+ sym_generic = ID2SYM(rb_intern("Generic"));
2235
+ sym_bytecode = ID2SYM(rb_intern("bytecode"));
2236
+ sym_map = ID2SYM(rb_intern("map"));
2237
+ sym_scalar = ID2SYM(rb_intern("scalar"));
2238
+ sym_seq = ID2SYM(rb_intern("seq"));
2239
+ sym_1quote = ID2SYM(rb_intern("quote1"));
2240
+ sym_2quote = ID2SYM(rb_intern("quote2"));
2241
+ sym_fold = ID2SYM(rb_intern("fold"));
2242
+ sym_literal = ID2SYM(rb_intern("literal"));
2243
+ sym_plain = ID2SYM(rb_intern("plain"));
2244
+ sym_inline = ID2SYM(rb_intern("inline"));
2245
+
2246
+ /*
2247
+ * Define YAML::Syck::Resolver class
2248
+ */
2249
+ cResolver = rb_define_class_under( rb_syck, "Resolver", rb_cObject );
2250
+ rb_define_attr( cResolver, "tags", 1, 1 );
2251
+ rb_define_method( cResolver, "initialize", syck_resolver_initialize, 0 );
2252
+ rb_define_method( cResolver, "add_type", syck_resolver_add_type, 2 );
2253
+ rb_define_method( cResolver, "use_types_at", syck_resolver_use_types_at, 1 );
2254
+ rb_define_method( cResolver, "detect_implicit", syck_resolver_detect_implicit, 1 );
2255
+ rb_define_method( cResolver, "transfer", syck_resolver_transfer, 2 );
2256
+ rb_define_method( cResolver, "node_import", syck_resolver_node_import, 1 );
2257
+ rb_define_method( cResolver, "tagurize", syck_resolver_tagurize, 1 );
2258
+
2259
+ oDefaultResolver = rb_funcall( cResolver, rb_intern( "new" ), 0 );
2260
+ rb_define_singleton_method( oDefaultResolver, "node_import", syck_defaultresolver_node_import, 1 );
2261
+ rb_define_singleton_method( oDefaultResolver, "detect_implicit", syck_defaultresolver_detect_implicit, 1 );
2262
+ rb_define_const( rb_syck, "DefaultResolver", oDefaultResolver );
2263
+ oGenericResolver = rb_funcall( cResolver, rb_intern( "new" ), 0 );
2264
+ rb_define_singleton_method( oGenericResolver, "node_import", syck_genericresolver_node_import, 1 );
2265
+ rb_define_const( rb_syck, "GenericResolver", oGenericResolver );
2266
+
2267
+ /*
2268
+ * Define YAML::Syck::Parser class
2269
+ */
2270
+ cParser = rb_define_class_under( rb_syck, "Parser", rb_cObject );
2271
+ rb_define_attr( cParser, "options", 1, 1 );
2272
+ rb_define_attr( cParser, "resolver", 1, 1 );
2273
+ rb_define_attr( cParser, "input", 1, 1 );
2274
+ rb_define_alloc_func( cParser, syck_parser_s_alloc );
2275
+ rb_define_method(cParser, "initialize", syck_parser_initialize, -1 );
2276
+ rb_define_method(cParser, "bufsize=", syck_parser_bufsize_set, 1 );
2277
+ rb_define_method(cParser, "bufsize", syck_parser_bufsize_get, 0 );
2278
+ rb_define_method(cParser, "load", syck_parser_load, -1);
2279
+ rb_define_method(cParser, "load_documents", syck_parser_load_documents, -1);
2280
+ rb_define_method(cParser, "set_resolver", syck_parser_set_resolver, 1);
2281
+
2282
+ /*
2283
+ * Define YAML::Syck::Node class
2284
+ */
2285
+ cNode = rb_define_class_under( rb_syck, "Node", rb_cObject );
2286
+ rb_define_method( cNode, "initialize_copy", syck_node_init_copy, 1 );
2287
+ rb_define_attr( cNode, "emitter", 1, 1 );
2288
+ rb_define_attr( cNode, "resolver", 1, 1 );
2289
+ rb_define_attr( cNode, "kind", 1, 0 );
2290
+ rb_define_attr( cNode, "type_id", 1, 0 );
2291
+ rb_define_attr( cNode, "value", 1, 0 );
2292
+ rb_define_method( cNode, "type_id=", syck_node_type_id_set, 1 );
2293
+ rb_define_method( cNode, "transform", syck_node_transform, 0);
2294
+
2295
+ /*
2296
+ * Define YAML::Syck::Scalar, YAML::Syck::Seq, YAML::Syck::Map --
2297
+ * all are the publicly usable variants of YAML::Syck::Node
2298
+ */
2299
+ cScalar = rb_define_class_under( rb_syck, "Scalar", cNode );
2300
+ rb_define_alloc_func( cScalar, syck_scalar_alloc );
2301
+ rb_define_attr( cNode, "value", 1, 0 );
2302
+ rb_define_method( cScalar, "initialize", syck_scalar_initialize, 3 );
2303
+ rb_define_method( cScalar, "value=", syck_scalar_value_set, 1 );
2304
+ rb_define_method( cScalar, "style=", syck_scalar_style_set, 1 );
2305
+ cSeq = rb_define_class_under( rb_syck, "Seq", cNode );
2306
+ rb_define_alloc_func( cSeq, syck_seq_alloc );
2307
+ rb_define_method( cSeq, "initialize", syck_seq_initialize, 3 );
2308
+ rb_define_method( cSeq, "value=", syck_seq_value_set, 1 );
2309
+ rb_define_method( cSeq, "add", syck_seq_add_m, 1 );
2310
+ rb_define_method( cSeq, "style=", syck_seq_style_set, 1 );
2311
+ cMap = rb_define_class_under( rb_syck, "Map", cNode );
2312
+ rb_define_alloc_func( cMap, syck_map_alloc );
2313
+ rb_define_method( cMap, "initialize", syck_map_initialize, 3 );
2314
+ rb_define_method( cMap, "value=", syck_map_value_set, 1 );
2315
+ rb_define_method( cMap, "add", syck_map_add_m, 2 );
2316
+ rb_define_method( cMap, "style=", syck_map_style_set, 1 );
2317
+
2318
+ /*
2319
+ * Define YAML::PrivateType class
2320
+ */
2321
+ cPrivateType = rb_define_class_under( rb_yaml, "PrivateType", rb_cObject );
2322
+ rb_define_attr( cPrivateType, "type_id", 1, 1 );
2323
+ rb_define_attr( cPrivateType, "value", 1, 1 );
2324
+ rb_define_method( cPrivateType, "initialize", syck_privatetype_initialize, 2);
2325
+
2326
+ /*
2327
+ * Define YAML::DomainType class
2328
+ */
2329
+ cDomainType = rb_define_class_under( rb_yaml, "DomainType", rb_cObject );
2330
+ rb_define_attr( cDomainType, "domain", 1, 1 );
2331
+ rb_define_attr( cDomainType, "type_id", 1, 1 );
2332
+ rb_define_attr( cDomainType, "value", 1, 1 );
2333
+ rb_define_method( cDomainType, "initialize", syck_domaintype_initialize, 3);
2334
+
2335
+ /*
2336
+ * Define YAML::Object class
2337
+ */
2338
+ cYObject = rb_define_class_under( rb_yaml, "Object", rb_cObject );
2339
+ rb_define_attr( cYObject, "class", 1, 1 );
2340
+ rb_define_attr( cYObject, "ivars", 1, 1 );
2341
+ rb_define_method( cYObject, "initialize", syck_yobject_initialize, 2);
2342
+ rb_define_method( cYObject, "yaml_initialize", syck_yobject_initialize, 2);
2343
+
2344
+ /*
2345
+ * Define YAML::Syck::BadAlias class
2346
+ */
2347
+ cBadAlias = rb_define_class_under( rb_syck, "BadAlias", rb_cObject );
2348
+ rb_define_attr( cBadAlias, "name", 1, 1 );
2349
+ rb_define_method( cBadAlias, "initialize", syck_badalias_initialize, 1);
2350
+ rb_define_method( cBadAlias, "<=>", syck_badalias_cmp, 1);
2351
+ rb_include_module( cBadAlias, rb_const_get( rb_cObject, rb_intern("Comparable") ) );
2352
+
2353
+ /*
2354
+ * Define YAML::Syck::MergeKey class
2355
+ */
2356
+ cMergeKey = rb_define_class_under( rb_syck, "MergeKey", rb_cObject );
2357
+
2358
+ /*
2359
+ * Define YAML::Syck::DefaultKey class
2360
+ */
2361
+ cDefaultKey = rb_define_class_under( rb_syck, "DefaultKey", rb_cObject );
2362
+
2363
+ /*
2364
+ * Define YAML::Syck::Out classes
2365
+ */
2366
+ cOut = rb_define_class_under( rb_syck, "Out", rb_cObject );
2367
+ rb_define_attr( cOut, "emitter", 1, 1 );
2368
+ rb_define_method( cOut, "initialize", syck_out_initialize, 1 );
2369
+ rb_define_method( cOut, "map", syck_out_map, -1 );
2370
+ rb_define_method( cOut, "seq", syck_out_seq, -1 );
2371
+ rb_define_method( cOut, "scalar", syck_out_scalar, -1 );
2372
+
2373
+ /*
2374
+ * Define YAML::Syck::Emitter class
2375
+ */
2376
+ cEmitter = rb_define_class_under( rb_syck, "Emitter", rb_cObject );
2377
+ rb_define_attr( cEmitter, "level", 1, 1 );
2378
+ rb_define_alloc_func( cEmitter, syck_emitter_s_alloc );
2379
+ rb_define_method( cEmitter, "initialize", syck_emitter_reset, -1 );
2380
+ rb_define_method( cEmitter, "reset", syck_emitter_reset, -1 );
2381
+ rb_define_method( cEmitter, "emit", syck_emitter_emit, -1 );
2382
+ rb_define_method( cEmitter, "set_resolver", syck_emitter_set_resolver, 1);
2383
+ rb_define_method( cEmitter, "node_export", syck_emitter_node_export, 1);
2384
+ }
2385
+