diff options
| -rw-r--r-- | ctimeline.c | 205 | 
1 files changed, 205 insertions, 0 deletions
diff --git a/ctimeline.c b/ctimeline.c new file mode 100644 index 0000000..ce0331d --- /dev/null +++ b/ctimeline.c @@ -0,0 +1,205 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#include "xstring.h" + +#define COMMENT_CHAR '#' + +struct branch { +	string *name; +	string *position; +	string *age; +	string *desc; +}; + +struct branch_ll { +	struct branch *branch; +	struct branch_ll *prev; +}; + +struct branch_ll *first_branch; +struct branch *current_branch; + +void emit_timeline_html() +{ +	printf("\t<ul class=\"timeline\">\n"); + +	struct branch_ll *ptr; +	for(ptr = first_branch; ptr; ptr = ptr->prev) { +		printf( +		"\t<li>\n" +			"\t\t<div class=\"direction-%s\">\n" +				"\t\t\t<div class=\"flag-wrapper\">\n" +					"\t\t\t\t<span class=\"flag\">%s</span>\n" +					"\t\t\t\t<span class=\"time-wrapper\"><span class=\"time\">%s</span></span>\n" +				"\t\t\t</div>\n" +				"\t\t\t<div class=\"desc\">%s</div>\n" +			"\t\t</div>\n" +		"\t</li>\n", ptr->branch->position->s, ptr->branch->name->s, +			ptr->branch->age->s, ptr->branch->desc->s); +	} + +	printf("\t</ul>\n"); +} + +struct branch *add_branch(const char *name) +{ +	struct branch *br; + +	if(!first_branch) { +		first_branch = malloc(sizeof(struct branch_ll)); +		first_branch->branch = malloc(sizeof(struct branch)); +		first_branch->prev = NULL; + +		br = first_branch->branch; +	} +	else { +		struct branch_ll *ptr; +		for(ptr = first_branch; ptr; ptr = ptr->prev) { +			if(!ptr->prev) { +				ptr->prev = malloc(sizeof(struct branch_ll)); +				ptr->prev->branch = malloc(sizeof(struct branch)); +				ptr->prev->prev = NULL; + +				br = ptr->prev->branch; +				break; +			} +		} +	} + +	br->name = string_alloc(name); +	br->position = string_alloc("right"); +	br->age = string_alloc("No age"); +	br->desc = string_alloc("No description"); + +	return br; +} + +void handle_config_context(const char *name, const char *value) +{ +	if(strcmp(name, "branch.name") == 0) { +		current_branch = add_branch(value); +	} +	else if(strcmp(name, "branch.position") == 0) { +		if(!current_branch) +			return; + +		if(strcmp(value, "right") != 0 && strcmp(value, "left") != 0) +			return; + +		string_release(current_branch->position); +		current_branch->position = string_alloc(value); +	} +	else if(strcmp(name, "branch.age") == 0) { +		if(!current_branch) +			return; + +		string_release(current_branch->age); +		current_branch->age = string_alloc(value); +	} +	else if(strcmp(name, "branch.desc") == 0) { +		if(!current_branch) +			return; + +		string_release(current_branch->desc); +		current_branch->desc = string_alloc(value); +	} +} + +void skip_line(FILE *f) +{ +	int c; +	while( (c = fgetc(f)) && c != '\n' && c != EOF ) +		; +} + +int read_config_line(FILE *f, string *name, string *value) +{ +	int c; + +	// skip comments and white spaces +	for(;;) { +		c = fgetc(f); +		if(c == EOF) +			return 1; +		else if(c == COMMENT_CHAR) +			skip_line(f); +		else if(!isspace(c)) +			break; +	} + +	// read variable name +	while(c != '=') { +		if(isspace(c) || c == EOF) +			return 1; +		string_addch(name, c); +		c = fgetc(f); +	} + +	// read variable value +	c = fgetc(f); +	while(c != '\n' && c != EOF) { +		string_addch(value, c); +		c = fgetc(f); +	} + +	return 0; +} + +int parse_config_file(const char *filename) +{ +	string *name = string_alloc(NULL); +	string *value = string_alloc(NULL); +	FILE *f; +	 +	f = fopen(filename, "r"); +	if(!f) +		return 1; +		 +	while(read_config_line(f, name, value) == 0) { +		// printf("name: %s; value: %s\n", name->s, value->s); +		handle_config_context(name->s, value->s); +		string_reset(name); +		string_reset(value); +	} +		 +	fclose(f); +	string_release(name); +	string_release(value); +	return 0; +} + +void usage() +{ +	printf("Usage: ctimeline [-h, --help] config_path\n" +		"Copyright (C) 2021 Aleksandr D. Goncharov (Joursoir)\n" +		"License: GNU GPL version 3 + X11 License\n" +		"This is free software: you are free to change and redistribute it.\n" +		"This program comes with ABSOLUTELY NO WARRANTY.\n"); +} + +int main(int argc, char **argv) +{ +	int result; +	const char *config; +	if(argc < 2) { +		usage(); +		return 1; +	} +	if(strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0) { +		usage(); +		return 0; +	} +	config = argv[1]; + +	result = parse_config_file(config); +	if(result) { +		perror(config); +		return 1; +	} + +	emit_timeline_html(); +	return 0;	 +}  | 
