]>
Commit | Line | Data |
---|---|---|
a672b071 IN |
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 | ||
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 | ||
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 | ||
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 | ||
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 | ||
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 | } |