aboutsummaryrefslogtreecommitdiffstats
path: root/ctimeline.c
diff options
context:
space:
mode:
Diffstat (limited to 'ctimeline.c')
-rw-r--r--ctimeline.c205
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;
+}