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