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,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
+