mkrf 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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,1224 @@
1
+ /*
2
+ * emitter.c
3
+ *
4
+ * $Author: why $
5
+ * $Date: 2005/05/19 06:07:42 $
6
+ *
7
+ * Copyright (C) 2003 why the lucky stiff
8
+ *
9
+ * All Base64 code from Ruby's pack.c.
10
+ * Ruby is Copyright (C) 1993-2003 Yukihiro Matsumoto
11
+ */
12
+ #include <stdio.h>
13
+ #include <string.h>
14
+
15
+ #include "syck.h"
16
+
17
+ #define DEFAULT_ANCHOR_FORMAT "id%03d"
18
+
19
+ const char hex_table[] =
20
+ "0123456789ABCDEF";
21
+ static char b64_table[] =
22
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
23
+
24
+ /*
25
+ * Built-in base64 (from Ruby's pack.c)
26
+ */
27
+ char *
28
+ syck_base64enc( char *s, long len )
29
+ {
30
+ long i = 0;
31
+ int padding = '=';
32
+ char *buff = S_ALLOC_N(char, len * 4 / 3 + 6);
33
+
34
+ while (len >= 3) {
35
+ buff[i++] = b64_table[077 & (*s >> 2)];
36
+ buff[i++] = b64_table[077 & (((*s << 4) & 060) | ((s[1] >> 4) & 017))];
37
+ buff[i++] = b64_table[077 & (((s[1] << 2) & 074) | ((s[2] >> 6) & 03))];
38
+ buff[i++] = b64_table[077 & s[2]];
39
+ s += 3;
40
+ len -= 3;
41
+ }
42
+ if (len == 2) {
43
+ buff[i++] = b64_table[077 & (*s >> 2)];
44
+ buff[i++] = b64_table[077 & (((*s << 4) & 060) | ((s[1] >> 4) & 017))];
45
+ buff[i++] = b64_table[077 & (((s[1] << 2) & 074) | (('\0' >> 6) & 03))];
46
+ buff[i++] = padding;
47
+ }
48
+ else if (len == 1) {
49
+ buff[i++] = b64_table[077 & (*s >> 2)];
50
+ buff[i++] = b64_table[077 & (((*s << 4) & 060) | (('\0' >> 4) & 017))];
51
+ buff[i++] = padding;
52
+ buff[i++] = padding;
53
+ }
54
+ buff[i++] = '\n';
55
+ return buff;
56
+ }
57
+
58
+ char *
59
+ syck_base64dec( char *s, long len )
60
+ {
61
+ int a = -1,b = -1,c = 0,d;
62
+ static int first = 1;
63
+ static int b64_xtable[256];
64
+ char *ptr = syck_strndup( s, len );
65
+ char *end = ptr;
66
+ char *send = s + len;
67
+
68
+ if (first) {
69
+ int i;
70
+ first = 0;
71
+
72
+ for (i = 0; i < 256; i++) {
73
+ b64_xtable[i] = -1;
74
+ }
75
+ for (i = 0; i < 64; i++) {
76
+ b64_xtable[(int)b64_table[i]] = i;
77
+ }
78
+ }
79
+ while (s < send) {
80
+ while (s[0] == '\r' || s[0] == '\n') { s++; }
81
+ if ((a = b64_xtable[(int)s[0]]) == -1) break;
82
+ if ((b = b64_xtable[(int)s[1]]) == -1) break;
83
+ if ((c = b64_xtable[(int)s[2]]) == -1) break;
84
+ if ((d = b64_xtable[(int)s[3]]) == -1) break;
85
+ *end++ = a << 2 | b >> 4;
86
+ *end++ = b << 4 | c >> 2;
87
+ *end++ = c << 6 | d;
88
+ s += 4;
89
+ }
90
+ if (a != -1 && b != -1) {
91
+ if (s + 2 < send && s[2] == '=')
92
+ *end++ = a << 2 | b >> 4;
93
+ if (c != -1 && s + 3 < send && s[3] == '=') {
94
+ *end++ = a << 2 | b >> 4;
95
+ *end++ = b << 4 | c >> 2;
96
+ }
97
+ }
98
+ *end = '\0';
99
+ /*RSTRING(buf)->len = ptr - RSTRING(buf)->ptr;*/
100
+ return ptr;
101
+ }
102
+
103
+ /*
104
+ * Allocate an emitter
105
+ */
106
+ SyckEmitter *
107
+ syck_new_emitter()
108
+ {
109
+ SyckEmitter *e;
110
+ e = S_ALLOC( SyckEmitter );
111
+ e->headless = 0;
112
+ e->use_header = 0;
113
+ e->use_version = 0;
114
+ e->sort_keys = 0;
115
+ e->anchor_format = NULL;
116
+ e->explicit_typing = 0;
117
+ e->best_width = 80;
118
+ e->style = scalar_none;
119
+ e->stage = doc_open;
120
+ e->indent = 2;
121
+ e->level = -1;
122
+ e->anchors = NULL;
123
+ e->markers = NULL;
124
+ e->anchored = NULL;
125
+ e->bufsize = SYCK_BUFFERSIZE;
126
+ e->buffer = NULL;
127
+ e->marker = NULL;
128
+ e->bufpos = 0;
129
+ e->emitter_handler = NULL;
130
+ e->output_handler = NULL;
131
+ e->lvl_idx = 0;
132
+ e->lvl_capa = ALLOC_CT;
133
+ e->levels = S_ALLOC_N( SyckLevel, e->lvl_capa );
134
+ syck_emitter_reset_levels( e );
135
+ e->bonus = NULL;
136
+ return e;
137
+ }
138
+
139
+ int
140
+ syck_st_free_anchors( char *key, char *name, char *arg )
141
+ {
142
+ S_FREE( name );
143
+ return ST_CONTINUE;
144
+ }
145
+
146
+ void
147
+ syck_emitter_st_free( SyckEmitter *e )
148
+ {
149
+ /*
150
+ * Free the anchor tables
151
+ */
152
+ if ( e->anchors != NULL )
153
+ {
154
+ st_foreach( e->anchors, syck_st_free_anchors, 0 );
155
+ st_free_table( e->anchors );
156
+ e->anchors = NULL;
157
+ }
158
+
159
+ if ( e->anchored != NULL )
160
+ {
161
+ st_free_table( e->anchored );
162
+ e->anchored = NULL;
163
+ }
164
+
165
+ /*
166
+ * Free the markers tables
167
+ */
168
+ if ( e->markers != NULL )
169
+ {
170
+ st_free_table( e->markers );
171
+ e->markers = NULL;
172
+ }
173
+ }
174
+
175
+ SyckLevel *
176
+ syck_emitter_current_level( SyckEmitter *e )
177
+ {
178
+ return &e->levels[e->lvl_idx-1];
179
+ }
180
+
181
+ SyckLevel *
182
+ syck_emitter_parent_level( SyckEmitter *e )
183
+ {
184
+ return &e->levels[e->lvl_idx-2];
185
+ }
186
+
187
+ void
188
+ syck_emitter_pop_level( SyckEmitter *e )
189
+ {
190
+ ASSERT( e != NULL );
191
+
192
+ /* The root level should never be popped */
193
+ if ( e->lvl_idx <= 1 ) return;
194
+
195
+ e->lvl_idx -= 1;
196
+ free( e->levels[e->lvl_idx].domain );
197
+ }
198
+
199
+ void
200
+ syck_emitter_add_level( SyckEmitter *e, int len, enum syck_level_status status )
201
+ {
202
+ ASSERT( e != NULL );
203
+ if ( e->lvl_idx + 1 > e->lvl_capa )
204
+ {
205
+ e->lvl_capa += ALLOC_CT;
206
+ S_REALLOC_N( e->levels, SyckLevel, e->lvl_capa );
207
+ }
208
+
209
+ ASSERT( len > e->levels[e->lvl_idx-1].spaces );
210
+ e->levels[e->lvl_idx].spaces = len;
211
+ e->levels[e->lvl_idx].ncount = 0;
212
+ e->levels[e->lvl_idx].domain = syck_strndup( e->levels[e->lvl_idx-1].domain, strlen( e->levels[e->lvl_idx-1].domain ) );
213
+ e->levels[e->lvl_idx].status = status;
214
+ e->levels[e->lvl_idx].anctag = 0;
215
+ e->lvl_idx += 1;
216
+ }
217
+
218
+ void
219
+ syck_emitter_reset_levels( SyckEmitter *e )
220
+ {
221
+ while ( e->lvl_idx > 1 )
222
+ {
223
+ syck_emitter_pop_level( e );
224
+ }
225
+
226
+ if ( e->lvl_idx < 1 )
227
+ {
228
+ e->lvl_idx = 1;
229
+ e->levels[0].spaces = -1;
230
+ e->levels[0].ncount = 0;
231
+ e->levels[0].domain = syck_strndup( "", 0 );
232
+ e->levels[0].anctag = 0;
233
+ }
234
+ e->levels[0].status = syck_lvl_header;
235
+ }
236
+
237
+ void
238
+ syck_emitter_handler( SyckEmitter *e, SyckEmitterHandler hdlr )
239
+ {
240
+ e->emitter_handler = hdlr;
241
+ }
242
+
243
+ void
244
+ syck_output_handler( SyckEmitter *e, SyckOutputHandler hdlr )
245
+ {
246
+ e->output_handler = hdlr;
247
+ }
248
+
249
+ void
250
+ syck_free_emitter( SyckEmitter *e )
251
+ {
252
+ /*
253
+ * Free tables
254
+ */
255
+ syck_emitter_st_free( e );
256
+ syck_emitter_reset_levels( e );
257
+ S_FREE( e->levels[0].domain );
258
+ S_FREE( e->levels );
259
+ if ( e->buffer != NULL )
260
+ {
261
+ S_FREE( e->buffer );
262
+ }
263
+ S_FREE( e );
264
+ }
265
+
266
+ void
267
+ syck_emitter_clear( SyckEmitter *e )
268
+ {
269
+ if ( e->buffer == NULL )
270
+ {
271
+ e->buffer = S_ALLOC_N( char, e->bufsize );
272
+ S_MEMZERO( e->buffer, char, e->bufsize );
273
+ }
274
+ e->buffer[0] = '\0';
275
+ e->marker = e->buffer;
276
+ e->bufpos = 0;
277
+ }
278
+
279
+ /*
280
+ * Raw write to the emitter buffer.
281
+ */
282
+ void
283
+ syck_emitter_write( SyckEmitter *e, char *str, long len )
284
+ {
285
+ long at;
286
+ ASSERT( str != NULL )
287
+ if ( e->buffer == NULL )
288
+ {
289
+ syck_emitter_clear( e );
290
+ }
291
+
292
+ /*
293
+ * Flush if at end of buffer
294
+ */
295
+ at = e->marker - e->buffer;
296
+ if ( len + at >= e->bufsize )
297
+ {
298
+ syck_emitter_flush( e, 0 );
299
+ for (;;) {
300
+ long rest = e->bufsize - (e->marker - e->buffer);
301
+ if (len <= rest) break;
302
+ S_MEMCPY( e->marker, str, char, rest );
303
+ e->marker += rest;
304
+ str += rest;
305
+ len -= rest;
306
+ syck_emitter_flush( e, 0 );
307
+ }
308
+ }
309
+
310
+ /*
311
+ * Write to buffer
312
+ */
313
+ S_MEMCPY( e->marker, str, char, len );
314
+ e->marker += len;
315
+ e->marker[0] = '\0';
316
+ }
317
+
318
+ /*
319
+ * Write a chunk of data out.
320
+ */
321
+ void
322
+ syck_emitter_flush( SyckEmitter *e, long check_room )
323
+ {
324
+ /*
325
+ * Check for enough space in the buffer for check_room length.
326
+ */
327
+ if ( check_room > 0 )
328
+ {
329
+ if ( e->bufsize > ( e->marker - e->buffer ) + check_room )
330
+ {
331
+ return;
332
+ }
333
+ }
334
+ else
335
+ {
336
+ check_room = e->bufsize;
337
+ }
338
+
339
+ /*
340
+ * Determine headers.
341
+ */
342
+ if ( ( e->stage == doc_open && ( e->headless == 0 || e->use_header == 1 ) ) ||
343
+ e->stage == doc_need_header )
344
+ {
345
+ if ( e->use_version == 1 )
346
+ {
347
+ char *header = S_ALLOC_N( char, 64 );
348
+ S_MEMZERO( header, char, 64 );
349
+ sprintf( header, "--- %%YAML:%d.%d ", SYCK_YAML_MAJOR, SYCK_YAML_MINOR );
350
+ (e->output_handler)( e, header, strlen( header ) );
351
+ S_FREE( header );
352
+ }
353
+ else
354
+ {
355
+ (e->output_handler)( e, "--- ", 4 );
356
+ }
357
+ e->stage = doc_processing;
358
+ }
359
+
360
+ /*
361
+ * Commit buffer.
362
+ */
363
+ if ( check_room > e->marker - e->buffer )
364
+ {
365
+ check_room = e->marker - e->buffer;
366
+ }
367
+ (e->output_handler)( e, e->buffer, check_room );
368
+ e->bufpos += check_room;
369
+ e->marker -= check_room;
370
+ }
371
+
372
+ /*
373
+ * Start emitting from the given node, check for anchoring and then
374
+ * issue the callback to the emitter handler.
375
+ */
376
+ void
377
+ syck_emit( SyckEmitter *e, st_data_t n )
378
+ {
379
+ SYMID oid;
380
+ char *anchor_name = NULL;
381
+ int indent = 0, x = 0;
382
+ SyckLevel *lvl = syck_emitter_current_level( e );
383
+
384
+ /* Add new level */
385
+ if ( lvl->spaces >= 0 ) {
386
+ indent = lvl->spaces + e->indent;
387
+ }
388
+ syck_emitter_add_level( e, indent, syck_lvl_open );
389
+ lvl = syck_emitter_current_level( e );
390
+
391
+ /* Look for anchor */
392
+ if ( e->anchors != NULL &&
393
+ st_lookup( e->markers, n, (st_data_t *)&oid ) &&
394
+ st_lookup( e->anchors, (st_data_t)oid, (st_data_t *)&anchor_name ) )
395
+ {
396
+ if ( e->anchored == NULL )
397
+ {
398
+ e->anchored = st_init_numtable();
399
+ }
400
+
401
+ if ( ! st_lookup( e->anchored, (st_data_t)anchor_name, (st_data_t *)&x ) )
402
+ {
403
+ char *an = S_ALLOC_N( char, strlen( anchor_name ) + 3 );
404
+ sprintf( an, "&%s ", anchor_name );
405
+ syck_emitter_write( e, an, strlen( anchor_name ) + 2 );
406
+ free( an );
407
+
408
+ x = 1;
409
+ st_insert( e->anchored, (st_data_t)anchor_name, (st_data_t)x );
410
+ lvl->anctag = 1;
411
+ }
412
+ else
413
+ {
414
+ char *an = S_ALLOC_N( char, strlen( anchor_name ) + 2 );
415
+ sprintf( an, "*%s", anchor_name );
416
+ syck_emitter_write( e, an, strlen( anchor_name ) + 1 );
417
+ free( an );
418
+
419
+ goto end_emit;
420
+ }
421
+ }
422
+
423
+ (e->emitter_handler)( e, n );
424
+
425
+ /* Pop the level */
426
+ end_emit:
427
+ syck_emitter_pop_level( e );
428
+ if ( e->lvl_idx == 1 ) {
429
+ syck_emitter_write( e, "\n", 1 );
430
+ e->stage = doc_open;
431
+ }
432
+ }
433
+
434
+ /*
435
+ * Determine what tag needs to be written, based on the taguri of the node
436
+ * and the implicit tag which would be assigned to this node. If a tag is
437
+ * required, write the tag.
438
+ */
439
+ void syck_emit_tag( SyckEmitter *e, char *tag, char *ignore )
440
+ {
441
+ SyckLevel *lvl;
442
+ if ( tag == NULL ) return;
443
+ if ( ignore != NULL && syck_tagcmp( tag, ignore ) == 0 && e->explicit_typing == 0 ) return;
444
+ lvl = syck_emitter_current_level( e );
445
+
446
+ /* implicit */
447
+ if ( strlen( tag ) == 0 ) {
448
+ syck_emitter_write( e, "! ", 2 );
449
+
450
+ /* global types */
451
+ } else if ( strncmp( tag, "tag:", 4 ) == 0 ) {
452
+ int taglen = strlen( tag );
453
+ syck_emitter_write( e, "!", 1 );
454
+ if ( strncmp( tag + 4, YAML_DOMAIN, strlen( YAML_DOMAIN ) ) == 0 ) {
455
+ int skip = 4 + strlen( YAML_DOMAIN ) + 1;
456
+ syck_emitter_write( e, tag + skip, taglen - skip );
457
+ } else {
458
+ char *subd = tag + 4;
459
+ while ( *subd != ':' && *subd != '\0' ) subd++;
460
+ if ( *subd == ':' ) {
461
+ if ( subd - tag > ( strlen( YAML_DOMAIN ) + 5 ) &&
462
+ strncmp( subd - strlen( YAML_DOMAIN ), YAML_DOMAIN, strlen( YAML_DOMAIN ) ) == 0 ) {
463
+ syck_emitter_write( e, tag + 4, subd - strlen( YAML_DOMAIN ) - ( tag + 4 ) - 1 );
464
+ syck_emitter_write( e, "/", 1 );
465
+ syck_emitter_write( e, subd + 1, ( tag + taglen ) - ( subd + 1 ) );
466
+ } else {
467
+ syck_emitter_write( e, tag + 4, subd - ( tag + 4 ) );
468
+ syck_emitter_write( e, "/", 1 );
469
+ syck_emitter_write( e, subd + 1, ( tag + taglen ) - ( subd + 1 ) );
470
+ }
471
+ } else {
472
+ /* TODO: Invalid tag (no colon after domain) */
473
+ return;
474
+ }
475
+ }
476
+ syck_emitter_write( e, " ", 1 );
477
+
478
+ /* private types */
479
+ } else if ( strncmp( tag, "x-private:", 10 ) == 0 ) {
480
+ syck_emitter_write( e, "!!", 2 );
481
+ syck_emitter_write( e, tag + 10, strlen( tag ) - 10 );
482
+ syck_emitter_write( e, " ", 1 );
483
+ }
484
+ lvl->anctag = 1;
485
+ }
486
+
487
+ /*
488
+ * Emit a newline and an appropriately spaced indent.
489
+ */
490
+ void syck_emit_indent( SyckEmitter *e )
491
+ {
492
+ int i;
493
+ SyckLevel *lvl = syck_emitter_current_level( e );
494
+ if ( lvl->spaces >= 0 ) {
495
+ char *spcs = S_ALLOC_N( char, lvl->spaces + 2 );
496
+
497
+ spcs[0] = '\n'; spcs[lvl->spaces + 1] = '\0';
498
+ for ( i = 0; i < lvl->spaces; i++ ) spcs[i+1] = ' ';
499
+ syck_emitter_write( e, spcs, lvl->spaces + 1 );
500
+ free( spcs );
501
+ }
502
+ }
503
+
504
+ /* Clear the scan */
505
+ #define SCAN_NONE 0
506
+ /* All printable characters? */
507
+ #define SCAN_NONPRINT 1
508
+ /* Any indented lines? */
509
+ #define SCAN_INDENTED 2
510
+ /* Larger than the requested width? */
511
+ #define SCAN_WIDE 4
512
+ /* Opens with whitespace? */
513
+ #define SCAN_WHITESTART 8
514
+ /* Contains a newline */
515
+ #define SCAN_NEWLINE 16
516
+ /* Contains a single quote */
517
+ #define SCAN_SINGLEQ 32
518
+ /* Contains a double quote */
519
+ #define SCAN_DOUBLEQ 64
520
+ /* Starts with a token */
521
+ #define SCAN_INDIC_S 128
522
+ /* Contains a flow indicator */
523
+ #define SCAN_INDIC_C 256
524
+ /* Ends without newlines */
525
+ #define SCAN_NONL_E 512
526
+ /* Ends with many newlines */
527
+ #define SCAN_MANYNL_E 1024
528
+ /* Contains flow map indicators */
529
+ #define SCAN_FLOWMAP 2048
530
+ /* Contains flow seq indicators */
531
+ #define SCAN_FLOWSEQ 4096
532
+ /* Contains a valid doc separator */
533
+ #define SCAN_DOCSEP 8192
534
+
535
+ /*
536
+ * Basic printable test for LATIN-1 characters.
537
+ */
538
+ int
539
+ syck_scan_scalar( int req_width, char *cursor, long len )
540
+ {
541
+ long i = 0, start = 0;
542
+ int flags = SCAN_NONE;
543
+
544
+ if ( len < 1 ) return flags;
545
+
546
+ /* c-indicators from the spec */
547
+ if ( cursor[0] == '[' || cursor[0] == ']' ||
548
+ cursor[0] == '{' || cursor[0] == '}' ||
549
+ cursor[0] == '!' || cursor[0] == '*' ||
550
+ cursor[0] == '&' || cursor[0] == '|' ||
551
+ cursor[0] == '>' || cursor[0] == '\'' ||
552
+ cursor[0] == '"' || cursor[0] == '#' ||
553
+ cursor[0] == '%' || cursor[0] == '@' ||
554
+ cursor[0] == '&' ) {
555
+ flags |= SCAN_INDIC_S;
556
+ }
557
+ if ( ( cursor[0] == '-' || cursor[0] == ':' ||
558
+ cursor[0] == '?' || cursor[0] == ',' ) &&
559
+ cursor[1] == ' ' ) {
560
+ flags |= SCAN_INDIC_S;
561
+ }
562
+
563
+ /* ending newlines */
564
+ if ( cursor[len-1] != '\n' ) {
565
+ flags |= SCAN_NONL_E;
566
+ } else if ( len > 1 && cursor[len-2] == '\n' ) {
567
+ flags |= SCAN_MANYNL_E;
568
+ }
569
+
570
+ /* opening doc sep */
571
+ if ( len >= 3 && strncmp( cursor, "---", 3 ) == 0 )
572
+ flags |= SCAN_DOCSEP;
573
+
574
+ /* scan string */
575
+ for ( i = 0; i < len; i++ ) {
576
+
577
+ if ( ! ( cursor[i] == 0x9 ||
578
+ cursor[i] == 0xA ||
579
+ cursor[i] == 0xD ||
580
+ ( cursor[i] >= 0x20 && cursor[i] <= 0x7E ) )
581
+ ) {
582
+ flags |= SCAN_NONPRINT;
583
+ }
584
+ else if ( cursor[i] == '\n' ) {
585
+ flags |= SCAN_NEWLINE;
586
+ if ( len - i >= 3 && strncmp( &cursor[i+1], "---", 3 ) == 0 )
587
+ flags |= SCAN_DOCSEP;
588
+ if ( cursor[i+1] == ' ' || cursor[i+1] == '\t' )
589
+ flags |= SCAN_INDENTED;
590
+ if ( req_width > 0 && i - start > req_width )
591
+ flags |= SCAN_WIDE;
592
+ start = i;
593
+ }
594
+ else if ( cursor[i] == '\'' )
595
+ {
596
+ flags |= SCAN_SINGLEQ;
597
+ }
598
+ else if ( cursor[i] == '"' )
599
+ {
600
+ flags |= SCAN_DOUBLEQ;
601
+ }
602
+ else if ( cursor[i] == ']' )
603
+ {
604
+ flags |= SCAN_FLOWSEQ;
605
+ }
606
+ else if ( cursor[i] == '}' )
607
+ {
608
+ flags |= SCAN_FLOWMAP;
609
+ }
610
+ /* remember, if plain collections get implemented, to add nb-plain-flow-char */
611
+ else if ( ( cursor[i] == ' ' && cursor[i+1] == '#' ) ||
612
+ ( cursor[i] == ':' && cursor[i+1] == ' ' ) )
613
+ {
614
+ flags |= SCAN_INDIC_C;
615
+ }
616
+ else if ( cursor[i] == ',' && cursor[i+1] == ' ' )
617
+ {
618
+ flags |= SCAN_FLOWMAP;
619
+ flags |= SCAN_FLOWSEQ;
620
+ }
621
+
622
+ if ( i == 0 &&
623
+ ( cursor[i] == ' ' || cursor[i] == '\t' )
624
+ ) {
625
+ flags |= SCAN_WHITESTART;
626
+ }
627
+ }
628
+
629
+ /* printf( "---STR---\n%s\nFLAGS: %d\n", cursor, flags ); */
630
+ return flags;
631
+ }
632
+ /*
633
+ * All scalars should be emitted through this function, which determines an appropriate style,
634
+ * tag and indent.
635
+ */
636
+ void syck_emit_scalar( SyckEmitter *e, char *tag, enum scalar_style force_style, int force_indent, int force_width,
637
+ char keep_nl, char *str, long len )
638
+ {
639
+ enum scalar_style favor_style = scalar_literal;
640
+ SyckLevel *parent = syck_emitter_parent_level( e );
641
+ SyckLevel *lvl = syck_emitter_current_level( e );
642
+ int scan;
643
+ char *implicit;
644
+
645
+ if ( str == NULL ) str = "";
646
+
647
+ /* No empty nulls as map keys */
648
+ if ( len == 0 && ( parent->status == syck_lvl_map || parent->status == syck_lvl_imap ) &&
649
+ parent->ncount % 2 == 1 && syck_tagcmp( tag, "tag:yaml.org,2002:null" ) == 0 )
650
+ {
651
+ str = "~";
652
+ len = 1;
653
+ }
654
+
655
+ scan = syck_scan_scalar( force_width, str, len );
656
+ implicit = syck_match_implicit( str, len );
657
+
658
+ /* quote strings which default to implicits */
659
+ implicit = syck_taguri( YAML_DOMAIN, implicit, strlen( implicit ) );
660
+ if ( syck_tagcmp( tag, implicit ) != 0 && syck_tagcmp( tag, "tag:yaml.org,2002:str" ) == 0 ) {
661
+ force_style = scalar_2quote;
662
+ } else {
663
+ syck_emit_tag( e, tag, implicit );
664
+ }
665
+ S_FREE( implicit );
666
+
667
+ /* if still arbitrary, sniff a good block style. */
668
+ if ( force_style == scalar_none ) {
669
+ if ( scan & SCAN_NEWLINE ) {
670
+ force_style = scalar_literal;
671
+ } else {
672
+ force_style = scalar_plain;
673
+ }
674
+ }
675
+
676
+ if ( e->style == scalar_fold ) {
677
+ favor_style = scalar_fold;
678
+ }
679
+
680
+ /* Determine block style */
681
+ if ( scan & SCAN_NONPRINT ) {
682
+ force_style = scalar_2quote;
683
+ } else if ( scan & SCAN_WHITESTART ) {
684
+ force_style = scalar_2quote;
685
+ } else if ( force_style != scalar_fold && ( scan & SCAN_INDENTED ) ) {
686
+ force_style = scalar_literal;
687
+ } else if ( force_style == scalar_plain && ( scan & SCAN_NEWLINE ) ) {
688
+ force_style = favor_style;
689
+ } else if ( force_style == scalar_plain && parent->status == syck_lvl_iseq && ( scan & SCAN_FLOWSEQ ) ) {
690
+ force_style = scalar_2quote;
691
+ } else if ( force_style == scalar_plain && parent->status == syck_lvl_imap && ( scan & SCAN_FLOWMAP ) ) {
692
+ force_style = scalar_2quote;
693
+ /* } else if ( force_style == scalar_fold && ( ! ( scan & SCAN_WIDE ) ) ) {
694
+ force_style = scalar_literal; */
695
+ } else if ( force_style == scalar_plain && ( scan & SCAN_INDIC_S || scan & SCAN_INDIC_C ) ) {
696
+ if ( scan & SCAN_NEWLINE ) {
697
+ force_style = favor_style;
698
+ } else {
699
+ force_style = scalar_2quote;
700
+ }
701
+ }
702
+
703
+ if ( force_indent > 0 ) {
704
+ lvl->spaces = parent->spaces + force_indent;
705
+ } else if ( scan & SCAN_DOCSEP ) {
706
+ lvl->spaces = parent->spaces + e->indent;
707
+ }
708
+
709
+ /* For now, all ambiguous keys are going to be double-quoted */
710
+ if ( parent->status == syck_lvl_map && parent->ncount % 2 == 1 ) {
711
+ if ( force_style != scalar_plain ) {
712
+ force_style = scalar_2quote;
713
+ }
714
+ }
715
+
716
+ /* If the parent is an inline, double quote anything complex */
717
+ if ( parent->status == syck_lvl_imap || parent->status == syck_lvl_iseq ) {
718
+ if ( force_style != scalar_plain && force_style != scalar_1quote ) {
719
+ force_style = scalar_2quote;
720
+ }
721
+ }
722
+
723
+ /* Fix the ending newlines */
724
+ if ( scan & SCAN_NONL_E ) {
725
+ keep_nl = NL_CHOMP;
726
+ } else if ( scan & SCAN_MANYNL_E ) {
727
+ keep_nl = NL_KEEP;
728
+ }
729
+
730
+ /* Write the text node */
731
+ switch ( force_style )
732
+ {
733
+ case scalar_1quote:
734
+ syck_emit_1quoted( e, force_width, str, len );
735
+ break;
736
+
737
+ case scalar_2quote:
738
+ syck_emit_2quoted( e, force_width, str, len );
739
+ break;
740
+
741
+ case scalar_fold:
742
+ syck_emit_folded( e, force_width, keep_nl, str, len );
743
+ break;
744
+
745
+ case scalar_literal:
746
+ syck_emit_literal( e, keep_nl, str, len );
747
+ break;
748
+
749
+ case scalar_plain:
750
+ syck_emitter_write( e, str, len );
751
+ break;
752
+ }
753
+ }
754
+
755
+ void
756
+ syck_emitter_escape( SyckEmitter *e, char *src, long len )
757
+ {
758
+ int i;
759
+ for( i = 0; i < len; i++ )
760
+ {
761
+ if( (src[i] < 0x20) || (0x7E < src[i]) )
762
+ {
763
+ syck_emitter_write( e, "\\", 1 );
764
+ if( '\0' == src[i] )
765
+ syck_emitter_write( e, "0", 1 );
766
+ else
767
+ {
768
+ syck_emitter_write( e, "x", 1 );
769
+ syck_emitter_write( e, (char *)hex_table + ((src[i] & 0xF0) >> 4), 1 );
770
+ syck_emitter_write( e, (char *)hex_table + (src[i] & 0x0F), 1 );
771
+ }
772
+ }
773
+ else
774
+ {
775
+ syck_emitter_write( e, src + i, 1 );
776
+ if( '\\' == src[i] )
777
+ syck_emitter_write( e, "\\", 1 );
778
+ }
779
+ }
780
+ }
781
+
782
+ /*
783
+ * Outputs a single-quoted block.
784
+ */
785
+ void syck_emit_1quoted( SyckEmitter *e, int width, char *str, long len )
786
+ {
787
+ char do_indent = 0;
788
+ char *mark = str;
789
+ char *start = str;
790
+ char *end = str;
791
+ syck_emitter_write( e, "'", 1 );
792
+ while ( mark < str + len ) {
793
+ if ( do_indent ) {
794
+ syck_emit_indent( e );
795
+ do_indent = 0;
796
+ }
797
+ switch ( *mark ) {
798
+ case '\'': syck_emitter_write( e, "'", 1 ); break;
799
+
800
+ case '\n':
801
+ end = mark + 1;
802
+ if ( *start != ' ' && *start != '\n' && *end != '\n' && *end != ' ' ) {
803
+ syck_emitter_write( e, "\n\n", 2 );
804
+ } else {
805
+ syck_emitter_write( e, "\n", 1 );
806
+ }
807
+ do_indent = 1;
808
+ start = mark + 1;
809
+ break;
810
+
811
+ case ' ':
812
+ if ( width > 0 && *start != ' ' && mark - end > width ) {
813
+ do_indent = 1;
814
+ end = mark + 1;
815
+ } else {
816
+ syck_emitter_write( e, " ", 1 );
817
+ }
818
+ break;
819
+
820
+ default:
821
+ syck_emitter_write( e, mark, 1 );
822
+ break;
823
+ }
824
+ mark++;
825
+ }
826
+ syck_emitter_write( e, "'", 1 );
827
+ }
828
+
829
+ /*
830
+ * Outputs a double-quoted block.
831
+ */
832
+ void syck_emit_2quoted( SyckEmitter *e, int width, char *str, long len )
833
+ {
834
+ char do_indent = 0;
835
+ char *mark = str;
836
+ char *start = str;
837
+ char *end = str;
838
+ syck_emitter_write( e, "\"", 1 );
839
+ while ( mark < str + len ) {
840
+ if ( do_indent > 0 ) {
841
+ if ( do_indent == 2 ) {
842
+ syck_emitter_write( e, "\\", 1 );
843
+ }
844
+ syck_emit_indent( e );
845
+ do_indent = 0;
846
+ }
847
+ switch ( *mark ) {
848
+
849
+ /* Escape sequences allowed within double quotes. */
850
+ case '"': syck_emitter_write( e, "\\\"", 2 ); break;
851
+ case '\\': syck_emitter_write( e, "\\\\", 2 ); break;
852
+ case '\0': syck_emitter_write( e, "\\0", 2 ); break;
853
+ case '\a': syck_emitter_write( e, "\\a", 2 ); break;
854
+ case '\b': syck_emitter_write( e, "\\b", 2 ); break;
855
+ case '\f': syck_emitter_write( e, "\\f", 2 ); break;
856
+ case '\r': syck_emitter_write( e, "\\r", 2 ); break;
857
+ case '\t': syck_emitter_write( e, "\\t", 2 ); break;
858
+ case '\v': syck_emitter_write( e, "\\v", 2 ); break;
859
+ case 0x1b: syck_emitter_write( e, "\\e", 2 ); break;
860
+
861
+ case '\n':
862
+ end = mark + 1;
863
+ syck_emitter_write( e, "\\n", 2 );
864
+ do_indent = 2;
865
+ start = mark + 1;
866
+ if ( start < str + len && ( *start == ' ' || *start == '\n' ) ) {
867
+ do_indent = 0;
868
+ }
869
+ break;
870
+
871
+ case ' ':
872
+ if ( width > 0 && *start != ' ' && mark - end > width ) {
873
+ do_indent = 1;
874
+ end = mark + 1;
875
+ } else {
876
+ syck_emitter_write( e, " ", 1 );
877
+ }
878
+ break;
879
+
880
+ default:
881
+ syck_emitter_escape( e, mark, 1 );
882
+ break;
883
+ }
884
+ mark++;
885
+ }
886
+ syck_emitter_write( e, "\"", 1 );
887
+ }
888
+
889
+ /*
890
+ * Outputs a literal block.
891
+ */
892
+ void syck_emit_literal( SyckEmitter *e, char keep_nl, char *str, long len )
893
+ {
894
+ char *mark = str;
895
+ char *start = str;
896
+ char *end = str;
897
+ syck_emitter_write( e, "|", 1 );
898
+ if ( keep_nl == NL_CHOMP ) {
899
+ syck_emitter_write( e, "-", 1 );
900
+ } else if ( keep_nl == NL_KEEP ) {
901
+ syck_emitter_write( e, "+", 1 );
902
+ }
903
+ syck_emit_indent( e );
904
+ while ( mark < str + len ) {
905
+ if ( *mark == '\n' ) {
906
+ end = mark;
907
+ if ( *start != ' ' && *start != '\n' && *end != '\n' && *end != ' ' ) end += 1;
908
+ syck_emitter_write( e, start, end - start );
909
+ if ( mark + 1 == str + len ) {
910
+ if ( keep_nl != NL_KEEP ) syck_emitter_write( e, "\n", 1 );
911
+ } else {
912
+ syck_emit_indent( e );
913
+ }
914
+ start = mark + 1;
915
+ }
916
+ mark++;
917
+ }
918
+ end = str + len;
919
+ if ( start < end ) {
920
+ syck_emitter_write( e, start, end - start );
921
+ }
922
+ }
923
+
924
+ /*
925
+ * Outputs a folded block.
926
+ */
927
+ void syck_emit_folded( SyckEmitter *e, int width, char keep_nl, char *str, long len )
928
+ {
929
+ char *mark = str;
930
+ char *start = str;
931
+ char *end = str;
932
+ syck_emitter_write( e, ">", 1 );
933
+ if ( keep_nl == NL_CHOMP ) {
934
+ syck_emitter_write( e, "-", 1 );
935
+ } else if ( keep_nl == NL_KEEP ) {
936
+ syck_emitter_write( e, "+", 1 );
937
+ }
938
+ syck_emit_indent( e );
939
+ if ( width <= 0 ) width = e->best_width;
940
+ while ( mark < str + len ) {
941
+ switch ( *mark ) {
942
+ case '\n':
943
+ syck_emitter_write( e, end, mark - end );
944
+ end = mark + 1;
945
+ if ( *start != ' ' && *start != '\n' && *end != '\n' && *end != ' ' ) {
946
+ syck_emitter_write( e, "\n", 1 );
947
+ }
948
+ if ( mark + 1 == str + len ) {
949
+ if ( keep_nl != NL_KEEP ) syck_emitter_write( e, "\n", 1 );
950
+ } else {
951
+ syck_emit_indent( e );
952
+ }
953
+ start = mark + 1;
954
+ break;
955
+
956
+ case ' ':
957
+ if ( *start != ' ' ) {
958
+ if ( mark - end > width ) {
959
+ syck_emitter_write( e, end, mark - end );
960
+ syck_emit_indent( e );
961
+ end = mark + 1;
962
+ }
963
+ }
964
+ break;
965
+ }
966
+ mark++;
967
+ }
968
+ if ( end < mark ) {
969
+ syck_emitter_write( e, end, mark - end );
970
+ }
971
+ }
972
+
973
+ /*
974
+ * Begins emission of a sequence.
975
+ */
976
+ void syck_emit_seq( SyckEmitter *e, char *tag, enum seq_style style )
977
+ {
978
+ SyckLevel *parent = syck_emitter_parent_level( e );
979
+ SyckLevel *lvl = syck_emitter_current_level( e );
980
+ syck_emit_tag( e, tag, "tag:yaml.org,2002:seq" );
981
+ if ( style == seq_inline || ( parent->status == syck_lvl_imap || parent->status == syck_lvl_iseq ) ) {
982
+ syck_emitter_write( e, "[", 1 );
983
+ lvl->status = syck_lvl_iseq;
984
+ } else {
985
+ lvl->status = syck_lvl_seq;
986
+ }
987
+ }
988
+
989
+ /*
990
+ * Begins emission of a mapping.
991
+ */
992
+ void syck_emit_map( SyckEmitter *e, char *tag, enum map_style style )
993
+ {
994
+ SyckLevel *parent = syck_emitter_parent_level( e );
995
+ SyckLevel *lvl = syck_emitter_current_level( e );
996
+ syck_emit_tag( e, tag, "tag:yaml.org,2002:map" );
997
+ if ( style == map_inline || ( parent->status == syck_lvl_imap || parent->status == syck_lvl_iseq ) ) {
998
+ syck_emitter_write( e, "{", 1 );
999
+ lvl->status = syck_lvl_imap;
1000
+ } else {
1001
+ lvl->status = syck_lvl_map;
1002
+ }
1003
+ }
1004
+
1005
+ /*
1006
+ * Handles emitting of a collection item (for both
1007
+ * sequences and maps)
1008
+ */
1009
+ void syck_emit_item( SyckEmitter *e, st_data_t n )
1010
+ {
1011
+ SyckLevel *lvl = syck_emitter_current_level( e );
1012
+ switch ( lvl->status )
1013
+ {
1014
+ case syck_lvl_seq:
1015
+ {
1016
+ SyckLevel *parent = syck_emitter_parent_level( e );
1017
+
1018
+ /* seq-in-map shortcut */
1019
+ if ( parent->status == syck_lvl_map && lvl->ncount == 0 ) {
1020
+ /* complex key */
1021
+ if ( parent->ncount % 2 == 1 ) {
1022
+ syck_emitter_write( e, "?", 1 );
1023
+ parent->status = syck_lvl_mapx;
1024
+ /* shortcut -- the lvl->anctag check should be unneccesary but
1025
+ * there is a nasty shift/reduce in the parser on this point and
1026
+ * i'm not ready to tickle it. */
1027
+ } else if ( lvl->anctag == 0 ) {
1028
+ lvl->spaces = parent->spaces;
1029
+ }
1030
+ }
1031
+
1032
+ /* seq-in-seq shortcut */
1033
+ else if ( lvl->anctag == 0 && parent->status == syck_lvl_seq && lvl->ncount == 0 ) {
1034
+ int spcs = ( lvl->spaces - parent->spaces ) - 2;
1035
+ if ( spcs >= 0 ) {
1036
+ int i = 0;
1037
+ for ( i = 0; i < spcs; i++ ) {
1038
+ syck_emitter_write( e, " ", 1 );
1039
+ }
1040
+ syck_emitter_write( e, "- ", 2 );
1041
+ break;
1042
+ }
1043
+ }
1044
+
1045
+ syck_emit_indent( e );
1046
+ syck_emitter_write( e, "- ", 2 );
1047
+ }
1048
+ break;
1049
+
1050
+ case syck_lvl_iseq:
1051
+ {
1052
+ if ( lvl->ncount > 0 ) {
1053
+ syck_emitter_write( e, ", ", 2 );
1054
+ }
1055
+ }
1056
+ break;
1057
+
1058
+ case syck_lvl_map:
1059
+ {
1060
+ SyckLevel *parent = syck_emitter_parent_level( e );
1061
+
1062
+ /* map-in-map */
1063
+ if ( parent->status == syck_lvl_map && lvl->ncount == 0 ) {
1064
+ /* complex key */
1065
+ if ( parent->ncount % 2 == 1 ) {
1066
+ syck_emitter_write( e, "?", 1 );
1067
+ parent->status = syck_lvl_mapx;
1068
+ }
1069
+ }
1070
+
1071
+ /* map-in-seq shortcut */
1072
+ if ( lvl->anctag == 0 && parent->status == syck_lvl_seq && lvl->ncount == 0 ) {
1073
+ int spcs = ( lvl->spaces - parent->spaces ) - 2;
1074
+ if ( spcs >= 0 ) {
1075
+ int i = 0;
1076
+ for ( i = 0; i < spcs; i++ ) {
1077
+ syck_emitter_write( e, " ", 1 );
1078
+ }
1079
+ break;
1080
+ }
1081
+ }
1082
+
1083
+ if ( lvl->ncount % 2 == 0 ) {
1084
+ syck_emit_indent( e );
1085
+ } else {
1086
+ syck_emitter_write( e, ": ", 2 );
1087
+ }
1088
+ }
1089
+ break;
1090
+
1091
+ case syck_lvl_mapx:
1092
+ {
1093
+ if ( lvl->ncount % 2 == 0 ) {
1094
+ syck_emit_indent( e );
1095
+ lvl->status = syck_lvl_map;
1096
+ } else {
1097
+ int i;
1098
+ if ( lvl->spaces > 0 ) {
1099
+ char *spcs = S_ALLOC_N( char, lvl->spaces + 1 );
1100
+
1101
+ spcs[lvl->spaces] = '\0';
1102
+ for ( i = 0; i < lvl->spaces; i++ ) spcs[i] = ' ';
1103
+ syck_emitter_write( e, spcs, lvl->spaces );
1104
+ S_FREE( spcs );
1105
+ }
1106
+ syck_emitter_write( e, ": ", 2 );
1107
+ }
1108
+ }
1109
+ break;
1110
+
1111
+ case syck_lvl_imap:
1112
+ {
1113
+ if ( lvl->ncount > 0 ) {
1114
+ if ( lvl->ncount % 2 == 0 ) {
1115
+ syck_emitter_write( e, ", ", 2 );
1116
+ } else {
1117
+ syck_emitter_write( e, ": ", 2 );
1118
+ }
1119
+ }
1120
+ }
1121
+ break;
1122
+ }
1123
+ lvl->ncount++;
1124
+
1125
+ syck_emit( e, n );
1126
+ }
1127
+
1128
+ /*
1129
+ * Closes emission of a collection.
1130
+ */
1131
+ void syck_emit_end( SyckEmitter *e )
1132
+ {
1133
+ SyckLevel *lvl = syck_emitter_current_level( e );
1134
+ SyckLevel *parent = syck_emitter_parent_level( e );
1135
+ switch ( lvl->status )
1136
+ {
1137
+ case syck_lvl_seq:
1138
+ if ( lvl->ncount == 0 ) {
1139
+ syck_emitter_write( e, "[]\n", 3 );
1140
+ } else if ( parent->status == syck_lvl_mapx ) {
1141
+ syck_emitter_write( e, "\n", 1 );
1142
+ }
1143
+ break;
1144
+
1145
+ case syck_lvl_iseq:
1146
+ syck_emitter_write( e, "]\n", 1 );
1147
+ break;
1148
+
1149
+ case syck_lvl_map:
1150
+ if ( lvl->ncount == 0 ) {
1151
+ syck_emitter_write( e, "{}\n", 3 );
1152
+ } else if ( lvl->ncount % 2 == 1 ) {
1153
+ syck_emitter_write( e, ":\n", 1 );
1154
+ } else if ( parent->status == syck_lvl_mapx ) {
1155
+ syck_emitter_write( e, "\n", 1 );
1156
+ }
1157
+ break;
1158
+
1159
+ case syck_lvl_imap:
1160
+ syck_emitter_write( e, "}\n", 1 );
1161
+ break;
1162
+ }
1163
+ }
1164
+
1165
+ /*
1166
+ * Fill markers table with emitter nodes in the
1167
+ * soon-to-be-emitted tree.
1168
+ */
1169
+ SYMID
1170
+ syck_emitter_mark_node( SyckEmitter *e, st_data_t n )
1171
+ {
1172
+ SYMID oid = 0;
1173
+ char *anchor_name = NULL;
1174
+
1175
+ /*
1176
+ * Ensure markers table is initialized.
1177
+ */
1178
+ if ( e->markers == NULL )
1179
+ {
1180
+ e->markers = st_init_numtable();
1181
+ }
1182
+
1183
+ /*
1184
+ * Markers table initially marks the string position of the
1185
+ * object. Doesn't yet create an anchor, simply notes the
1186
+ * position.
1187
+ */
1188
+ if ( ! st_lookup( e->markers, n, (st_data_t *)&oid ) )
1189
+ {
1190
+ /*
1191
+ * Store all markers
1192
+ */
1193
+ oid = e->markers->num_entries + 1;
1194
+ st_insert( e->markers, n, (st_data_t)oid );
1195
+ }
1196
+ else
1197
+ {
1198
+ if ( e->anchors == NULL )
1199
+ {
1200
+ e->anchors = st_init_numtable();
1201
+ }
1202
+
1203
+ if ( ! st_lookup( e->anchors, (st_data_t)oid, (st_data_t *)&anchor_name ) )
1204
+ {
1205
+ int idx = 0;
1206
+ char *anc = ( e->anchor_format == NULL ? DEFAULT_ANCHOR_FORMAT : e->anchor_format );
1207
+
1208
+ /*
1209
+ * Second time hitting this object, let's give it an anchor
1210
+ */
1211
+ idx = e->anchors->num_entries + 1;
1212
+ anchor_name = S_ALLOC_N( char, strlen( anc ) + 10 );
1213
+ S_MEMZERO( anchor_name, char, strlen( anc ) + 10 );
1214
+ sprintf( anchor_name, anc, idx );
1215
+
1216
+ /*
1217
+ * Insert into anchors table
1218
+ */
1219
+ st_insert( e->anchors, (st_data_t)oid, (st_data_t)anchor_name );
1220
+ }
1221
+ }
1222
+ return oid;
1223
+ }
1224
+