1 #include <yaml.h>
2
3 #include <stdlib.h>
4 #include <stdio.h>
5 #include <assert.h>
6 #include "../src/yaml_private.h"
7
8 int get_line(FILE * input, char *line);
9 char *get_anchor(char sigil, char *line, char *anchor);
10 char *get_tag(char *line, char *tag);
11 void get_value(char *line, char *value, int *style);
12 int usage(int ret);
13
main(int argc,char * argv[])14 int main(int argc, char *argv[])
15 {
16 FILE *input;
17 yaml_emitter_t emitter;
18 yaml_event_t event;
19 yaml_version_directive_t *version_directive = NULL;
20
21 int canonical = 0;
22 int unicode = 0;
23 char line[1024];
24 int foundfile = 0;
25 int i = 0;
26 int minor = 0;
27 int flow = -1; /** default no flow style collections */
28
29 for (i = 1; i < argc; i++) {
30 if (strncmp(argv[i], "--help", 6) == 0)
31 return usage(0);
32 if (strncmp(argv[i], "-h", 2) == 0)
33 return usage(0);
34 if (strncmp(argv[i], "--flow", 6) == 0) {
35 if (i+1 == argc)
36 return usage(1);
37 i++;
38 if (strncmp(argv[i], "keep", 4) == 0)
39 flow = 0;
40 else if (strncmp(argv[i], "on", 2) == 0)
41 flow = 1;
42 else if (strncmp(argv[i], "off", 3) == 0)
43 flow = -1;
44 else
45 return usage(1);
46 }
47 else if (strncmp(argv[i], "--directive", 11) == 0) {
48 if (i+1 == argc)
49 return usage(1);
50 i++;
51 if (strncmp(argv[i], "1.1", 3) == 0)
52 minor = 1;
53 else if (strncmp(argv[i], "1.2", 3) == 0)
54 minor = 2;
55 else
56 return usage(1);
57 }
58 else if (!foundfile) {
59 input = fopen(argv[i], "rb");
60 foundfile = 1;
61 }
62
63 }
64 if (minor) {
65 version_directive = YAML_MALLOC_STATIC(yaml_version_directive_t);
66 version_directive->major = 1;
67 version_directive->minor = minor;
68 }
69 if (!foundfile)
70 input = stdin;
71
72 assert(input);
73
74 if (!yaml_emitter_initialize(&emitter)) {
75 fprintf(stderr, "Could not initalize the emitter object\n");
76 return 1;
77 }
78 yaml_emitter_set_output_file(&emitter, stdout);
79 yaml_emitter_set_canonical(&emitter, canonical);
80 yaml_emitter_set_unicode(&emitter, unicode);
81
82
83 while (get_line(input, line)) {
84 int ok;
85 char anchor[256];
86 char tag[256];
87 int implicit;
88 int style;
89
90 if (strncmp(line, "+STR", 4) == 0) {
91 ok = yaml_stream_start_event_initialize(&event, YAML_UTF8_ENCODING);
92 }
93 else if (strncmp(line, "-STR", 4) == 0) {
94 ok = yaml_stream_end_event_initialize(&event);
95 }
96 else if (strncmp(line, "+DOC", 4) == 0) {
97 implicit = strncmp(line+4, " ---", 4) != 0;
98 ok = yaml_document_start_event_initialize(&event, version_directive, NULL, NULL, implicit);
99 }
100 else if (strncmp(line, "-DOC", 4) == 0) {
101 implicit = strncmp(line+4, " ...", 4) != 0;
102 ok = yaml_document_end_event_initialize(&event, implicit);
103 }
104 else if (strncmp(line, "+MAP", 4) == 0) {
105 style = YAML_BLOCK_MAPPING_STYLE;
106 if (flow == 1)
107 style = YAML_FLOW_MAPPING_STYLE;
108 else if (flow == 0 && strncmp(line+5, "{}", 2) == 0)
109 style = YAML_FLOW_MAPPING_STYLE;
110 ok = yaml_mapping_start_event_initialize(&event, (yaml_char_t *)
111 get_anchor('&', line, anchor), (yaml_char_t *)
112 get_tag(line, tag), 0, style);
113 }
114 else if (strncmp(line, "-MAP", 4) == 0) {
115 ok = yaml_mapping_end_event_initialize(&event);
116 }
117 else if (strncmp(line, "+SEQ", 4) == 0) {
118 style = YAML_BLOCK_SEQUENCE_STYLE;
119 if (flow == 1)
120 style = YAML_FLOW_MAPPING_STYLE;
121 else if (flow == 0 && strncmp(line+5, "[]", 2) == 0)
122 style = YAML_FLOW_SEQUENCE_STYLE;
123 ok = yaml_sequence_start_event_initialize(&event, (yaml_char_t *)
124 get_anchor('&', line, anchor), (yaml_char_t *)
125 get_tag(line, tag), 0, style);
126 }
127 else if (strncmp(line, "-SEQ", 4) == 0) {
128 ok = yaml_sequence_end_event_initialize(&event);
129 }
130 else if (strncmp(line, "=VAL", 4) == 0) {
131 char value[1024];
132 int style;
133
134 get_value(line, value, &style);
135 implicit = (get_tag(line, tag) == NULL);
136
137 ok = yaml_scalar_event_initialize(&event, (yaml_char_t *)
138 get_anchor('&', line, anchor), (yaml_char_t *) get_tag(line, tag), (yaml_char_t *) value, -1, implicit, implicit, style);
139 }
140 else if (strncmp(line, "=ALI", 4) == 0) {
141 ok = yaml_alias_event_initialize(&event, (yaml_char_t *)
142 get_anchor('*', line, anchor)
143 );
144 }
145 else {
146 fprintf(stderr, "Unknown event: '%s'\n", line);
147 fflush(stdout);
148 return 1;
149 }
150
151 if (!ok)
152 goto event_error;
153 if (!yaml_emitter_emit(&emitter, &event))
154 goto emitter_error;
155 }
156
157 assert(!fclose(input));
158 yaml_emitter_delete(&emitter);
159 fflush(stdout);
160
161 return 0;
162
163 emitter_error:
164 switch (emitter.error) {
165 case YAML_MEMORY_ERROR:
166 fprintf(stderr, "Memory error: Not enough memory for emitting\n");
167 break;
168 case YAML_WRITER_ERROR:
169 fprintf(stderr, "Writer error: %s\n", emitter.problem);
170 break;
171 case YAML_EMITTER_ERROR:
172 fprintf(stderr, "Emitter error: %s\n", emitter.problem);
173 break;
174 default:
175 /*
176 * Couldn't happen.
177 */
178 fprintf(stderr, "Internal error\n");
179 break;
180 }
181 yaml_emitter_delete(&emitter);
182 return 1;
183
184 event_error:
185 fprintf(stderr, "Memory error: Not enough memory for creating an event\n");
186 yaml_emitter_delete(&emitter);
187 return 1;
188 }
189
get_line(FILE * input,char * line)190 int get_line(FILE * input, char *line)
191 {
192 char *newline;
193
194 if (!fgets(line, 1024 - 1, input))
195 return 0;
196
197 if ((newline = strchr(line, '\n')) == NULL) {
198 fprintf(stderr, "Line too long: '%s'", line);
199 abort();
200 }
201 *newline = '\0';
202
203 return 1;
204 }
205
get_anchor(char sigil,char * line,char * anchor)206 char *get_anchor(char sigil, char *line, char *anchor)
207 {
208 char *start;
209 char *end;
210 if ((start = strchr(line, sigil)) == NULL)
211 return NULL;
212 start++;
213 if ((end = strchr(start, ' ')) == NULL)
214 end = line + strlen(line);
215 memcpy(anchor, start, end - start);
216 anchor[end - start] = '\0';
217 return anchor;
218 }
219
get_tag(char * line,char * tag)220 char *get_tag(char *line, char *tag)
221 {
222 char *start;
223 char *end;
224 if ((start = strchr(line, '<')) == NULL)
225 return NULL;
226 if ((end = strchr(line, '>')) == NULL)
227 return NULL;
228 memcpy(tag, start + 1, end - start - 1);
229 tag[end - start - 1] = '\0';
230 return tag;
231 }
232
get_value(char * line,char * value,int * style)233 void get_value(char *line, char *value, int *style)
234 {
235 int i = 0;
236 char *c;
237 char *start = NULL;
238 char *end = line + strlen(line);
239
240 for (c = line + 4; c < end; c++) {
241 if (*c == ' ') {
242 start = c + 1;
243 if (*start == ':')
244 *style = YAML_PLAIN_SCALAR_STYLE;
245 else if (*start == '\'')
246 *style = YAML_SINGLE_QUOTED_SCALAR_STYLE;
247 else if (*start == '"')
248 *style = YAML_DOUBLE_QUOTED_SCALAR_STYLE;
249 else if (*start == '|')
250 *style = YAML_LITERAL_SCALAR_STYLE;
251 else if (*start == '>')
252 *style = YAML_FOLDED_SCALAR_STYLE;
253 else {
254 start = NULL;
255 continue;
256 }
257 start++;
258 break;
259 }
260 }
261 if (!start)
262 abort();
263
264 for (c = start; c < end; c++) {
265 if (*c == '\\') {
266 if (*++c == '\\')
267 value[i++] = '\\';
268 else if (*c == '0')
269 value[i++] = '\0';
270 else if (*c == 'b')
271 value[i++] = '\b';
272 else if (*c == 'n')
273 value[i++] = '\n';
274 else if (*c == 'r')
275 value[i++] = '\r';
276 else if (*c == 't')
277 value[i++] = '\t';
278 else
279 abort();
280 }
281 else
282 value[i++] = *c;
283 }
284 value[i] = '\0';
285 }
286
usage(int ret)287 int usage(int ret) {
288 fprintf(stderr, "Usage: run-emitter-test-suite [--directive (1.1|1.2)] [--flow (on|off|keep)] [<input-file>]\n");
289 return ret;
290 }
291