#include "template.h" static int __template_max = 0; void __template_error(char *fmt, ...) { va_list ap; char buf[1024] = { 0 }; va_start(ap, fmt); vsprintf(buf, fmt, ap); fprintf(stderr, "Error: %s\n", buf); va_end(ap); exit(EXIT_FAILURE); } int _generate_hash(char *string) { int count = 0; char *p = string; while (*p) { count += *p + 31; p++; } return count % TEMPLATE_SIZE; } void template_input(__template_t **data, char *name, char *value) { int index = _generate_hash(name); __template_t *cursor = data[index]; if (index > __template_max) __template_max = index; if (cursor == NULL) { data[index] = cursor = calloc(1, sizeof(__template_t)); cursor->name = strdup(name); cursor->string = strdup(value); cursor->next = NULL; cursor->child = NULL; return; } for (cursor = data[index]; strcmp(cursor->name, name) || cursor->child ; cursor = cursor->child); __template_t *c = NULL; if (0 == strcmp(cursor->name, name)) { if (cursor->child == NULL) { c = cursor->child = calloc(1, sizeof(__template_t)); c->name = strdup(name); c->string = strdup(value); return; } for (c = cursor; c->child; c = cursor->child); if (c->child == NULL) { c->child = calloc(1, sizeof(__template_t)); c = c->child; c->name = strdup(name); c->string = strdup(value); return; } } if (cursor->next == NULL) { data[index] = cursor = calloc(1, sizeof(__template_t)); cursor->name = strdup(name); cursor->string = strdup(value); cursor->next = NULL; cursor->child = NULL; } else __template_error("Unknown error: template_input"); return; } void __parse_data( char *template, ssize_t bytes, __template_t **data) { __template_t *cursor = NULL; char exp[8192]; char forexp[8192]; char *pos = NULL; char *p = NULL; int count = strlen(template); char *result = calloc(1, count * 8); int idx = 0; strcpy(result, template); /* Modify template and then output it like below */ for (idx = 0; idx <= __template_max; idx++) { for (cursor = data[idx]; cursor; cursor = cursor->next) { sprintf(exp, TEMPLATE_MARK, cursor->name); sprintf(forexp, TEMPLATE_FOR, cursor->name); p = strdup(result); int i = 0; int j = 0; while (*p != '\0') { pos = strstr(p, exp); if (pos) { while(p != pos) { result[i++] = *(p++); } count += strlen(cursor->string) + 1; result = realloc(result, count); for (j = 0; j < strlen(cursor->string); j++) result[i++] = cursor->string[j]; p += strlen(exp); } else if ((pos = strstr(p, forexp))) { __template_t *c = NULL; while(p != pos) result[i++] = *(p++); p += strlen(forexp); c = cursor; if ((pos = strstr(p, TEMPLATE_FORMARK))) { char *again = p; while (c) { while (p != pos) { result[i++] = *(p++); } char *end = strchr(p, '\n'); p += strlen(TEMPLATE_FORMARK); count += strlen(c->string) + 1; result = realloc(result, count); for (j = 0; j < strlen(c->string); j++) { result[i++] = c->string[j]; } count += 1 + end - p; result = realloc(result, count); while (p != end) result[i++] = *(p++); c = c->child; p = again; } } pos = strstr(p, TEMPLATE_FOREND); while (p != pos) p++; p += strlen(TEMPLATE_FOREND); } else result[i++] = *(p++); } result[i] = '\0'; } } printf("%s\n", result); } int template_output(char *filename, __template_t **data) { ssize_t file_len = 0; struct stat fstats; FILE *fp = NULL; char *buf = NULL; fp = fopen(filename, "r"); if (fp == NULL) __template_error("Could not open %s because %s", filename, strerror(errno)); if (stat(filename, &fstats) < 0) __template_error("Could not stat %s", filename); file_len = fstats.st_size; buf = malloc(file_len * sizeof(char) + 1); if (buf == NULL) __template_error("malloc()"); fread(buf, file_len, sizeof(char), fp); buf[file_len] = '\0'; /* Process and parse the data and template */ __parse_data(buf, file_len, data); fclose(fp); return 0; } void *template_init(void) { int i; void **p = malloc(TEMPLATE_SIZE * sizeof(__template_t)); if (p == NULL) __template_error("malloc()"); for(i = 0; i < TEMPLATE_SIZE; i++) p[i] = NULL; return p; } void template_free(__template_t **data) { __template_t *next; __template_t *cursor = data[0]; int idx = 0; for (cursor = data[idx]; idx < TEMPLATE_SIZE; idx++) { while (cursor) { next = cursor->next; if (cursor->name) free(cursor->name); if (cursor->string) free(cursor->string); __template_t *c = cursor->child; __template_t *c_next = NULL; while (c) { c_next = c->child; free(c->name); free(c->string); free(c); c = c_next; } free(cursor); cursor = next; } } }