Blame yaml-filter/yamlp.c

Packit Service 569379
#include <stdio.h>
Packit Service 569379
#include <unistd.h>
Packit Service 569379
#include <errno.h>
Packit Service 569379
#include <stdlib.h>
Packit Service 569379
#include <string.h>
Packit Service 569379
Packit Service 569379
#include <yaml.h>
Packit Service 569379
Packit Service 569379
#include "yaml-path.h"
Packit Service 569379
Packit Service 569379
Packit Service 569379
int parse_and_emit (yaml_parser_t *parser, yaml_emitter_t *emitter, yaml_path_t *path, yaml_path_filter_mode_t mode, int use_flow_style)
Packit Service 569379
{
Packit Service 569379
	yaml_event_t event;
Packit Service 569379
	yaml_event_type_t prev_event_type, event_type;
Packit Service 569379
Packit Service 569379
	do {
Packit Service 569379
Packit Service 569379
		if (!yaml_parser_parse(parser, &event)) {
Packit Service 569379
			switch (parser->error) {
Packit Service 569379
			case YAML_MEMORY_ERROR:
Packit Service 569379
				fprintf(stderr, "Memory error: Not enough memory for parsing\n");
Packit Service 569379
				break;
Packit Service 569379
			case YAML_READER_ERROR:
Packit Service 569379
				if (parser->problem_value != -1) {
Packit Service 569379
					fprintf(stderr, "Reader error: %s: #%X at %ld\n", parser->problem, parser->problem_value, (long)parser->problem_offset);
Packit Service 569379
				} else {
Packit Service 569379
					fprintf(stderr, "Reader error: %s at %ld\n", parser->problem, (long)parser->problem_offset);
Packit Service 569379
				}
Packit Service 569379
				break;
Packit Service 569379
			case YAML_SCANNER_ERROR:
Packit Service 569379
				if (parser->context) {
Packit Service 569379
					fprintf(stderr, "Scanner error: %s at line %d, column %d\n%s at line %d, column %d\n", parser->context,
Packit Service 569379
					       (int)parser->context_mark.line+1,(int)parser->context_mark.column+1, parser->problem,
Packit Service 569379
					       (int)parser->problem_mark.line+1, (int)parser->problem_mark.column+1);
Packit Service 569379
				} else {
Packit Service 569379
					fprintf(stderr, "Scanner error: %s at line %d, column %d\n", parser->problem, (int)parser->problem_mark.line+1, (int)parser->problem_mark.column+1);
Packit Service 569379
				}
Packit Service 569379
				break;
Packit Service 569379
			case YAML_PARSER_ERROR:
Packit Service 569379
				if (parser->context) {
Packit Service 569379
					fprintf(stderr, "Parser error: %s at line %d, column %d\n%s at line %d, column %d\n", parser->context,
Packit Service 569379
					       (int)parser->context_mark.line+1, (int)parser->context_mark.column+1, parser->problem,
Packit Service 569379
					       (int)parser->problem_mark.line+1, (int)parser->problem_mark.column+1);
Packit Service 569379
				} else {
Packit Service 569379
					fprintf(stderr, "Parser error: %s at line %d, column %d\n", parser->problem, (int)parser->problem_mark.line+1, (int)parser->problem_mark.column+1);
Packit Service 569379
				}
Packit Service 569379
				break;
Packit Service 569379
			default:
Packit Service 569379
				fprintf(stderr, "Internal error\n");
Packit Service 569379
				break;
Packit Service 569379
			}
Packit Service 569379
			return 1;
Packit Service 569379
		} else {
Packit Service 569379
			event_type = event.type;
Packit Service 569379
			if (!yaml_path_filter_event(path, parser, &event, mode)) {
Packit Service 569379
				yaml_event_delete(&event);
Packit Service 569379
			} else {
Packit Service 569379
				if (use_flow_style) {
Packit Service 569379
					switch (event.type) {
Packit Service 569379
					case YAML_SEQUENCE_START_EVENT:
Packit Service 569379
						event.data.sequence_start.style = YAML_FLOW_SEQUENCE_STYLE;
Packit Service 569379
						break;
Packit Service 569379
					case YAML_MAPPING_START_EVENT:
Packit Service 569379
						event.data.mapping_start.style = YAML_FLOW_MAPPING_STYLE;
Packit Service 569379
						break;
Packit Service 569379
					default:
Packit Service 569379
						break;
Packit Service 569379
					}
Packit Service 569379
				}
Packit Service 569379
				if (prev_event_type == YAML_DOCUMENT_START_EVENT && event_type == YAML_DOCUMENT_END_EVENT) {
Packit Service 569379
					yaml_event_t null_event= {0};
Packit Service 569379
					yaml_scalar_event_initialize(&null_event, NULL, (yaml_char_t *)"!!null", (yaml_char_t *)"null", 4, 1, 0, YAML_ANY_SCALAR_STYLE);
Packit Service 569379
					yaml_emitter_emit(emitter, &null_event);
Packit Service 569379
				}
Packit Service 569379
				prev_event_type = event_type;
Packit Service 569379
				if (!yaml_emitter_emit(emitter, &event)) {
Packit Service 569379
					switch (emitter->error)
Packit Service 569379
					{
Packit Service 569379
					case YAML_MEMORY_ERROR:
Packit Service 569379
						fprintf(stderr, "Memory error: Not enough memory for emitting\n");
Packit Service 569379
						break;
Packit Service 569379
					case YAML_WRITER_ERROR:
Packit Service 569379
						fprintf(stderr, "Writer error: %s\n", emitter->problem);
Packit Service 569379
						break;
Packit Service 569379
					case YAML_EMITTER_ERROR:
Packit Service 569379
						fprintf(stderr, "Emitter error: %s\n", emitter->problem);
Packit Service 569379
						break;
Packit Service 569379
					default:
Packit Service 569379
						fprintf(stderr, "Internal error\n");
Packit Service 569379
						break;
Packit Service 569379
					}
Packit Service 569379
					return 2;
Packit Service 569379
				}
Packit Service 569379
			}
Packit Service 569379
		}
Packit Service 569379
	} while (event_type != YAML_STREAM_END_EVENT);
Packit Service 569379
Packit Service 569379
	return 0;
Packit Service 569379
}
Packit Service 569379
Packit Service 569379
Packit Service 569379
void help (void)
Packit Service 569379
{
Packit Service 569379
	printf("yamlp - filtering utility for YAML documents\n");
Packit Service 569379
	printf("\n");
Packit Service 569379
	printf("Usage: yamlp [-F] [-S] [-W <width>] [-f <file>] <path>\n");
Packit Service 569379
	printf("       yamlp -h\n");
Packit Service 569379
	printf("\n");
Packit Service 569379
	printf("The tool will take the input YAML document from <stdin> or a <file> (-f option),\n");
Packit Service 569379
	printf("and it will then return the portion of the document marked with the given <path>.\n");
Packit Service 569379
	printf("\n");
Packit Service 569379
	printf("Options:\n");
Packit Service 569379
	printf("  -f	a filename to get the YAML document from,\n");
Packit Service 569379
	printf("    	<stdin> will be used if omitted;\n");
Packit Service 569379
	printf("\n");
Packit Service 569379
	printf("  -F	forced 'flow' style for the output YAML document;\n");
Packit Service 569379
	printf("\n");
Packit Service 569379
	printf("  -h	help;\n");
Packit Service 569379
	printf("\n");
Packit Service 569379
	printf("  -S	'shallow' filter mode;\n");
Packit Service 569379
	printf("\n");
Packit Service 569379
	printf("  -W	line wrap width, no wrapping if omitted.\n");
Packit Service 569379
	printf("\n");
Packit Service 569379
}
Packit Service 569379
Packit Service 569379
int main(int argc, char *argv[])
Packit Service 569379
{
Packit Service 569379
	int flow = 0;
Packit Service 569379
	char *file_name = NULL;
Packit Service 569379
	char *path_string = NULL;
Packit Service 569379
	int wrap = -1;
Packit Service 569379
	yaml_path_filter_mode_t mode = YAML_PATH_FILTER_RETURN_ALL;
Packit Service 569379
Packit Service 569379
	int opt;
Packit Service 569379
	while ((opt = getopt(argc, argv, ":f:W:vhSF")) != -1) {
Packit Service 569379
		switch (opt) {
Packit Service 569379
		case 'h':
Packit Service 569379
			help();
Packit Service 569379
			return 0;
Packit Service 569379
			break;
Packit Service 569379
		case 'F':
Packit Service 569379
			flow = 1;
Packit Service 569379
			break;
Packit Service 569379
		case 'S':
Packit Service 569379
			mode = YAML_PATH_FILTER_RETURN_SHALLOW;
Packit Service 569379
			break;
Packit Service 569379
		case 'W':
Packit Service 569379
			wrap = strtol(optarg, NULL, 10);
Packit Service 569379
			if (!wrap) {
Packit Service 569379
				fprintf(stderr, "Invalid value for wrap width '%s'\n", optarg);
Packit Service 569379
				return 1;
Packit Service 569379
			}
Packit Service 569379
			break;
Packit Service 569379
		case 'f':
Packit Service 569379
			file_name = optarg;
Packit Service 569379
			break;
Packit Service 569379
		case ':':
Packit Service 569379
			fprintf(stderr, "Option needs a value\n");
Packit Service 569379
			return 1;
Packit Service 569379
			break;
Packit Service 569379
		case '?':
Packit Service 569379
			fprintf(stderr, "Unknown option '%c'\n", optopt);
Packit Service 569379
			return 1;
Packit Service 569379
			break;
Packit Service 569379
		}
Packit Service 569379
	}
Packit Service 569379
Packit Service 569379
	for (; optind < argc; optind++) {
Packit Service 569379
		path_string = argv[optind];
Packit Service 569379
	}
Packit Service 569379
Packit Service 569379
	FILE *file = NULL;
Packit Service 569379
	if (file_name != NULL) {
Packit Service 569379
		file = fopen(file_name, "r");
Packit Service 569379
		if (file == NULL) {
Packit Service 569379
			fprintf(stderr, "Unable to open file '%s' (%s)\n", file_name, strerror(errno));
Packit Service 569379
			return 2;
Packit Service 569379
		}
Packit Service 569379
	}
Packit Service 569379
Packit Service 569379
	if (path_string == NULL || path_string[0] == 0) {
Packit Service 569379
		fprintf(stderr, "Empty path\n");
Packit Service 569379
		return 3;
Packit Service 569379
	}
Packit Service 569379
Packit Service 569379
	yaml_path_t *path = yaml_path_create();
Packit Service 569379
	if (yaml_path_parse(path, path_string)) {
Packit Service 569379
		fprintf(stderr, "Invalid path '%s' (%s)\n", path_string, yaml_path_error_get(path)->message);
Packit Service 569379
		return 3;
Packit Service 569379
	};
Packit Service 569379
Packit Service 569379
	yaml_parser_t parser;
Packit Service 569379
	yaml_emitter_t emitter;
Packit Service 569379
Packit Service 569379
	yaml_parser_initialize(&parser);
Packit Service 569379
	yaml_parser_set_input_file(&parser, file != NULL ? file : stdin);
Packit Service 569379
Packit Service 569379
	yaml_emitter_initialize(&emitter);
Packit Service 569379
	yaml_emitter_set_output_file(&emitter, stdout);
Packit Service 569379
	yaml_emitter_set_width(&emitter, wrap);
Packit Service 569379
Packit Service 569379
	if (parse_and_emit(&parser, &emitter, path, mode, flow)) {
Packit Service 569379
		return 4;
Packit Service 569379
	}
Packit Service 569379
Packit Service 569379
	yaml_parser_delete(&parser);
Packit Service 569379
	yaml_emitter_delete(&emitter);
Packit Service 569379
Packit Service 569379
	yaml_path_destroy(path);
Packit Service 569379
	fclose(file);
Packit Service 569379
Packit Service 569379
	return 0;
Packit Service 569379
}