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