xref: /freebsd/contrib/libyaml/tests/run-emitter-test-suite.c (revision 0f5c86ddb0257f4b7620f1d8e898289be30b19bf)
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