aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/blogc-git-receiver.c502
-rw-r--r--src/blogc-runserver.c389
-rw-r--r--src/blogc.c (renamed from src/main.c)52
-rw-r--r--src/content-parser.c349
-rw-r--r--src/content-parser.h3
-rw-r--r--src/datetime-parser.c4
-rw-r--r--src/directives.c8
-rw-r--r--src/directives.h4
-rw-r--r--src/error.c12
-rw-r--r--src/file.c8
-rw-r--r--src/loader.c84
-rw-r--r--src/loader.h8
-rw-r--r--src/renderer.c68
-rw-r--r--src/renderer.h16
-rw-r--r--src/source-parser.c40
-rw-r--r--src/source-parser.h4
-rw-r--r--src/template-parser.c42
-rw-r--r--src/template-parser.h6
-rw-r--r--src/utils.c612
-rw-r--r--src/utils.h102
-rw-r--r--src/utils/mem.c42
-rw-r--r--src/utils/slist.c68
-rw-r--r--src/utils/strings.c314
-rw-r--r--src/utils/trie.c199
-rw-r--r--src/utils/utils.h79
25 files changed, 1981 insertions, 1034 deletions
diff --git a/src/blogc-git-receiver.c b/src/blogc-git-receiver.c
new file mode 100644
index 0000000..ffeac61
--- /dev/null
+++ b/src/blogc-git-receiver.c
@@ -0,0 +1,502 @@
+/*
+ * blogc: A blog compiler.
+ * Copyright (C) 2015-2016 Rafael G. Martins <rafael@rafaelmartins.eng.br>
+ *
+ * This program can be distributed under the terms of the BSD License.
+ * See the file LICENSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <libgen.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <time.h>
+
+#include "utils.h"
+
+#ifndef BUFFER_SIZE
+#define BUFFER_SIZE 4096
+#endif
+
+
+static unsigned int
+cpu_count(void)
+{
+#ifdef _SC_NPROCESSORS_ONLN
+ long num = sysconf(_SC_NPROCESSORS_ONLN);
+ if (num >= 1)
+ return (unsigned int) num;
+#endif
+ return 1;
+}
+
+
+static void
+rmdir_recursive(const char *dir)
+{
+ struct stat buf;
+ if (0 != stat(dir, &buf)) {
+ fprintf(stderr, "warning: failed to remove directory (%s): %s\n", dir,
+ strerror(errno));
+ return;
+ }
+ if (!S_ISDIR(buf.st_mode)) {
+ fprintf(stderr, "error: trying to remove invalid directory: %s\n", dir);
+ exit(2);
+ }
+ DIR *d = opendir(dir);
+ if (d == NULL) {
+ fprintf(stderr, "error: failed to open directory: %s\n",
+ strerror(errno));
+ exit(2);
+ }
+ struct dirent *e;
+ while (NULL != (e = readdir(d))) {
+ if ((0 == strcmp(e->d_name, ".")) || (0 == strcmp(e->d_name, "..")))
+ continue;
+ char *f = sb_strdup_printf("%s/%s", dir, e->d_name);
+ if (0 != stat(f, &buf)) {
+ fprintf(stderr, "error: failed to stat directory entry (%s): %s\n",
+ e->d_name, strerror(errno));
+ free(f);
+ exit(2);
+ }
+ if (S_ISDIR(buf.st_mode)) {
+ rmdir_recursive(f);
+ }
+ else if (0 != unlink(f)) {
+ fprintf(stderr, "error: failed to remove file (%s): %s\n", f,
+ strerror(errno));
+ free(f);
+ exit(2);
+ }
+ free(f);
+ }
+ if (0 != closedir(d)) {
+ fprintf(stderr, "error: failed to close directory: %s\n",
+ strerror(errno));
+ exit(2);
+ }
+ if (0 != rmdir(dir)) {
+ fprintf(stderr, "error: failed to remove directory: %s\n",
+ strerror(errno));
+ exit(2);
+ }
+}
+
+
+static int
+git_shell(int argc, char *argv[])
+{
+ int rv = 0;
+
+ char *repo = NULL;
+ char *command_orig = NULL;
+ char *command_name = NULL;
+ char command_new[BUFFER_SIZE];
+
+ bool exec_git = false;
+
+ // validate git command
+ size_t len = strlen(argv[2]);
+ if (!((len > 17 && (0 == strncmp(argv[2], "git-receive-pack ", 17))) ||
+ (len > 16 && (0 == strncmp(argv[2], "git-upload-pack ", 16))) ||
+ (len > 19 && (0 == strncmp(argv[2], "git-upload-archive ", 19)))))
+ {
+ fprintf(stderr, "error: unsupported git command: %s\n", argv[2]);
+ rv = 1;
+ goto cleanup;
+ }
+
+ // get shell path
+ char *self = getenv("SHELL");
+ if (self == NULL) {
+ fprintf(stderr, "error: failed to find blogc-git-receiver path\n");
+ rv = 1;
+ goto cleanup;
+ }
+
+ // get home path
+ char *home = getenv("HOME");
+ if (home == NULL) {
+ fprintf(stderr, "error: failed to find user home path\n");
+ rv = 1;
+ goto cleanup;
+ }
+
+ // get git repository
+ command_orig = sb_strdup(argv[2]);
+ char *p, *r;
+ for (p = command_orig; *p != ' ' && *p != '\0'; p++);
+ if (*p == ' ')
+ p++;
+ if (*p == '\'' || *p == '"')
+ p++;
+ if (*p == '/')
+ p++;
+ for (r = p; *p != '\'' && *p != '"' && *p != '\0'; p++);
+ if (*p == '\'' || *p == '"')
+ *p = '\0';
+ if (*--p == '/')
+ *p = '\0';
+
+ repo = sb_strdup_printf("repos/%s", r);
+
+ // check if repository is sane
+ if (0 == strlen(repo)) {
+ fprintf(stderr, "error: invalid repository\n");
+ rv = 1;
+ goto cleanup;
+ }
+
+ if (0 == strncmp(argv[2], "git-upload-", 11)) // no need to check len here
+ goto git_exec;
+
+ if (0 != chdir(home)) {
+ fprintf(stderr, "error: failed to chdir (%s): %s\n", home,
+ strerror(errno));
+ rv = 1;
+ goto cleanup;
+ }
+
+ if (0 != access(repo, F_OK)) {
+ char *git_init_cmd = sb_strdup_printf(
+ "git init --bare \"%s\" > /dev/null", repo);
+ if (0 != system(git_init_cmd)) {
+ fprintf(stderr, "error: failed to create git repository: %s\n",
+ repo);
+ rv = 1;
+ free(git_init_cmd);
+ goto cleanup;
+ }
+ free(git_init_cmd);
+ }
+
+ if (0 != chdir(repo)) {
+ fprintf(stderr, "error: failed to chdir (%s/%s): %s\n", home, repo,
+ strerror(errno));
+ rv = 1;
+ goto cleanup;
+ }
+
+ if (0 != access("hooks", F_OK)) {
+ // openwrt git package won't install git templates, then the git
+ // repositories created with it won't have the hooks/ directory.
+ if (0 != mkdir("hooks", 0777)) { // mkdir honors umask for us.
+ fprintf(stderr, "error: failed to create directory (%s/%s/hooks): "
+ "%s\n", home, repo, strerror(errno));
+ rv = 1;
+ goto cleanup;
+ }
+ }
+
+ if (0 != chdir("hooks")) {
+ fprintf(stderr, "error: failed to chdir (%s/%s/hooks): %s\n", home,
+ repo, strerror(errno));
+ rv = 1;
+ goto cleanup;
+ }
+
+ if (0 == access("pre-receive", F_OK)) {
+ if (0 != unlink("pre-receive")) {
+ fprintf(stderr, "error: failed to remove old symlink "
+ "(%s/%s/hooks/pre-receive): %s\n", home, repo, strerror(errno));
+ rv = 1;
+ goto cleanup;
+ }
+ }
+
+ if (0 != symlink(self, "pre-receive")) {
+ fprintf(stderr, "error: failed to create symlink "
+ "(%s/%s/hooks/pre-receive): %s\n", home, repo, strerror(errno));
+ rv = 1;
+ goto cleanup;
+ }
+
+ if (0 == access("post-receive", F_OK)) {
+ if (0 != unlink("post-receive")) {
+ fprintf(stderr, "error: failed to remove old symlink "
+ "(%s/%s/hooks/post-receive): %s\n", home, repo, strerror(errno));
+ rv = 1;
+ goto cleanup;
+ }
+ }
+
+ if (0 != symlink(self, "post-receive")) {
+ fprintf(stderr, "error: failed to create symlink "
+ "(%s/%s/hooks/post-receive): %s\n", home, repo, strerror(errno));
+ rv = 1;
+ goto cleanup;
+ }
+
+ if (0 != chdir(home)) {
+ fprintf(stderr, "error: failed to chdir (%s): %s\n", home,
+ strerror(errno));
+ rv = 1;
+ goto cleanup;
+ }
+
+git_exec:
+ command_name = sb_strdup(argv[2]);
+ for (p = command_name; *p != ' ' && *p != '\0'; p++);
+ if (*p == ' ')
+ *p = '\0';
+
+ if (BUFFER_SIZE < (strlen(command_name) + strlen(repo) + 4)) {
+ fprintf(stderr, "error: git-shell command is too big\n");
+ rv = 1;
+ goto cleanup;
+ }
+
+ if (snprintf(command_new, BUFFER_SIZE, "%s '%s'", command_name, repo))
+ exec_git = true;
+
+cleanup:
+ free(repo);
+ free(command_orig);
+ free(command_name);
+
+ if (exec_git) {
+ execlp("git-shell", "git-shell", "-c", command_new, NULL);
+
+ // execlp only returns on error, then something bad happened
+ fprintf(stderr, "error: failed to execute git-shell\n");
+ rv = 1;
+ }
+
+ return rv;
+}
+
+
+static int
+git_post_receive_hook(int argc, char *argv[])
+{
+ if (0 != system("git remote get-url --push mirror &> /dev/null"))
+ return 0;
+
+ // at this point we know that we have a remote called mirror, we can just
+ // push to it.
+ if (0 != system("git push --mirror mirror"))
+ fprintf(stderr, "warning: failed push to git mirror\n");
+
+ return 0;
+}
+
+
+typedef enum {
+ START_OLD = 1,
+ OLD,
+ START_NEW,
+ NEW,
+ START_REF,
+ REF
+} input_state_t;
+
+
+static int
+git_pre_receive_hook(int argc, char *argv[])
+{
+ int c;
+ char buffer[BUFFER_SIZE];
+
+ input_state_t state = START_OLD;
+ size_t i = 0;
+ size_t start = 0;
+
+ int rv = 0;
+ char *new = NULL;
+ char *master = NULL;
+
+ while (EOF != (c = getc(stdin))) {
+
+ buffer[i] = (char) c;
+
+ switch (state) {
+ case START_OLD:
+ start = i;
+ state = OLD;
+ break;
+ case OLD:
+ if (c != ' ')
+ break;
+ // no need to store old
+ state = START_NEW;
+ break;
+ case START_NEW:
+ start = i;
+ state = NEW;
+ break;
+ case NEW:
+ if (c != ' ')
+ break;
+ state = START_REF;
+ new = strndup(buffer + start, i - start);
+ break;
+ case START_REF:
+ start = i;
+ state = REF;
+ break;
+ case REF:
+ if (c != '\n')
+ break;
+ state = START_OLD;
+ // we just care about a ref (refs/heads/master), everything
+ // else is disposable :)
+ if (!((i - start == 17) &&
+ (0 == strncmp("refs/heads/master", buffer + start, 17))))
+ {
+ free(new);
+ new = NULL;
+ break;
+ }
+ master = new;
+ break;
+ }
+
+ if (++i >= BUFFER_SIZE) {
+ fprintf(stderr, "error: pre-receive hook payload is too big.\n");
+ rv = 1;
+ goto cleanup2;
+ }
+ }
+
+ if (master == NULL) {
+ fprintf(stderr, "warning: no reference to master branch found. "
+ "nothing to deploy.\n");
+ goto cleanup2;
+ }
+
+ char *repo_dir = NULL;
+ char *output_dir = NULL;
+
+ if (NULL == getcwd(buffer, BUFFER_SIZE)) {
+ fprintf(stderr, "error: failed to get repository remote path: %s\n",
+ strerror(errno));
+ rv = 1;
+ goto cleanup;
+ }
+
+ repo_dir = sb_strdup(buffer);
+
+ char dir[] = "/tmp/blogc_XXXXXX";
+ if (NULL == mkdtemp(dir)) {
+ rv = 1;
+ goto cleanup;
+ }
+
+ char *git_archive_cmd = sb_strdup_printf(
+ "git archive \"%s\" | tar -x -C \"%s\" -f -", master, dir);
+ if (0 != system(git_archive_cmd)) {
+ fprintf(stderr, "error: failed to extract git content to temporary "
+ "directory: %s\n", dir);
+ rv = 1;
+ free(git_archive_cmd);
+ goto cleanup;
+ }
+ free(git_archive_cmd);
+
+ if (0 != chdir(dir)) {
+ fprintf(stderr, "error: failed to chdir (%s): %s\n", dir,
+ strerror(errno));
+ rv = 1;
+ goto cleanup;
+ }
+
+ if ((0 != access("Makefile", F_OK)) && (0 != access("GNUMakefile", F_OK))) {
+ fprintf(stderr, "warning: no makefile found. skipping ...\n");
+ goto cleanup;
+ }
+
+ char *home = getenv("HOME");
+ if (home == NULL) {
+ fprintf(stderr, "error: failed to find user home path\n");
+ rv = 1;
+ goto cleanup;
+ }
+
+ unsigned long epoch = time(NULL);
+ output_dir = sb_strdup_printf("%s/builds/%s-%lu", home, master, epoch);
+ char *gmake_cmd = sb_strdup_printf(
+ "gmake -j%d OUTPUT_DIR=\"%s\" BLOGC_GIT_RECEIVER=1",
+ cpu_count(), output_dir);
+ fprintf(stdout, "running command: %s\n\n", gmake_cmd);
+ fflush(stdout);
+ if (0 != system(gmake_cmd)) {
+ fprintf(stderr, "error: failed to build website ...\n");
+ rmdir_recursive(output_dir);
+ free(gmake_cmd);
+ rv = 1;
+ goto cleanup;
+ }
+ free(gmake_cmd);
+
+ if (0 != chdir(repo_dir)) {
+ fprintf(stderr, "error: failed to chdir (%s): %s\n", repo_dir,
+ strerror(errno));
+ rmdir_recursive(output_dir);
+ rv = 1;
+ goto cleanup;
+ }
+
+ char *htdocs_sym = NULL;
+ ssize_t htdocs_sym_len = readlink("htdocs", buffer, BUFFER_SIZE);
+ if (0 < htdocs_sym_len) {
+ if (0 != unlink("htdocs")) {
+ fprintf(stderr, "error: failed to remove symlink (%s/htdocs): %s\n",
+ repo_dir, strerror(errno));
+ rmdir_recursive(output_dir);
+ rv = 1;
+ goto cleanup;
+ }
+ buffer[htdocs_sym_len] = '\0';
+ htdocs_sym = buffer;
+ }
+
+ if (0 != symlink(output_dir, "htdocs")) {
+ fprintf(stderr, "error: failed to create symlink (%s/htdocs): %s\n",
+ repo_dir, strerror(errno));
+ rmdir_recursive(output_dir);
+ rv = 1;
+ goto cleanup;
+ }
+
+ if (htdocs_sym != NULL)
+ rmdir_recursive(htdocs_sym);
+
+cleanup:
+ free(output_dir);
+ rmdir_recursive(dir);
+ free(repo_dir);
+cleanup2:
+ free(new);
+ return rv;
+}
+
+
+int
+main(int argc, char *argv[])
+{
+ if (argc > 0) {
+ if (0 == strcmp(basename(argv[0]), "pre-receive"))
+ return git_pre_receive_hook(argc, argv);
+ if (0 == strcmp(basename(argv[0]), "post-receive"))
+ return git_post_receive_hook(argc, argv);
+ }
+
+ if (argc == 3 && (0 == strcmp(argv[1], "-c")))
+ return git_shell(argc, argv);
+
+ fprintf(stderr, "error: this is a special shell, go away!\n");
+ return 1;
+}
diff --git a/src/blogc-runserver.c b/src/blogc-runserver.c
new file mode 100644
index 0000000..81bd5f9
--- /dev/null
+++ b/src/blogc-runserver.c
@@ -0,0 +1,389 @@
+/*
+ * blogc: A blog compiler.
+ * Copyright (C) 2015-2016 Rafael G. Martins <rafael@rafaelmartins.eng.br>
+ *
+ * This program can be distributed under the terms of the BSD License.
+ * See the file LICENSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <event2/event.h>
+#include <event2/http.h>
+#include <event2/buffer.h>
+#include <event2/keyvalq_struct.h>
+#include <magic.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "utils.h"
+
+
+/**
+ * this mapping is used to declare "supported" file types, that are forced over
+ * whatever detected by libmagic, but we will still use the charset provided by
+ * libmagic anyway. it also helps detecting index files when the client asks
+ * for a directory.
+ */
+static const struct content_type_map {
+ const char *mimetype;
+ const char *extension;
+ const char *index;
+} content_types[] = {
+ {"text/html", "html", "index.html"},
+ {"text/html", "htm", "index.htm"},
+ {"text/xml", "xml", "index.xml"},
+ {"text/plain", "txt", "index.txt"},
+ {"text/css", "css", NULL},
+ {"application/javascript", "js", NULL},
+ {NULL, NULL, NULL}
+};
+
+
+static magic_t magic_all = NULL;
+static magic_t magic_charset = NULL;
+
+
+static const char*
+get_extension(const char *filename)
+{
+ const char *ext = NULL;
+ unsigned int i;
+ for (i = strlen(filename); i > 0; i--) {
+ if (filename[i] == '.') {
+ ext = filename + i + 1;
+ break;
+ }
+ }
+ if (i == 0)
+ return NULL;
+ return ext;
+}
+
+
+static char*
+guess_content_type(const char *filename, int fd)
+{
+ int newfd;
+
+ // try "supported" types first, and just use libmagic for charset
+ const char *extension = get_extension(filename);
+ if (extension == NULL)
+ goto libmagic;
+ const char *supported = NULL;
+ for (unsigned int i = 0; content_types[i].extension != NULL; i++)
+ if (0 == strcmp(content_types[i].extension, extension))
+ supported = content_types[i].mimetype;
+ if (supported != NULL) {
+ newfd = dup(fd);
+ if (-1 != newfd) {
+ const char* charset = magic_descriptor(magic_charset, newfd);
+ close(newfd);
+ if (charset != NULL)
+ return sb_strdup_printf("%s; charset=%s", supported, charset);
+ }
+ return sb_strdup(supported);
+ }
+
+libmagic:
+
+ // fallback to use libmagic for everything
+ newfd = dup(fd);
+ if (-1 != newfd) {
+ const char* content_type = magic_descriptor(magic_all, newfd);
+ close(newfd);
+ if (content_type != NULL)
+ return sb_strdup(content_type);
+ }
+ return sb_strdup("application/octet-stream");
+}
+
+
+static void
+handler(struct evhttp_request *request, void *ptr)
+{
+ const char *root = ptr;
+ const char *uri = evhttp_request_get_uri(request);
+
+ struct evhttp_uri *decoded_uri = evhttp_uri_parse(uri);
+ if (decoded_uri == NULL) {
+ evhttp_send_error(request, 400, "Bad request");
+ return;
+ }
+
+ const char *path = evhttp_uri_get_path(decoded_uri);
+ if (path == NULL)
+ path = "/";
+
+ char *decoded_path = evhttp_uridecode(path, 0, NULL);
+ if (decoded_path == NULL) {
+ evhttp_send_error(request, 400, "Bad request");
+ goto point1;
+ }
+
+ char *abs_path = sb_strdup_printf("%s/%s", root, decoded_path);
+ char *real_path = realpath(abs_path, NULL);
+ free(abs_path);
+
+ if (real_path == NULL) {
+ evhttp_send_error(request, 404, "Not found");
+ goto point2;
+ }
+
+ char *real_root = realpath(root, NULL);
+ if (real_root == NULL) {
+ evhttp_send_error(request, 500, "Internal server error");
+ goto point3;
+ }
+
+ if (0 != strncmp(real_root, real_path, strlen(real_root))) {
+ evhttp_send_error(request, 404, "Not found");
+ goto point4;
+ }
+
+ struct stat st;
+ if (0 > stat(real_path, &st)) {
+ evhttp_send_error(request, 404, "Not found");
+ goto point4;
+ }
+
+ bool add_slash = false;
+
+ if (S_ISDIR(st.st_mode)) {
+ char *found = NULL;
+
+ for (unsigned int i = 0; content_types[i].mimetype != NULL; i++) {
+ if (content_types[i].index == NULL)
+ continue;
+ char *f = sb_strdup_printf("%s/%s", real_path,
+ content_types[i].index);
+ if (0 == access(f, F_OK)) {
+ found = sb_strdup(f);
+ break;
+ }
+ free(f);
+ }
+
+ if (found == NULL) {
+ evhttp_send_error(request, 403, "Forbidden");
+ goto point4;
+ }
+
+ size_t path_len = strlen(path);
+ if (path_len > 0 && path[path_len - 1] != '/')
+ add_slash = true;
+
+ free(real_path);
+ real_path = found;
+ }
+
+ int fd;
+ if ((fd = open(real_path, O_RDONLY)) < 0) {
+ evhttp_send_error(request, 500, "Internal server error");
+ goto point4;
+ }
+
+ char *type = guess_content_type(real_path, fd);
+
+ if (fstat(fd, &st) < 0) {
+ evhttp_send_error(request, 500, "Internal server error");
+ goto point5;
+ }
+
+ struct evkeyvalq *headers = evhttp_request_get_output_headers(request);
+
+ if (add_slash) {
+ char *tmp = sb_strdup_printf("%s/", path);
+ evhttp_add_header(headers, "Location", tmp);
+ free(tmp);
+ // production webservers usually returns 301 in such cases, but 302 is
+ // better for development/testing.
+ evhttp_send_reply(request, 302, "Found", NULL);
+ goto point5;
+ }
+
+ evhttp_add_header(headers, "Content-Type", type);
+ char *content_length = sb_strdup_printf("%zu", st.st_size);
+ evhttp_add_header(headers, "Content-Length", content_length);
+ free(content_length);
+
+ struct evbuffer *evb = evbuffer_new();
+ evbuffer_add_file(evb, fd, 0, st.st_size);
+ evhttp_send_reply(request, 200, "OK", evb);
+
+point5:
+ free(type);
+point4:
+ free(real_root);
+point3:
+ free(real_path);
+point2:
+ free(decoded_path);
+point1:
+ evhttp_uri_free(decoded_uri);
+}
+
+
+static int
+runserver(const char *address, unsigned short port, const char *root)
+{
+ struct event_base *base = event_base_new();
+ if (base == NULL) {
+ fprintf(stderr, "error: failed to initialize event base\n");
+ return 1;
+ }
+
+ struct evhttp *http = evhttp_new(base);
+ if (http == NULL) {
+ fprintf(stderr, "error: failed to initialize HTTP server\n");
+ return 1;
+ }
+
+ evhttp_set_gencb(http, handler, (char*) root);
+
+ evhttp_set_allowed_methods(http, EVHTTP_REQ_GET | EVHTTP_REQ_HEAD);
+
+ if (0 != evhttp_bind_socket(http, address, port)) {
+ fprintf(stderr, "error: failed to bind socket to %s:%d\n", address,
+ port);
+ return 1;
+ }
+
+ fprintf(stderr, " * Running on http://%s:%d/\n", address, port);
+
+ event_base_dispatch(base);
+
+ return 0;
+}
+
+
+static void
+print_help(void)
+{
+ printf(
+ "usage:\n"
+ " blogc-runserver [-h] [-v] [-t HOST] [-p PORT] DOCROOT\n"
+ " - A simple HTTP server to test blogc websites.\n"
+ "\n"
+ "positional arguments:\n"
+ " DOCROOT document root directory\n"
+ "\n"
+ "optional arguments:\n"
+ " -h show this help message and exit\n"
+ " -v show version and exit\n"
+ " -t HOST set server listen address (default: 127.0.0.1)\n"
+ " -p PORT set server listen port (default: 8080)\n");
+}
+
+
+static void
+print_usage(void)
+{
+ printf("usage: blogc-runserver [-h] [-v] [-t HOST] [-p PORT] DOCROOT\n");
+}
+
+
+int
+main(int argc, char **argv)
+{
+ signal(SIGPIPE, SIG_IGN);
+
+ int rv = 0;
+ char *host = NULL;
+ char *docroot = NULL;
+ unsigned short port = 8080;
+
+ unsigned int args = 0;
+
+ for (unsigned int i = 1; i < argc; i++) {
+ if (argv[i][0] == '-') {
+ switch (argv[i][1]) {
+ case 'h':
+ print_help();
+ goto cleanup;
+ case 'v':
+ printf("%s\n", PACKAGE_STRING);
+ goto cleanup;
+ case 't':
+ if (argv[i][2] != '\0')
+ host = sb_strdup(argv[i] + 2);
+ else
+ host = sb_strdup(argv[++i]);
+ break;
+ case 'p':
+ if (argv[i][2] != '\0')
+ port = strtoul(argv[i] + 2, NULL, 10);
+ else
+ port = strtoul(argv[++i], NULL, 10);
+ break;
+ default:
+ print_usage();
+ fprintf(stderr, "blogc-runserver: error: invalid "
+ "argument: -%c\n", argv[i][1]);
+ rv = 2;
+ goto cleanup;
+ }
+ }
+ else {
+ if (args > 0) {
+ print_usage();
+ fprintf(stderr, "blogc-runserver: error: only one positional "
+ "argument allowed\n");
+ rv = 2;
+ goto cleanup;
+ }
+ args++;
+ docroot = sb_strdup(argv[i]);
+ }
+ }
+
+ if (docroot == NULL) {
+ print_usage();
+ fprintf(stderr, "blogc-runserver: error: document root directory "
+ "required\n");
+ rv = 2;
+ goto cleanup;
+ }
+
+ if (host == NULL)
+ host = sb_strdup("127.0.0.1");
+
+ magic_all = magic_open(MAGIC_MIME);
+ magic_charset = magic_open(MAGIC_MIME_ENCODING);
+ if (magic_all == NULL || magic_charset == NULL) {
+ fprintf(stderr, "error: failed to initialize libmagic\n");
+ rv = 1;
+ goto cleanup;
+ }
+
+ if ((0 != magic_load(magic_all, NULL)) ||
+ (0 != magic_load(magic_charset, NULL)))
+ {
+ fprintf(stderr, "error: failed to load libmagic data\n");
+ magic_close(magic_all);
+ magic_close(magic_charset);
+ rv = 1;
+ goto cleanup;
+ }
+
+ rv = runserver(host, port, docroot);
+
+ magic_close(magic_all);
+ magic_close(magic_charset);
+
+cleanup:
+ free(host);
+ free(docroot);
+
+ return rv;
+}
diff --git a/src/main.c b/src/blogc.c
index f3f990b..2338c9e 100644
--- a/src/main.c
+++ b/src/blogc.c
@@ -24,12 +24,12 @@
#include <stdio.h>
#include <string.h>
-#include "utils/utils.h"
#include "source-parser.h"
#include "template-parser.h"
#include "loader.h"
#include "renderer.h"
#include "error.h"
+#include "utils.h"
#ifndef PACKAGE_VERSION
#define PACKAGE_VERSION "Unknown"
@@ -71,7 +71,7 @@ blogc_print_usage(void)
static void
blogc_mkdir_recursive(const char *filename)
{
- char *fname = b_strdup(filename);
+ char *fname = sb_strdup(filename);
for (char *tmp = fname; *tmp != '\0'; tmp++) {
if (*tmp != '/' && *tmp != '\\')
continue;
@@ -117,9 +117,9 @@ main(int argc, char **argv)
char *tmp = NULL;
char **pieces = NULL;
- b_slist_t *sources = NULL;
- b_trie_t *config = b_trie_new(free);
- b_trie_insert(config, "BLOGC_VERSION", b_strdup(PACKAGE_VERSION));
+ sb_slist_t *sources = NULL;
+ sb_trie_t *config = sb_trie_new(free);
+ sb_trie_insert(config, "BLOGC_VERSION", sb_strdup(PACKAGE_VERSION));
for (unsigned int i = 1; i < argc; i++) {
tmp = NULL;
@@ -136,21 +136,21 @@ main(int argc, char **argv)
break;
case 't':
if (argv[i][2] != '\0')
- template = b_strdup(argv[i] + 2);
+ template = sb_strdup(argv[i] + 2);
else if (i + 1 < argc)
- template = b_strdup(argv[++i]);
+ template = sb_strdup(argv[++i]);
break;
case 'o':
if (argv[i][2] != '\0')
- output = b_strdup(argv[i] + 2);
+ output = sb_strdup(argv[i] + 2);
else if (i + 1 < argc)
- output = b_strdup(argv[++i]);
+ output = sb_strdup(argv[++i]);
break;
case 'p':
if (argv[i][2] != '\0')
- print = b_strdup(argv[i] + 2);
+ print = sb_strdup(argv[i] + 2);
else if (i + 1 < argc)
- print = b_strdup(argv[++i]);
+ print = sb_strdup(argv[++i]);
break;
case 'D':
if (argv[i][2] != '\0')
@@ -158,11 +158,11 @@ main(int argc, char **argv)
else if (i + 1 < argc)
tmp = argv[++i];
if (tmp != NULL) {
- pieces = b_str_split(tmp, '=', 2);
- if (b_strv_length(pieces) != 2) {
+ pieces = sb_str_split(tmp, '=', 2);
+ if (sb_strv_length(pieces) != 2) {
fprintf(stderr, "blogc: error: invalid value for "
"-D (must have an '='): %s\n", tmp);
- b_strv_free(pieces);
+ sb_strv_free(pieces);
rv = 2;
goto cleanup;
}
@@ -173,13 +173,13 @@ main(int argc, char **argv)
fprintf(stderr, "blogc: error: invalid value "
"for -D (configuration key must be uppercase "
"with '_'): %s\n", pieces[0]);
- b_strv_free(pieces);
+ sb_strv_free(pieces);
rv = 2;
goto cleanup;
}
}
- b_trie_insert(config, pieces[0], b_strdup(pieces[1]));
- b_strv_free(pieces);
+ sb_trie_insert(config, pieces[0], sb_strdup(pieces[1]));
+ sb_strv_free(pieces);
pieces = NULL;
}
break;
@@ -192,17 +192,17 @@ main(int argc, char **argv)
}
}
else
- sources = b_slist_append(sources, b_strdup(argv[i]));
+ sources = sb_slist_append(sources, sb_strdup(argv[i]));
}
- if (!listing && b_slist_length(sources) == 0) {
+ if (!listing && sb_slist_length(sources) == 0) {
blogc_print_usage();
fprintf(stderr, "blogc: error: one source file is required\n");
rv = 2;
goto cleanup;
}
- if (!listing && b_slist_length(sources) > 1) {
+ if (!listing && sb_slist_length(sources) > 1) {
blogc_print_usage();
fprintf(stderr, "blogc: error: only one source file should be provided, "
"if running without '-l'\n");
@@ -212,14 +212,14 @@ main(int argc, char **argv)
blogc_error_t *err = NULL;
- b_slist_t *s = blogc_source_parse_from_files(config, sources, &err);
+ sb_slist_t *s = blogc_source_parse_from_files(config, sources, &err);
if (err != NULL) {
blogc_error_print(err);
rv = 2;
goto cleanup2;
}
- b_slist_t* l = blogc_template_parse_from_file(template, &err);
+ sb_slist_t* l = blogc_template_parse_from_file(template, &err);
if (err != NULL) {
blogc_error_print(err);
rv = 2;
@@ -227,7 +227,7 @@ main(int argc, char **argv)
}
if (print != NULL) {
- const char *val = b_trie_lookup(config, print);
+ const char *val = sb_trie_lookup(config, print);
if (val == NULL) {
fprintf(stderr, "blogc: error: configuration variable not found: %s\n",
print);
@@ -273,13 +273,13 @@ cleanup4:
cleanup3:
blogc_template_free_stmts(l);
cleanup2:
- b_slist_free_full(s, (b_free_func_t) b_trie_free);
+ sb_slist_free_full(s, (sb_free_func_t) sb_trie_free);
blogc_error_free(err);
cleanup:
- b_trie_free(config);
+ sb_trie_free(config);
free(template);
free(output);
free(print);
- b_slist_free_full(sources, free);
+ sb_slist_free_full(sources, free);
return rv;
}
diff --git a/src/content-parser.c b/src/content-parser.c
index 8dceb8b..0561d20 100644
--- a/src/content-parser.c
+++ b/src/content-parser.c
@@ -13,9 +13,9 @@
#include <stdbool.h>
#include <string.h>
-#include "utils/utils.h"
#include "content-parser.h"
#include "directives.h"
+#include "utils.h"
// this is a half ass implementation of a markdown-like syntax. bugs are
// expected. feel free to improve the parser and add new features.
@@ -26,7 +26,7 @@ blogc_slugify(const char *str)
{
if (str == NULL)
return NULL;
- char *new_str = b_strdup(str);
+ char *new_str = sb_strdup(str);
int diff = 'a' - 'A'; // just to avoid magic numbers
for (size_t i = 0; new_str[i] != '\0'; i++) {
if (new_str[i] >= 'a' && new_str[i] <= 'z')
@@ -47,32 +47,32 @@ blogc_htmlentities(const char *str)
{
if (str == NULL)
return NULL;
- b_string_t *rv = b_string_new();
+ sb_string_t *rv = sb_string_new();
for (size_t i = 0; str[i] != '\0'; i++) {
switch (str[i]) {
case '&':
- b_string_append(rv, "&amp;");
+ sb_string_append(rv, "&amp;");
break;
case '<':
- b_string_append(rv, "&lt;");
+ sb_string_append(rv, "&lt;");
break;
case '>':
- b_string_append(rv, "&gt;");
+ sb_string_append(rv, "&gt;");
break;
case '"':
- b_string_append(rv, "&quot;");
+ sb_string_append(rv, "&quot;");
break;
case '\'':
- b_string_append(rv, "&#x27;");
+ sb_string_append(rv, "&#x27;");
break;
case '/':
- b_string_append(rv, "&#x2F;");
+ sb_string_append(rv, "&#x2F;");
break;
default:
- b_string_append_c(rv, str[i]);
+ sb_string_append_c(rv, str[i]);
}
}
- return b_string_free(rv, false);
+ return sb_string_free(rv, false);
}
@@ -139,7 +139,7 @@ blogc_content_parse_inline(const char *src)
size_t start_state = 0;
size_t end = 0;
- b_string_t *rv = b_string_new();
+ sb_string_t *rv = sb_string_new();
bool open_em_ast = false;
bool open_strong_ast = false;
@@ -165,7 +165,7 @@ blogc_content_parse_inline(const char *src)
if (escape) {
if (state == LINK_CLOSED)
- b_string_append_c(rv, c);
+ sb_string_append_c(rv, c);
current++;
escape = false;
continue;
@@ -174,11 +174,21 @@ blogc_content_parse_inline(const char *src)
if (c != ' ' && c != '\n' && c != '\r')
spaces = 0;
+ if (state == LINK_TEXT_CLOSE && c != ' ' && c != '\n' && c != '\r' &&
+ c != '(')
+ {
+ sb_string_append_c(rv, src[start_state]);
+ tmp = blogc_content_parse_inline(src + start_state + 1);
+ sb_string_append(rv, tmp);
+ // no need to free here, we will exit the loop!
+ break;
+ }
+
switch (c) {
case '\\':
if (state == LINK_CLOSED && (open_code || open_code_double)) {
- b_string_append_c(rv, c);
+ sb_string_append_c(rv, c);
break;
}
if (!escape)
@@ -188,7 +198,7 @@ blogc_content_parse_inline(const char *src)
case '*':
case '_':
if (state == LINK_CLOSED && (open_code || open_code_double)) {
- b_string_append_c(rv, c);
+ sb_string_append_c(rv, c);
break;
}
if (!is_last && src[current + 1] == c) {
@@ -197,7 +207,7 @@ blogc_content_parse_inline(const char *src)
(c == '_' && open_strong_und))
{
if (state == LINK_CLOSED)
- b_string_append(rv, "</strong>");
+ sb_string_append(rv, "</strong>");
if (c == '*')
open_strong_ast = false;
else
@@ -205,7 +215,7 @@ blogc_content_parse_inline(const char *src)
break;
}
if (state == LINK_CLOSED)
- b_string_append(rv, "<strong>");
+ sb_string_append(rv, "<strong>");
if (c == '*')
open_strong_ast = true;
else
@@ -214,7 +224,7 @@ blogc_content_parse_inline(const char *src)
}
if ((c == '*' && open_em_ast) || (c == '_' && open_em_und)) {
if (state == LINK_CLOSED)
- b_string_append(rv, "</em>");
+ sb_string_append(rv, "</em>");
if (c == '*')
open_em_ast = false;
else
@@ -222,7 +232,7 @@ blogc_content_parse_inline(const char *src)
break;
}
if (state == LINK_CLOSED)
- b_string_append(rv, "<em>");
+ sb_string_append(rv, "<em>");
if (c == '*')
open_em_ast = true;
else
@@ -233,22 +243,26 @@ blogc_content_parse_inline(const char *src)
if (!is_last && src[current + 1] == c) {
current++;
if (state == LINK_CLOSED)
- b_string_append_printf(rv, "<%scode>",
+ sb_string_append_printf(rv, "<%scode>",
open_code_double ? "/" : "");
open_code_double = !open_code_double;
break;
}
if (state == LINK_CLOSED)
- b_string_append_printf(rv, "<%scode>", open_code ? "/" : "");
+ sb_string_append_printf(rv, "<%scode>", open_code ? "/" : "");
open_code = !open_code;
break;
case '!':
- if (state == LINK_CLOSED && (open_code || open_code_double)) {
- b_string_append_c(rv, c);
- break;
- }
if (state == LINK_CLOSED) {
+ if (open_code || open_code_double) {
+ sb_string_append_c(rv, c);
+ break;
+ }
+ if (!is_last && src[current + 1] != '[') {
+ sb_string_append_c(rv, c);
+ break;
+ }
state = LINK_IMAGE;
is_image = true;
start_state = current;
@@ -257,7 +271,7 @@ blogc_content_parse_inline(const char *src)
case '[':
if (state == LINK_CLOSED && (open_code || open_code_double)) {
- b_string_append_c(rv, c);
+ sb_string_append_c(rv, c);
break;
}
if (state == LINK_CLOSED || state == LINK_IMAGE) {
@@ -287,8 +301,8 @@ blogc_content_parse_inline(const char *src)
}
if (state == LINK_AUTO_CLOSE) {
state = LINK_CLOSED;
- tmp = b_strndup(src + start, end - start);
- b_string_append_printf(rv, "<a href=\"%s\">%s</a>", tmp, tmp);
+ tmp = sb_strndup(src + start, end - start);
+ sb_string_append_printf(rv, "<a href=\"%s\">%s</a>", tmp, tmp);
end = 0;
free(tmp);
tmp = NULL;
@@ -298,7 +312,7 @@ blogc_content_parse_inline(const char *src)
if (state == LINK_TEXT) {
if (open_bracket-- == 0) {
state = LINK_TEXT_CLOSE;
- tmp = b_strndup(src + start, current - start);
+ tmp = sb_strndup(src + start, current - start);
tmp2 = blogc_content_parse_inline(tmp);
free(tmp);
tmp = NULL;
@@ -306,7 +320,7 @@ blogc_content_parse_inline(const char *src)
break;
}
if (state == LINK_CLOSED)
- b_string_append_c(rv, c);
+ sb_string_append_c(rv, c);
break;
case '(':
@@ -316,18 +330,18 @@ blogc_content_parse_inline(const char *src)
break;
}
if (state == LINK_CLOSED)
- b_string_append_c(rv, c);
+ sb_string_append_c(rv, c);
break;
case ')':
if (state == LINK_URL) {
state = LINK_CLOSED;
- tmp = b_strndup(src + start, current - start);
+ tmp = sb_strndup(src + start, current - start);
if (is_image)
- b_string_append_printf(rv, "<img src=\"%s\" alt=\"%s\">",
+ sb_string_append_printf(rv, "<img src=\"%s\" alt=\"%s\">",
tmp, tmp2);
else
- b_string_append_printf(rv, "<a href=\"%s\">%s</a>",
+ sb_string_append_printf(rv, "<a href=\"%s\">%s</a>",
tmp, tmp2);
free(tmp);
tmp = NULL;
@@ -337,13 +351,13 @@ blogc_content_parse_inline(const char *src)
break;
}
if (state == LINK_CLOSED)
- b_string_append_c(rv, c);
+ sb_string_append_c(rv, c);
break;
case ' ':
if (state == LINK_CLOSED) {
spaces++;
- b_string_append_c(rv, c);
+ sb_string_append_c(rv, c);
}
if (!is_last)
break;
@@ -352,55 +366,74 @@ blogc_content_parse_inline(const char *src)
case '\r':
if (state == LINK_CLOSED) {
if (spaces >= 2) {
- b_string_append(rv, "<br />");
+ sb_string_append(rv, "<br />");
spaces = 0;
}
if (c == '\n' || c == '\r')
- b_string_append_c(rv, c);
+ sb_string_append_c(rv, c);
+ }
+ break;
+
+ case '-':
+ if (state != LINK_CLOSED)
+ break;
+ if ((current < (src_len - 1) && src[current + 1] == '-') &&
+ !(open_code || open_code_double))
+ {
+ if (current < (src_len - 2) && src[current + 2] == '-') {
+ sb_string_append(rv, "&mdash;");
+ current += 2;
+ }
+ else {
+ sb_string_append(rv, "&ndash;");
+ current += 1;
+ }
+ }
+ else {
+ sb_string_append_c(rv, c);
}
break;
case '&':
if (state == LINK_CLOSED)
- b_string_append(rv, "&amp;");
+ sb_string_append(rv, "&amp;");
break;
case '<':
if (state == LINK_CLOSED)
- b_string_append(rv, "&lt;");
+ sb_string_append(rv, "&lt;");
break;
case '>':
if (state == LINK_CLOSED)
- b_string_append(rv, "&gt;");
+ sb_string_append(rv, "&gt;");
break;
case '"':
if (state == LINK_CLOSED)
- b_string_append(rv, "&quot;");
+ sb_string_append(rv, "&quot;");
break;
case '\'':
if (state == LINK_CLOSED)
- b_string_append(rv, "&#x27;");
+ sb_string_append(rv, "&#x27;");
break;
case '/':
if (state == LINK_CLOSED)
- b_string_append(rv, "&#x2F;");
+ sb_string_append(rv, "&#x2F;");
break;
default:
if (state == LINK_CLOSED)
- b_string_append_c(rv, c);
+ sb_string_append_c(rv, c);
}
if (is_last && state != LINK_CLOSED) {
- b_string_append_c(rv, src[start_state]);
+ sb_string_append_c(rv, src[start_state]);
tmp = blogc_content_parse_inline(src + start_state + 1);
- b_string_append(rv, tmp);
- free(tmp);
- tmp = NULL;
+ sb_string_append(rv, tmp);
+ // no need to free here, its the last iteration
}
current++;
}
@@ -408,7 +441,7 @@ blogc_content_parse_inline(const char *src)
free(tmp);
free(tmp2);
- return b_string_free(rv, false);
+ return sb_string_free(rv, false);
}
@@ -440,7 +473,7 @@ blogc_is_ordered_list_item(const char *str, size_t prefix_len)
char*
-blogc_content_parse(const char *src, size_t *end_excerpt)
+blogc_content_parse(const char *src, size_t *end_excerpt, char **description)
{
// src is always nul-terminated.
size_t src_len = strlen(src);
@@ -463,7 +496,7 @@ blogc_content_parse(const char *src, size_t *end_excerpt)
char *directive_name = NULL;
char *directive_argument = NULL;
char *directive_key = NULL;
- b_trie_t *directive_params = NULL;
+ sb_trie_t *directive_params = NULL;
// this isn't empty because we need some reasonable default value in the
// unlikely case that we need to print some line ending before evaluating
@@ -473,11 +506,11 @@ blogc_content_parse(const char *src, size_t *end_excerpt)
char d = '\0';
- b_slist_t *lines = NULL;
- b_slist_t *lines2 = NULL;
+ sb_slist_t *lines = NULL;
+ sb_slist_t *lines2 = NULL;
- b_string_t *rv = b_string_new();
- b_string_t *tmp_str = NULL;
+ sb_string_t *rv = sb_string_new();
+ sb_string_t *tmp_str = NULL;
blogc_content_parser_state_t state = CONTENT_START_LINE;
@@ -607,14 +640,14 @@ blogc_content_parse(const char *src, size_t *end_excerpt)
if (c == '\n' || c == '\r' || is_last) {
end = is_last && c != '\n' && c != '\r' ? src_len :
(real_end != 0 ? real_end : current);
- tmp = b_strndup(src + start, end - start);
+ tmp = sb_strndup(src + start, end - start);
parsed = blogc_content_parse_inline(tmp);
slug = blogc_slugify(tmp);
if (slug == NULL)
- b_string_append_printf(rv, "<h%d>%s</h%d>%s",
+ sb_string_append_printf(rv, "<h%d>%s</h%d>%s",
header_level, parsed, header_level, line_ending);
else
- b_string_append_printf(rv, "<h%d id=\"%s\">%s</h%d>%s",
+ sb_string_append_printf(rv, "<h%d id=\"%s\">%s</h%d>%s",
header_level, slug, parsed, header_level,
line_ending);
free(slug);
@@ -638,8 +671,8 @@ blogc_content_parse(const char *src, size_t *end_excerpt)
case CONTENT_HTML_END:
if (c == '\n' || c == '\r' || is_last) {
- tmp = b_strndup(src + start, end - start);
- b_string_append_printf(rv, "%s%s", tmp, line_ending);
+ tmp = sb_strndup(src + start, end - start);
+ sb_string_append_printf(rv, "%s%s", tmp, line_ending);
free(tmp);
tmp = NULL;
state = CONTENT_START_LINE;
@@ -652,7 +685,7 @@ blogc_content_parse(const char *src, size_t *end_excerpt)
case CONTENT_BLOCKQUOTE:
if (c == ' ' || c == '\t')
break;
- prefix = b_strndup(src + start, current - start);
+ prefix = sb_strndup(src + start, current - start);
state = CONTENT_BLOCKQUOTE_START;
break;
@@ -660,16 +693,16 @@ blogc_content_parse(const char *src, size_t *end_excerpt)
if (c == '\n' || c == '\r' || is_last) {
end = is_last && c != '\n' && c != '\r' ? src_len :
(real_end != 0 ? real_end : current);
- tmp = b_strndup(src + start2, end - start2);
- if (b_str_starts_with(tmp, prefix)) {
- lines = b_slist_append(lines, b_strdup(tmp + strlen(prefix)));
+ tmp = sb_strndup(src + start2, end - start2);
+ if (sb_str_starts_with(tmp, prefix)) {
+ lines = sb_slist_append(lines, sb_strdup(tmp + strlen(prefix)));
state = CONTENT_BLOCKQUOTE_END;
}
else {
state = CONTENT_PARAGRAPH;
free(prefix);
prefix = NULL;
- b_slist_free_full(lines, free);
+ sb_slist_free_full(lines, free);
lines = NULL;
if (is_last) {
free(tmp);
@@ -685,22 +718,18 @@ blogc_content_parse(const char *src, size_t *end_excerpt)
case CONTENT_BLOCKQUOTE_END:
if (c == '\n' || c == '\r' || is_last) {
- tmp_str = b_string_new();
- for (b_slist_t *l = lines; l != NULL; l = l->next) {
- if (l->next == NULL)
- b_string_append_printf(tmp_str, "%s", l->data);
- else
- b_string_append_printf(tmp_str, "%s%s", l->data,
- line_ending);
- }
- tmp = blogc_content_parse(tmp_str->str, NULL);
- b_string_append_printf(rv, "<blockquote>%s</blockquote>%s",
+ tmp_str = sb_string_new();
+ for (sb_slist_t *l = lines; l != NULL; l = l->next)
+ sb_string_append_printf(tmp_str, "%s%s", l->data,
+ line_ending);
+ tmp = blogc_content_parse(tmp_str->str, NULL, description);
+ sb_string_append_printf(rv, "<blockquote>%s</blockquote>%s",
tmp, line_ending);
free(tmp);
tmp = NULL;
- b_string_free(tmp_str, true);
+ sb_string_free(tmp_str, true);
tmp_str = NULL;
- b_slist_free_full(lines, free);
+ sb_slist_free_full(lines, free);
lines = NULL;
free(prefix);
prefix = NULL;
@@ -716,7 +745,7 @@ blogc_content_parse(const char *src, size_t *end_excerpt)
case CONTENT_CODE:
if (c == ' ' || c == '\t')
break;
- prefix = b_strndup(src + start, current - start);
+ prefix = sb_strndup(src + start, current - start);
state = CONTENT_CODE_START;
break;
@@ -724,16 +753,16 @@ blogc_content_parse(const char *src, size_t *end_excerpt)
if (c == '\n' || c == '\r' || is_last) {
end = is_last && c != '\n' && c != '\r' ? src_len :
(real_end != 0 ? real_end : current);
- tmp = b_strndup(src + start2, end - start2);
- if (b_str_starts_with(tmp, prefix)) {
- lines = b_slist_append(lines, b_strdup(tmp + strlen(prefix)));
+ tmp = sb_strndup(src + start2, end - start2);
+ if (sb_str_starts_with(tmp, prefix)) {
+ lines = sb_slist_append(lines, sb_strdup(tmp + strlen(prefix)));
state = CONTENT_CODE_END;
}
else {
state = CONTENT_PARAGRAPH;
free(prefix);
prefix = NULL;
- b_slist_free_full(lines, free);
+ sb_slist_free_full(lines, free);
lines = NULL;
free(tmp);
tmp = NULL;
@@ -749,18 +778,18 @@ blogc_content_parse(const char *src, size_t *end_excerpt)
case CONTENT_CODE_END:
if (c == '\n' || c == '\r' || is_last) {
- b_string_append(rv, "<pre><code>");
- for (b_slist_t *l = lines; l != NULL; l = l->next) {
+ sb_string_append(rv, "<pre><code>");
+ for (sb_slist_t *l = lines; l != NULL; l = l->next) {
char *tmp_line = blogc_htmlentities(l->data);
if (l->next == NULL)
- b_string_append_printf(rv, "%s", tmp_line);
+ sb_string_append_printf(rv, "%s", tmp_line);
else
- b_string_append_printf(rv, "%s%s", tmp_line,
+ sb_string_append_printf(rv, "%s%s", tmp_line,
line_ending);
free(tmp_line);
}
- b_string_append_printf(rv, "</code></pre>%s", line_ending);
- b_slist_free_full(lines, free);
+ sb_string_append_printf(rv, "</code></pre>%s", line_ending);
+ sb_slist_free_full(lines, free);
lines = NULL;
free(prefix);
prefix = NULL;
@@ -782,7 +811,7 @@ blogc_content_parse(const char *src, size_t *end_excerpt)
}
if (c == ' ' || c == '\t')
break;
- prefix = b_strndup(src + start, current - start);
+ prefix = sb_strndup(src + start, current - start);
state = CONTENT_UNORDERED_LIST_START;
break;
@@ -791,7 +820,7 @@ blogc_content_parse(const char *src, size_t *end_excerpt)
break;
}
if (c == '\n' || c == '\r' || is_last) {
- b_string_append_printf(rv, "<hr />%s", line_ending);
+ sb_string_append_printf(rv, "<hr />%s", line_ending);
state = CONTENT_START_LINE;
start = current;
d = '\0';
@@ -804,30 +833,30 @@ blogc_content_parse(const char *src, size_t *end_excerpt)
if (c == '\n' || c == '\r' || is_last) {
end = is_last && c != '\n' && c != '\r' ? src_len :
(real_end != 0 ? real_end : current);
- tmp = b_strndup(src + start2, end - start2);
- tmp2 = b_strdup_printf("%-*s", strlen(prefix), "");
- if (b_str_starts_with(tmp, prefix)) {
+ tmp = sb_strndup(src + start2, end - start2);
+ tmp2 = sb_strdup_printf("%-*s", strlen(prefix), "");
+ if (sb_str_starts_with(tmp, prefix)) {
if (lines2 != NULL) {
- tmp_str = b_string_new();
- for (b_slist_t *l = lines2; l != NULL; l = l->next) {
+ tmp_str = sb_string_new();
+ for (sb_slist_t *l = lines2; l != NULL; l = l->next) {
if (l->next == NULL)
- b_string_append_printf(tmp_str, "%s", l->data);
+ sb_string_append_printf(tmp_str, "%s", l->data);
else
- b_string_append_printf(tmp_str, "%s%s", l->data,
+ sb_string_append_printf(tmp_str, "%s%s", l->data,
line_ending);
}
- b_slist_free_full(lines2, free);
+ sb_slist_free_full(lines2, free);
lines2 = NULL;
parsed = blogc_content_parse_inline(tmp_str->str);
- b_string_free(tmp_str, true);
- lines = b_slist_append(lines, b_strdup(parsed));
+ sb_string_free(tmp_str, true);
+ lines = sb_slist_append(lines, sb_strdup(parsed));
free(parsed);
parsed = NULL;
}
- lines2 = b_slist_append(lines2, b_strdup(tmp + strlen(prefix)));
+ lines2 = sb_slist_append(lines2, sb_strdup(tmp + strlen(prefix)));
}
- else if (b_str_starts_with(tmp, tmp2)) {
- lines2 = b_slist_append(lines2, b_strdup(tmp + strlen(prefix)));
+ else if (sb_str_starts_with(tmp, tmp2)) {
+ lines2 = sb_slist_append(lines2, sb_strdup(tmp + strlen(prefix)));
}
else {
state = CONTENT_PARAGRAPH_END;
@@ -837,8 +866,8 @@ blogc_content_parse(const char *src, size_t *end_excerpt)
tmp2 = NULL;
free(prefix);
prefix = NULL;
- b_slist_free_full(lines, free);
- b_slist_free_full(lines2, free);
+ sb_slist_free_full(lines, free);
+ sb_slist_free_full(lines2, free);
lines = NULL;
if (is_last)
continue;
@@ -857,28 +886,28 @@ blogc_content_parse(const char *src, size_t *end_excerpt)
if (c == '\n' || c == '\r' || is_last) {
if (lines2 != NULL) {
// FIXME: avoid repeting the code below
- tmp_str = b_string_new();
- for (b_slist_t *l = lines2; l != NULL; l = l->next) {
+ tmp_str = sb_string_new();
+ for (sb_slist_t *l = lines2; l != NULL; l = l->next) {
if (l->next == NULL)
- b_string_append_printf(tmp_str, "%s", l->data);
+ sb_string_append_printf(tmp_str, "%s", l->data);
else
- b_string_append_printf(tmp_str, "%s%s", l->data,
+ sb_string_append_printf(tmp_str, "%s%s", l->data,
line_ending);
}
- b_slist_free_full(lines2, free);
+ sb_slist_free_full(lines2, free);
lines2 = NULL;
parsed = blogc_content_parse_inline(tmp_str->str);
- b_string_free(tmp_str, true);
- lines = b_slist_append(lines, b_strdup(parsed));
+ sb_string_free(tmp_str, true);
+ lines = sb_slist_append(lines, sb_strdup(parsed));
free(parsed);
parsed = NULL;
}
- b_string_append_printf(rv, "<ul>%s", line_ending);
- for (b_slist_t *l = lines; l != NULL; l = l->next)
- b_string_append_printf(rv, "<li>%s</li>%s", l->data,
+ sb_string_append_printf(rv, "<ul>%s", line_ending);
+ for (sb_slist_t *l = lines; l != NULL; l = l->next)
+ sb_string_append_printf(rv, "<li>%s</li>%s", l->data,
line_ending);
- b_string_append_printf(rv, "</ul>%s", line_ending);
- b_slist_free_full(lines, free);
+ sb_string_append_printf(rv, "</ul>%s", line_ending);
+ sb_slist_free_full(lines, free);
lines = NULL;
free(prefix);
prefix = NULL;
@@ -915,30 +944,30 @@ blogc_content_parse(const char *src, size_t *end_excerpt)
if (c == '\n' || c == '\r' || is_last) {
end = is_last && c != '\n' && c != '\r' ? src_len :
(real_end != 0 ? real_end : current);
- tmp = b_strndup(src + start2, end - start2);
- tmp2 = b_strdup_printf("%-*s", prefix_len, "");
+ tmp = sb_strndup(src + start2, end - start2);
+ tmp2 = sb_strdup_printf("%-*s", prefix_len, "");
if (blogc_is_ordered_list_item(tmp, prefix_len)) {
if (lines2 != NULL) {
- tmp_str = b_string_new();
- for (b_slist_t *l = lines2; l != NULL; l = l->next) {
+ tmp_str = sb_string_new();
+ for (sb_slist_t *l = lines2; l != NULL; l = l->next) {
if (l->next == NULL)
- b_string_append_printf(tmp_str, "%s", l->data);
+ sb_string_append_printf(tmp_str, "%s", l->data);
else
- b_string_append_printf(tmp_str, "%s%s", l->data,
+ sb_string_append_printf(tmp_str, "%s%s", l->data,
line_ending);
}
- b_slist_free_full(lines2, free);
+ sb_slist_free_full(lines2, free);
lines2 = NULL;
parsed = blogc_content_parse_inline(tmp_str->str);
- b_string_free(tmp_str, true);
- lines = b_slist_append(lines, b_strdup(parsed));
+ sb_string_free(tmp_str, true);
+ lines = sb_slist_append(lines, sb_strdup(parsed));
free(parsed);
parsed = NULL;
}
- lines2 = b_slist_append(lines2, b_strdup(tmp + prefix_len));
+ lines2 = sb_slist_append(lines2, sb_strdup(tmp + prefix_len));
}
- else if (b_str_starts_with(tmp, tmp2)) {
- lines2 = b_slist_append(lines2, b_strdup(tmp + prefix_len));
+ else if (sb_str_starts_with(tmp, tmp2)) {
+ lines2 = sb_slist_append(lines2, sb_strdup(tmp + prefix_len));
}
else {
state = CONTENT_PARAGRAPH_END;
@@ -948,8 +977,8 @@ blogc_content_parse(const char *src, size_t *end_excerpt)
tmp2 = NULL;
free(parsed);
parsed = NULL;
- b_slist_free_full(lines, free);
- b_slist_free_full(lines2, free);
+ sb_slist_free_full(lines, free);
+ sb_slist_free_full(lines2, free);
lines = NULL;
if (is_last)
continue;
@@ -968,28 +997,28 @@ blogc_content_parse(const char *src, size_t *end_excerpt)
if (c == '\n' || c == '\r' || is_last) {
if (lines2 != NULL) {
// FIXME: avoid repeting the code below
- tmp_str = b_string_new();
- for (b_slist_t *l = lines2; l != NULL; l = l->next) {
+ tmp_str = sb_string_new();
+ for (sb_slist_t *l = lines2; l != NULL; l = l->next) {
if (l->next == NULL)
- b_string_append_printf(tmp_str, "%s", l->data);
+ sb_string_append_printf(tmp_str, "%s", l->data);
else
- b_string_append_printf(tmp_str, "%s%s", l->data,
+ sb_string_append_printf(tmp_str, "%s%s", l->data,
line_ending);
}
- b_slist_free_full(lines2, free);
+ sb_slist_free_full(lines2, free);
lines2 = NULL;
parsed = blogc_content_parse_inline(tmp_str->str);
- b_string_free(tmp_str, true);
- lines = b_slist_append(lines, b_strdup(parsed));
+ sb_string_free(tmp_str, true);
+ lines = sb_slist_append(lines, sb_strdup(parsed));
free(parsed);
parsed = NULL;
}
- b_string_append_printf(rv, "<ol>%s", line_ending);
- for (b_slist_t *l = lines; l != NULL; l = l->next)
- b_string_append_printf(rv, "<li>%s</li>%s", l->data,
+ sb_string_append_printf(rv, "<ol>%s", line_ending);
+ for (sb_slist_t *l = lines; l != NULL; l = l->next)
+ sb_string_append_printf(rv, "<li>%s</li>%s", l->data,
line_ending);
- b_string_append_printf(rv, "</ol>%s", line_ending);
- b_slist_free_full(lines, free);
+ sb_string_append_printf(rv, "</ol>%s", line_ending);
+ sb_slist_free_full(lines, free);
lines = NULL;
free(prefix);
prefix = NULL;
@@ -1033,7 +1062,7 @@ blogc_content_parse(const char *src, size_t *end_excerpt)
case CONTENT_DIRECTIVE_COLON:
if (c == ':') {
free(directive_name);
- directive_name = b_strndup(src + start2, end - start2);
+ directive_name = sb_strndup(src + start2, end - start2);
state = CONTENT_DIRECTIVE_ARGUMENT_START;
if (is_last) {
state = CONTENT_DIRECTIVE_PARAM_END;
@@ -1077,7 +1106,7 @@ blogc_content_parse(const char *src, size_t *end_excerpt)
end = is_last && c != '\n' && c != '\r' ? src_len :
(real_end != 0 ? real_end : current);
free(directive_argument);
- directive_argument = b_strndup(src + start2, end - start2);
+ directive_argument = sb_strndup(src + start2, end - start2);
if (is_last) {
state = CONTENT_DIRECTIVE_PARAM_END;
continue;
@@ -1098,7 +1127,7 @@ blogc_content_parse(const char *src, size_t *end_excerpt)
state = CONTENT_DIRECTIVE_PARAM_END;
continue;
}
- prefix = b_strndup(src + start2, current - start2);
+ prefix = sb_strndup(src + start2, current - start2);
state = CONTENT_DIRECTIVE_PARAM_PREFIX;
current--;
break;
@@ -1106,7 +1135,7 @@ blogc_content_parse(const char *src, size_t *end_excerpt)
case CONTENT_DIRECTIVE_PARAM_PREFIX:
if (c == ' ' || c == '\t')
break;
- if (c == ':' && b_str_starts_with(src + start2, prefix)) {
+ if (c == ':' && sb_str_starts_with(src + start2, prefix)) {
state = CONTENT_DIRECTIVE_PARAM_KEY_START;
break;
}
@@ -1137,7 +1166,7 @@ blogc_content_parse(const char *src, size_t *end_excerpt)
break;
if (c == ':') {
free(directive_key);
- directive_key = b_strndup(src + start2, current - start2);
+ directive_key = sb_strndup(src + start2, current - start2);
state = CONTENT_DIRECTIVE_PARAM_VALUE_START;
break;
}
@@ -1161,9 +1190,9 @@ blogc_content_parse(const char *src, size_t *end_excerpt)
end = is_last && c != '\n' && c != '\r' ? src_len :
(real_end != 0 ? real_end : current);
if (directive_params == NULL)
- directive_params = b_trie_new(free);
- b_trie_insert(directive_params, directive_key,
- b_strndup(src + start2, end - start2));
+ directive_params = sb_trie_new(free);
+ sb_trie_insert(directive_params, directive_key,
+ sb_strndup(src + start2, end - start2));
free(directive_key);
directive_key = NULL;
if (!is_last)
@@ -1176,7 +1205,7 @@ blogc_content_parse(const char *src, size_t *end_excerpt)
if (c == '\n' || c == '\r' || is_last) {
// FIXME: handle errors in the rest of the parser.
blogc_error_t *err = NULL;
- blogc_directive_ctx_t *ctx = b_malloc(
+ blogc_directive_ctx_t *ctx = sb_malloc(
sizeof(blogc_directive_ctx_t));
ctx->name = directive_name;
ctx->argument = directive_argument;
@@ -1186,7 +1215,7 @@ blogc_content_parse(const char *src, size_t *end_excerpt)
free(ctx);
blogc_error_print(err);
if (rv_d != NULL)
- b_string_append(rv, rv_d);
+ sb_string_append(rv, rv_d);
free(rv_d);
state = CONTENT_START_LINE;
start = current;
@@ -1194,7 +1223,7 @@ blogc_content_parse(const char *src, size_t *end_excerpt)
directive_name = NULL;
free(directive_argument);
directive_argument = NULL;
- b_trie_free(directive_params);
+ sb_trie_free(directive_params);
directive_params = NULL;
free(prefix);
prefix = NULL;
@@ -1215,15 +1244,17 @@ blogc_content_parse(const char *src, size_t *end_excerpt)
state = CONTENT_PARAGRAPH_END;
end = is_last && c != '\n' && c != '\r' ? src_len :
(real_end != 0 ? real_end : current);
+ if (description != NULL && *description == NULL)
+ *description = sb_strndup(src + start, end - start);
}
if (!is_last)
break;
case CONTENT_PARAGRAPH_END:
if (c == '\n' || c == '\r' || is_last) {
- tmp = b_strndup(src + start, end - start);
+ tmp = sb_strndup(src + start, end - start);
parsed = blogc_content_parse_inline(tmp);
- b_string_append_printf(rv, "<p>%s</p>%s", parsed,
+ sb_string_append_printf(rv, "<p>%s</p>%s", parsed,
line_ending);
free(parsed);
parsed = NULL;
@@ -1244,8 +1275,8 @@ blogc_content_parse(const char *src, size_t *end_excerpt)
free(directive_name);
free(directive_argument);
free(directive_key);
- b_trie_free(directive_params);
+ sb_trie_free(directive_params);
free(prefix);
- return b_string_free(rv, false);
+ return sb_string_free(rv, false);
}
diff --git a/src/content-parser.h b/src/content-parser.h
index 6617bb4..148d5ed 100644
--- a/src/content-parser.h
+++ b/src/content-parser.h
@@ -16,6 +16,7 @@ char* blogc_slugify(const char *str);
char* blogc_htmlentities(const char *str);
char* blogc_content_parse_inline(const char *src);
bool blogc_is_ordered_list_item(const char *str, size_t prefix_len);
-char* blogc_content_parse(const char *src, size_t *end_excerpt);
+char* blogc_content_parse(const char *src, size_t *end_excerpt,
+ char **description);
#endif /* _CONTENT_PARSER_H */
diff --git a/src/datetime-parser.c b/src/datetime-parser.c
index 8785a89..ad65ff7 100644
--- a/src/datetime-parser.c
+++ b/src/datetime-parser.c
@@ -17,8 +17,8 @@
#include <string.h>
#include "error.h"
-#include "utils/utils.h"
#include "datetime-parser.h"
+#include "utils.h"
typedef enum {
@@ -380,7 +380,7 @@ blogc_convert_datetime(const char *orig, const char *format,
return NULL;
}
- return b_strdup(buf);
+ return sb_strdup(buf);
#endif
}
diff --git a/src/directives.c b/src/directives.c
index b538825..eb6166b 100644
--- a/src/directives.c
+++ b/src/directives.c
@@ -12,9 +12,9 @@
#include <string.h>
-#include "utils/utils.h"
#include "directives.h"
#include "error.h"
+#include "utils.h"
const static blogc_directive_t registry[] = {
@@ -48,11 +48,11 @@ blogc_directive_youtube(blogc_directive_ctx_t *ctx, blogc_error_t **err)
return NULL;
}
- char *width = b_trie_lookup(ctx->params, "width");
- char *height = b_trie_lookup(ctx->params, "height");
+ char *width = sb_trie_lookup(ctx->params, "width");
+ char *height = sb_trie_lookup(ctx->params, "height");
// using default 16:9 sizes provided by youtube as of 2015-11-04
- return b_strdup_printf(
+ return sb_strdup_printf(
"<iframe width=\"%s\" height=\"%s\" "
"src=\"https://www.youtube.com/embed/%s\" frameborder=\"0\" "
"allowfullscreen></iframe>%s",
diff --git a/src/directives.h b/src/directives.h
index dd27f03..0c6e35b 100644
--- a/src/directives.h
+++ b/src/directives.h
@@ -9,13 +9,13 @@
#ifndef _DIRECTIVES_H
#define _DIRECTIVES_H
-#include "utils/utils.h"
+#include "utils.h"
#include "error.h"
typedef struct {
const char *name;
const char *argument;
- b_trie_t *params;
+ sb_trie_t *params;
const char *eol;
} blogc_directive_ctx_t;
diff --git a/src/error.c b/src/error.c
index 59a85a3..3aea641 100644
--- a/src/error.c
+++ b/src/error.c
@@ -14,16 +14,16 @@
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
-#include "utils/utils.h"
#include "error.h"
+#include "utils.h"
blogc_error_t*
blogc_error_new(blogc_error_type_t type, const char *msg)
{
- blogc_error_t *err = b_malloc(sizeof(blogc_error_t));
+ blogc_error_t *err = sb_malloc(sizeof(blogc_error_t));
err->type = type;
- err->msg = b_strdup(msg);
+ err->msg = sb_strdup(msg);
return err;
}
@@ -33,7 +33,7 @@ blogc_error_new_printf(blogc_error_type_t type, const char *format, ...)
{
va_list ap;
va_start(ap, format);
- char *tmp = b_strdup_vprintf(format, ap);
+ char *tmp = sb_strdup_vprintf(format, ap);
va_end(ap);
blogc_error_t *rv = blogc_error_new(type, tmp);
free(tmp);
@@ -47,7 +47,7 @@ blogc_error_parser(blogc_error_type_t type, const char *src, size_t src_len,
{
va_list ap;
va_start(ap, format);
- char *msg = b_strdup_vprintf(format, ap);
+ char *msg = sb_strdup_vprintf(format, ap);
va_end(ap);
size_t lineno = 1;
@@ -88,7 +88,7 @@ blogc_error_parser(blogc_error_type_t type, const char *src, size_t src_len,
if (lineend <= linestart && src_len >= linestart)
lineend = src_len;
- char *line = b_strndup(src + linestart, lineend - linestart);
+ char *line = sb_strndup(src + linestart, lineend - linestart);
blogc_error_t *rv = NULL;
diff --git a/src/file.c b/src/file.c
index a4c763a..f784d93 100644
--- a/src/file.c
+++ b/src/file.c
@@ -14,9 +14,9 @@
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
-#include "utils/utils.h"
#include "file.h"
#include "error.h"
+#include "utils.h"
// this would belong to loader.c, but we need it in a separated file to be
// able to mock it when unit testing the loader functions.
@@ -38,16 +38,16 @@ blogc_file_get_contents(const char *path, size_t *len, blogc_error_t **err)
return NULL;
}
- b_string_t *str = b_string_new();
+ sb_string_t *str = sb_string_new();
char buffer[BLOGC_FILE_CHUNK_SIZE];
while (!feof(fp)) {
size_t read_len = fread(buffer, sizeof(char), BLOGC_FILE_CHUNK_SIZE, fp);
*len += read_len;
- b_string_append_len(str, buffer, read_len);
+ sb_string_append_len(str, buffer, read_len);
}
fclose(fp);
- return b_string_free(str, false);
+ return sb_string_free(str, false);
}
diff --git a/src/loader.c b/src/loader.c
index baa81fa..5ca0aac 100644
--- a/src/loader.c
+++ b/src/loader.c
@@ -14,12 +14,12 @@
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
-#include "utils/utils.h"
#include "file.h"
#include "source-parser.h"
#include "template-parser.h"
#include "loader.h"
#include "error.h"
+#include "utils.h"
char*
@@ -31,7 +31,7 @@ blogc_get_filename(const char *f)
if (strlen(f) == 0)
return NULL;
- char *filename = b_strdup(f);
+ char *filename = sb_strdup(f);
// keep a pointer to original string
char *tmp = filename;
@@ -52,14 +52,14 @@ blogc_get_filename(const char *f)
}
}
- char *final_filename = b_strdup(tmp);
+ char *final_filename = sb_strdup(tmp);
free(filename);
return final_filename;
}
-b_slist_t*
+sb_slist_t*
blogc_template_parse_from_file(const char *f, blogc_error_t **err)
{
if (err == NULL || *err != NULL)
@@ -68,13 +68,13 @@ blogc_template_parse_from_file(const char *f, blogc_error_t **err)
char *s = blogc_file_get_contents(f, &len, err);
if (s == NULL)
return NULL;
- b_slist_t *rv = blogc_template_parse(s, len, err);
+ sb_slist_t *rv = blogc_template_parse(s, len, err);
free(s);
return rv;
}
-b_trie_t*
+sb_trie_t*
blogc_source_parse_from_file(const char *f, blogc_error_t **err)
{
if (err == NULL || *err != NULL)
@@ -83,13 +83,13 @@ blogc_source_parse_from_file(const char *f, blogc_error_t **err)
char *s = blogc_file_get_contents(f, &len, err);
if (s == NULL)
return NULL;
- b_trie_t *rv = blogc_source_parse(s, len, err);
+ sb_trie_t *rv = blogc_source_parse(s, len, err);
// set FILENAME variable
if (rv != NULL) {
char *filename = blogc_get_filename(f);
if (filename != NULL)
- b_trie_insert(rv, "FILENAME", filename);
+ sb_trie_insert(rv, "FILENAME", filename);
}
free(s);
@@ -97,16 +97,16 @@ blogc_source_parse_from_file(const char *f, blogc_error_t **err)
}
-b_slist_t*
-blogc_source_parse_from_files(b_trie_t *conf, b_slist_t *l, blogc_error_t **err)
+sb_slist_t*
+blogc_source_parse_from_files(sb_trie_t *conf, sb_slist_t *l, blogc_error_t **err)
{
blogc_error_t *tmp_err = NULL;
- b_slist_t *rv = NULL;
+ sb_slist_t *rv = NULL;
unsigned int with_date = 0;
- const char *filter_tag = b_trie_lookup(conf, "FILTER_TAG");
- const char *filter_page = b_trie_lookup(conf, "FILTER_PAGE");
- const char *filter_per_page = b_trie_lookup(conf, "FILTER_PER_PAGE");
+ const char *filter_tag = sb_trie_lookup(conf, "FILTER_TAG");
+ const char *filter_page = sb_trie_lookup(conf, "FILTER_PAGE");
+ const char *filter_per_page = sb_trie_lookup(conf, "FILTER_PER_PAGE");
long page = strtol(filter_page != NULL ? filter_page : "", NULL, 10);
if (page <= 0)
@@ -121,27 +121,27 @@ blogc_source_parse_from_files(b_trie_t *conf, b_slist_t *l, blogc_error_t **err)
unsigned int end = start + per_page;
unsigned int counter = 0;
- for (b_slist_t *tmp = l; tmp != NULL; tmp = tmp->next) {
+ for (sb_slist_t *tmp = l; tmp != NULL; tmp = tmp->next) {
char *f = tmp->data;
- b_trie_t *s = blogc_source_parse_from_file(f, &tmp_err);
+ sb_trie_t *s = blogc_source_parse_from_file(f, &tmp_err);
if (s == NULL) {
*err = blogc_error_new_printf(BLOGC_ERROR_LOADER,
"An error occurred while parsing source file: %s\n\n%s",
f, tmp_err->msg);
blogc_error_free(tmp_err);
tmp_err = NULL;
- b_slist_free_full(rv, (b_free_func_t) b_trie_free);
+ sb_slist_free_full(rv, (sb_free_func_t) sb_trie_free);
rv = NULL;
break;
}
if (filter_tag != NULL) {
- const char *tags_str = b_trie_lookup(s, "TAGS");
+ const char *tags_str = sb_trie_lookup(s, "TAGS");
// if user wants to filter by tag and no tag is provided, skip it
if (tags_str == NULL) {
- b_trie_free(s);
+ sb_trie_free(s);
continue;
}
- char **tags = b_str_split(tags_str, ' ', 0);
+ char **tags = sb_str_split(tags_str, ' ', 0);
bool found = false;
for (unsigned int i = 0; tags[i] != NULL; i++) {
if (tags[i][0] == '\0')
@@ -149,26 +149,26 @@ blogc_source_parse_from_files(b_trie_t *conf, b_slist_t *l, blogc_error_t **err)
if (0 == strcmp(tags[i], filter_tag))
found = true;
}
- b_strv_free(tags);
+ sb_strv_free(tags);
if (!found) {
- b_trie_free(s);
+ sb_trie_free(s);
continue;
}
}
if (filter_page != NULL) {
if (counter < start || counter >= end) {
counter++;
- b_trie_free(s);
+ sb_trie_free(s);
continue;
}
counter++;
}
- if (b_trie_lookup(s, "DATE") != NULL)
+ if (sb_trie_lookup(s, "DATE") != NULL)
with_date++;
- rv = b_slist_append(rv, s);
+ rv = sb_slist_append(rv, s);
}
- if (with_date > 0 && with_date < b_slist_length(rv))
+ if (with_date > 0 && with_date < sb_slist_length(rv))
// fatal error, maybe?
blogc_fprintf(stderr,
"blogc: warning: 'DATE' variable provided for at least one source "
@@ -176,38 +176,38 @@ blogc_source_parse_from_files(b_trie_t *conf, b_slist_t *l, blogc_error_t **err)
"wrong values for 'DATE_FIRST' and 'DATE_LAST' variables.\n");
bool first = true;
- for (b_slist_t *tmp = rv; tmp != NULL; tmp = tmp->next) {
- b_trie_t *s = tmp->data;
+ for (sb_slist_t *tmp = rv; tmp != NULL; tmp = tmp->next) {
+ sb_trie_t *s = tmp->data;
if (first) {
- const char *val = b_trie_lookup(s, "DATE");
+ const char *val = sb_trie_lookup(s, "DATE");
if (val != NULL)
- b_trie_insert(conf, "DATE_FIRST", b_strdup(val));
- val = b_trie_lookup(s, "FILENAME");
+ sb_trie_insert(conf, "DATE_FIRST", sb_strdup(val));
+ val = sb_trie_lookup(s, "FILENAME");
if (val != NULL)
- b_trie_insert(conf, "FILENAME_FIRST", b_strdup(val));
+ sb_trie_insert(conf, "FILENAME_FIRST", sb_strdup(val));
first = false;
}
if (tmp->next == NULL) { // last
- const char *val = b_trie_lookup(s, "DATE");
+ const char *val = sb_trie_lookup(s, "DATE");
if (val != NULL)
- b_trie_insert(conf, "DATE_LAST", b_strdup(val));
- val = b_trie_lookup(s, "FILENAME");
+ sb_trie_insert(conf, "DATE_LAST", sb_strdup(val));
+ val = sb_trie_lookup(s, "FILENAME");
if (val != NULL)
- b_trie_insert(conf, "FILENAME_LAST", b_strdup(val));
+ sb_trie_insert(conf, "FILENAME_LAST", sb_strdup(val));
}
}
if (filter_page != NULL) {
unsigned int last_page = ceilf(((float) counter) / per_page);
- b_trie_insert(conf, "CURRENT_PAGE", b_strdup_printf("%ld", page));
+ sb_trie_insert(conf, "CURRENT_PAGE", sb_strdup_printf("%ld", page));
if (page > 1)
- b_trie_insert(conf, "PREVIOUS_PAGE", b_strdup_printf("%ld", page - 1));
+ sb_trie_insert(conf, "PREVIOUS_PAGE", sb_strdup_printf("%ld", page - 1));
if (page < last_page)
- b_trie_insert(conf, "NEXT_PAGE", b_strdup_printf("%ld", page + 1));
- if (b_slist_length(rv) > 0)
- b_trie_insert(conf, "FIRST_PAGE", b_strdup("1"));
+ sb_trie_insert(conf, "NEXT_PAGE", sb_strdup_printf("%ld", page + 1));
+ if (sb_slist_length(rv) > 0)
+ sb_trie_insert(conf, "FIRST_PAGE", sb_strdup("1"));
if (last_page > 0)
- b_trie_insert(conf, "LAST_PAGE", b_strdup_printf("%d", last_page));
+ sb_trie_insert(conf, "LAST_PAGE", sb_strdup_printf("%d", last_page));
}
return rv;
diff --git a/src/loader.h b/src/loader.h
index c432e20..32b58be 100644
--- a/src/loader.h
+++ b/src/loader.h
@@ -9,13 +9,13 @@
#ifndef _LOADER_H
#define _LOADER_H
-#include "utils/utils.h"
#include "error.h"
+#include "utils.h"
char* blogc_get_filename(const char *f);
-b_slist_t* blogc_template_parse_from_file(const char *f, blogc_error_t **err);
-b_trie_t* blogc_source_parse_from_file(const char *f, blogc_error_t **err);
-b_slist_t* blogc_source_parse_from_files(b_trie_t *conf, b_slist_t *l,
+sb_slist_t* blogc_template_parse_from_file(const char *f, blogc_error_t **err);
+sb_trie_t* blogc_source_parse_from_file(const char *f, blogc_error_t **err);
+sb_slist_t* blogc_source_parse_from_files(sb_trie_t *conf, sb_slist_t *l,
blogc_error_t **err);
#endif /* _LOADER_H */
diff --git a/src/renderer.c b/src/renderer.c
index 5e07b0c..5af3b8a 100644
--- a/src/renderer.c
+++ b/src/renderer.c
@@ -13,69 +13,69 @@
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
-#include "utils/utils.h"
#include "datetime-parser.h"
#include "error.h"
#include "loader.h"
#include "source-parser.h"
#include "template-parser.h"
#include "renderer.h"
+#include "utils.h"
const char*
-blogc_get_variable(const char *name, b_trie_t *global, b_trie_t *local)
+blogc_get_variable(const char *name, sb_trie_t *global, sb_trie_t *local)
{
const char *rv = NULL;
if (local != NULL) {
- rv = b_trie_lookup(local, name);
+ rv = sb_trie_lookup(local, name);
if (rv != NULL)
return rv;
}
if (global != NULL)
- rv = b_trie_lookup(global, name);
+ rv = sb_trie_lookup(global, name);
return rv;
}
char*
-blogc_format_date(const char *date, b_trie_t *global, b_trie_t *local)
+blogc_format_date(const char *date, sb_trie_t *global, sb_trie_t *local)
{
const char *date_format = blogc_get_variable("DATE_FORMAT", global, local);
if (date == NULL)
return NULL;
if (date_format == NULL)
- return b_strdup(date);
+ return sb_strdup(date);
blogc_error_t *err = NULL;
char *rv = blogc_convert_datetime(date, date_format, &err);
if (err != NULL) {
blogc_error_print(err);
blogc_error_free(err);
- return b_strdup(date);
+ return sb_strdup(date);
}
return rv;
}
char*
-blogc_format_variable(const char *name, b_trie_t *global, b_trie_t *local,
- b_slist_t *foreach_var)
+blogc_format_variable(const char *name, sb_trie_t *global, sb_trie_t *local,
+ sb_slist_t *foreach_var)
{
if (0 == strcmp(name, "FOREACH_ITEM")) {
if (foreach_var != NULL && foreach_var->data != NULL) {
- return b_strdup(foreach_var->data);
+ return sb_strdup(foreach_var->data);
}
return NULL;
}
char *var = NULL;
bool must_format = false;
- if (b_str_ends_with(name, "_FORMATTED")) {
- var = b_strndup(name, strlen(name) - 10);
+ if (sb_str_ends_with(name, "_FORMATTED")) {
+ var = sb_strndup(name, strlen(name) - 10);
must_format = true;
}
if (var == NULL)
- var = b_strdup(name);
+ var = sb_strdup(name);
const char *value = blogc_get_variable(var, global, local);
free(var);
@@ -85,30 +85,30 @@ blogc_format_variable(const char *name, b_trie_t *global, b_trie_t *local,
char *rv = NULL;
if (must_format) {
- if (b_str_starts_with(name, "DATE_")) {
+ if (sb_str_starts_with(name, "DATE_")) {
rv = blogc_format_date(value, global, local);
}
}
if (rv == NULL)
- return b_strdup(value);
+ return sb_strdup(value);
return rv;
}
-b_slist_t*
-blogc_split_list_variable(const char *name, b_trie_t *global, b_trie_t *local)
+sb_slist_t*
+blogc_split_list_variable(const char *name, sb_trie_t *global, sb_trie_t *local)
{
const char *value = blogc_get_variable(name, global, local);
if (value == NULL)
return NULL;
- b_slist_t *rv = NULL;
+ sb_slist_t *rv = NULL;
- char **tmp = b_str_split(value, ' ', 0);
+ char **tmp = sb_str_split(value, ' ', 0);
for (unsigned int i = 0; tmp[i] != NULL; i++) {
if (tmp[i][0] != '\0') // ignore empty strings
- rv = b_slist_append(rv, tmp[i]);
+ rv = sb_slist_append(rv, tmp[i]);
else
free(tmp[i]);
}
@@ -119,25 +119,25 @@ blogc_split_list_variable(const char *name, b_trie_t *global, b_trie_t *local)
char*
-blogc_render(b_slist_t *tmpl, b_slist_t *sources, b_trie_t *config, bool listing)
+blogc_render(sb_slist_t *tmpl, sb_slist_t *sources, sb_trie_t *config, bool listing)
{
if (tmpl == NULL)
return NULL;
- b_slist_t *current_source = NULL;
- b_slist_t *listing_start = NULL;
+ sb_slist_t *current_source = NULL;
+ sb_slist_t *listing_start = NULL;
- b_string_t *str = b_string_new();
+ sb_string_t *str = sb_string_new();
- b_trie_t *tmp_source = NULL;
+ sb_trie_t *tmp_source = NULL;
char *config_value = NULL;
char *defined = NULL;
unsigned int if_count = 0;
- b_slist_t *foreach_var = NULL;
- b_slist_t *foreach_var_start = NULL;
- b_slist_t *foreach_start = NULL;
+ sb_slist_t *foreach_var = NULL;
+ sb_slist_t *foreach_var_start = NULL;
+ sb_slist_t *foreach_start = NULL;
bool if_not = false;
bool inside_block = false;
@@ -145,7 +145,7 @@ blogc_render(b_slist_t *tmpl, b_slist_t *sources, b_trie_t *config, bool listing
int cmp = 0;
- b_slist_t *tmp = tmpl;
+ sb_slist_t *tmp = tmpl;
while (tmp != NULL) {
blogc_template_stmt_t *stmt = tmp->data;
@@ -153,7 +153,7 @@ blogc_render(b_slist_t *tmpl, b_slist_t *sources, b_trie_t *config, bool listing
case BLOGC_TEMPLATE_CONTENT_STMT:
if (stmt->value != NULL)
- b_string_append(str, stmt->value);
+ sb_string_append(str, stmt->value);
break;
case BLOGC_TEMPLATE_BLOCK_STMT:
@@ -210,7 +210,7 @@ blogc_render(b_slist_t *tmpl, b_slist_t *sources, b_trie_t *config, bool listing
config_value = blogc_format_variable(stmt->value,
config, inside_block ? tmp_source : NULL, foreach_var);
if (config_value != NULL) {
- b_string_append(str, config_value);
+ sb_string_append(str, config_value);
free(config_value);
config_value = NULL;
break;
@@ -252,7 +252,7 @@ blogc_render(b_slist_t *tmpl, b_slist_t *sources, b_trie_t *config, bool listing
(stmt->value2[0] == '"') &&
(stmt->value2[strlen(stmt->value2) - 1] == '"'))
{
- defined2 = b_strndup(stmt->value2 + 1,
+ defined2 = sb_strndup(stmt->value2 + 1,
strlen(stmt->value2) - 2);
}
else {
@@ -354,7 +354,7 @@ blogc_render(b_slist_t *tmpl, b_slist_t *sources, b_trie_t *config, bool listing
}
}
foreach_start = NULL;
- b_slist_free_full(foreach_var_start, free);
+ sb_slist_free_full(foreach_var_start, free);
foreach_var_start = NULL;
break;
}
@@ -364,5 +364,5 @@ blogc_render(b_slist_t *tmpl, b_slist_t *sources, b_trie_t *config, bool listing
// no need to free temporary variables here. the template parser makes sure
// that templates are sane and statements are closed.
- return b_string_free(str, false);
+ return sb_string_free(str, false);
}
diff --git a/src/renderer.h b/src/renderer.h
index 15204e6..2982ee8 100644
--- a/src/renderer.h
+++ b/src/renderer.h
@@ -10,15 +10,15 @@
#define _RENDERER_H
#include <stdbool.h>
-#include "utils/utils.h"
+#include "utils.h"
-const char* blogc_get_variable(const char *name, b_trie_t *global, b_trie_t *local);
-char* blogc_format_date(const char *date, b_trie_t *global, b_trie_t *local);
-char* blogc_format_variable(const char *name, b_trie_t *global, b_trie_t *local,
- b_slist_t *foreach_var);
-b_slist_t* blogc_split_list_variable(const char *name, b_trie_t *global,
- b_trie_t *local);
-char* blogc_render(b_slist_t *tmpl, b_slist_t *sources, b_trie_t *config,
+const char* blogc_get_variable(const char *name, sb_trie_t *global, sb_trie_t *local);
+char* blogc_format_date(const char *date, sb_trie_t *global, sb_trie_t *local);
+char* blogc_format_variable(const char *name, sb_trie_t *global, sb_trie_t *local,
+ sb_slist_t *foreach_var);
+sb_slist_t* blogc_split_list_variable(const char *name, sb_trie_t *global,
+ sb_trie_t *local);
+char* blogc_render(sb_slist_t *tmpl, sb_slist_t *sources, sb_trie_t *config,
bool listing);
#endif /* _RENDERER_H */
diff --git a/src/source-parser.c b/src/source-parser.c
index 65fdd4e..f250bd3 100644
--- a/src/source-parser.c
+++ b/src/source-parser.c
@@ -13,10 +13,10 @@
#include <stdbool.h>
#include <string.h>
-#include "utils/utils.h"
#include "content-parser.h"
#include "source-parser.h"
#include "error.h"
+#include "utils.h"
typedef enum {
@@ -30,7 +30,7 @@ typedef enum {
} blogc_source_parser_state_t;
-b_trie_t*
+sb_trie_t*
blogc_source_parse(const char *src, size_t src_len, blogc_error_t **err)
{
if (err == NULL || *err != NULL)
@@ -43,7 +43,7 @@ blogc_source_parse(const char *src, size_t src_len, blogc_error_t **err)
char *key = NULL;
char *tmp = NULL;
char *content = NULL;
- b_trie_t *rv = b_trie_new(free);
+ sb_trie_t *rv = sb_trie_new(free);
blogc_source_parser_state_t state = SOURCE_START;
@@ -73,7 +73,7 @@ blogc_source_parse(const char *src, size_t src_len, blogc_error_t **err)
if ((c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_')
break;
if (c == ':') {
- key = b_strndup(src + start, current - start);
+ key = sb_strndup(src + start, current - start);
if (((current - start == 8) &&
(0 == strncmp("FILENAME", src + start, 8))) ||
((current - start == 7) &&
@@ -122,8 +122,8 @@ blogc_source_parse(const char *src, size_t src_len, blogc_error_t **err)
case SOURCE_CONFIG_VALUE:
if (c == '\n' || c == '\r') {
- tmp = b_strndup(src + start, current - start);
- b_trie_insert(rv, key, b_strdup(b_str_strip(tmp)));
+ tmp = sb_strndup(src + start, current - start);
+ sb_trie_insert(rv, key, sb_strdup(sb_str_strip(tmp)));
free(tmp);
free(key);
key = NULL;
@@ -152,12 +152,24 @@ blogc_source_parse(const char *src, size_t src_len, blogc_error_t **err)
case SOURCE_CONTENT:
if (current == (src_len - 1)) {
- tmp = b_strndup(src + start, src_len - start);
- b_trie_insert(rv, "RAW_CONTENT", tmp);
- content = blogc_content_parse(tmp, &end_excerpt);
- b_trie_insert(rv, "CONTENT", content);
- b_trie_insert(rv, "EXCERPT", end_excerpt == 0 ?
- b_strdup(content) : b_strndup(content, end_excerpt));
+ tmp = sb_strndup(src + start, src_len - start);
+ sb_trie_insert(rv, "RAW_CONTENT", tmp);
+ char *description = NULL;
+ content = blogc_content_parse(tmp, &end_excerpt, &description);
+ if (description != NULL) {
+ // do not override source-provided description.
+ if (NULL == sb_trie_lookup(rv, "DESCRIPTION")) {
+ // no need to free, because we are transfering memory
+ // ownership to the trie.
+ sb_trie_insert(rv, "DESCRIPTION", description);
+ }
+ else {
+ free(description);
+ }
+ }
+ sb_trie_insert(rv, "CONTENT", content);
+ sb_trie_insert(rv, "EXCERPT", end_excerpt == 0 ?
+ sb_strdup(content) : sb_strndup(content, end_excerpt));
}
break;
}
@@ -168,7 +180,7 @@ blogc_source_parse(const char *src, size_t src_len, blogc_error_t **err)
current++;
}
- if (*err == NULL && b_trie_size(rv) == 0) {
+ if (*err == NULL && sb_trie_size(rv) == 0) {
// ok, nothing found in the config trie, but no error set either.
// let's try to be nice with the users and provide some reasonable
@@ -202,7 +214,7 @@ blogc_source_parse(const char *src, size_t src_len, blogc_error_t **err)
if (*err != NULL) {
free(key);
- b_trie_free(rv);
+ sb_trie_free(rv);
return NULL;
}
diff --git a/src/source-parser.h b/src/source-parser.h
index f359f9e..5cadf95 100644
--- a/src/source-parser.h
+++ b/src/source-parser.h
@@ -10,10 +10,10 @@
#define _SOURCE_PARSER_H
#include <stdlib.h>
-#include "utils/utils.h"
#include "error.h"
+#include "utils.h"
-b_trie_t* blogc_source_parse(const char *src, size_t src_len,
+sb_trie_t* blogc_source_parse(const char *src, size_t src_len,
blogc_error_t **err);
#endif /* _SOURCE_PARSER_H */
diff --git a/src/template-parser.c b/src/template-parser.c
index 1d9046e..525f5f5 100644
--- a/src/template-parser.c
+++ b/src/template-parser.c
@@ -13,9 +13,9 @@
#include <stdbool.h>
#include <string.h>
-#include "utils/utils.h"
#include "template-parser.h"
#include "error.h"
+#include "utils.h"
typedef enum {
@@ -52,7 +52,7 @@ typedef enum {
} blogc_template_parser_block_state_t;
-b_slist_t*
+sb_slist_t*
blogc_template_parse(const char *src, size_t src_len, blogc_error_t **err)
{
if (err == NULL || *err != NULL)
@@ -71,7 +71,7 @@ blogc_template_parse(const char *src, size_t src_len, blogc_error_t **err)
unsigned int if_count = 0;
bool foreach_open = false;
- b_slist_t *stmts = NULL;
+ sb_slist_t *stmts = NULL;
blogc_template_stmt_t *stmt = NULL;
/*
@@ -100,21 +100,21 @@ blogc_template_parse(const char *src, size_t src_len, blogc_error_t **err)
case TEMPLATE_START:
if (last) {
- stmt = b_malloc(sizeof(blogc_template_stmt_t));
+ stmt = sb_malloc(sizeof(blogc_template_stmt_t));
stmt->type = type;
if (lstrip_next) {
- tmp = b_strndup(src + start, src_len - start);
- stmt->value = b_strdup(b_str_lstrip(tmp));
+ tmp = sb_strndup(src + start, src_len - start);
+ stmt->value = sb_strdup(sb_str_lstrip(tmp));
free(tmp);
tmp = NULL;
lstrip_next = false;
}
else {
- stmt->value = b_strndup(src + start, src_len - start);
+ stmt->value = sb_strndup(src + start, src_len - start);
}
stmt->op = 0;
stmt->value2 = NULL;
- stmts = b_slist_append(stmts, stmt);
+ stmts = sb_slist_append(stmts, stmt);
previous = stmt;
stmt = NULL;
}
@@ -131,21 +131,21 @@ blogc_template_parse(const char *src, size_t src_len, blogc_error_t **err)
else
state = TEMPLATE_VARIABLE_START;
if (end > start) {
- stmt = b_malloc(sizeof(blogc_template_stmt_t));
+ stmt = sb_malloc(sizeof(blogc_template_stmt_t));
stmt->type = type;
if (lstrip_next) {
- tmp = b_strndup(src + start, end - start);
- stmt->value = b_strdup(b_str_lstrip(tmp));
+ tmp = sb_strndup(src + start, end - start);
+ stmt->value = sb_strdup(sb_str_lstrip(tmp));
free(tmp);
tmp = NULL;
lstrip_next = false;
}
else {
- stmt->value = b_strndup(src + start, end - start);
+ stmt->value = sb_strndup(src + start, end - start);
}
stmt->op = 0;
stmt->value2 = NULL;
- stmts = b_slist_append(stmts, stmt);
+ stmts = sb_slist_append(stmts, stmt);
previous = stmt;
stmt = NULL;
}
@@ -159,7 +159,7 @@ blogc_template_parse(const char *src, size_t src_len, blogc_error_t **err)
if ((previous != NULL) &&
(previous->type == BLOGC_TEMPLATE_CONTENT_STMT))
{
- previous->value = b_str_rstrip(previous->value); // does not need copy
+ previous->value = sb_str_rstrip(previous->value); // does not need copy
}
state = TEMPLATE_BLOCK_START;
break;
@@ -559,19 +559,19 @@ blogc_template_parse(const char *src, size_t src_len, blogc_error_t **err)
op_start = 0;
op_end = 0;
}
- stmt = b_malloc(sizeof(blogc_template_stmt_t));
+ stmt = sb_malloc(sizeof(blogc_template_stmt_t));
stmt->type = type;
stmt->value = NULL;
stmt->op = tmp_op;
stmt->value2 = NULL;
if (end > start)
- stmt->value = b_strndup(src + start, end - start);
+ stmt->value = sb_strndup(src + start, end - start);
if (end2 > start2) {
- stmt->value2 = b_strndup(src + start2, end2 - start2);
+ stmt->value2 = sb_strndup(src + start2, end2 - start2);
start2 = 0;
end2 = 0;
}
- stmts = b_slist_append(stmts, stmt);
+ stmts = sb_slist_append(stmts, stmt);
previous = stmt;
stmt = NULL;
state = TEMPLATE_START;
@@ -622,9 +622,9 @@ blogc_template_parse(const char *src, size_t src_len, blogc_error_t **err)
void
-blogc_template_free_stmts(b_slist_t *stmts)
+blogc_template_free_stmts(sb_slist_t *stmts)
{
- for (b_slist_t *tmp = stmts; tmp != NULL; tmp = tmp->next) {
+ for (sb_slist_t *tmp = stmts; tmp != NULL; tmp = tmp->next) {
blogc_template_stmt_t *data = tmp->data;
if (data == NULL)
continue;
@@ -632,5 +632,5 @@ blogc_template_free_stmts(b_slist_t *stmts)
free(data->value2);
free(data);
}
- b_slist_free(stmts);
+ sb_slist_free(stmts);
}
diff --git a/src/template-parser.h b/src/template-parser.h
index 6cd2c80..a8b4e8b 100644
--- a/src/template-parser.h
+++ b/src/template-parser.h
@@ -9,8 +9,8 @@
#ifndef _TEMPLATE_PARSER_H
#define _TEMPLATE_PARSER_H
-#include "utils/utils.h"
#include "error.h"
+#include "utils.h"
/*
* note: whitespace cleaners are NOT added to ast. we fix strings right during
@@ -44,8 +44,8 @@ typedef struct {
blogc_template_stmt_operator_t op;
} blogc_template_stmt_t;
-b_slist_t* blogc_template_parse(const char *src, size_t src_len,
+sb_slist_t* blogc_template_parse(const char *src, size_t src_len,
blogc_error_t **err);
-void blogc_template_free_stmts(b_slist_t *stmts);
+void blogc_template_free_stmts(sb_slist_t *stmts);
#endif /* _TEMPLATE_GRAMMAR_H */
diff --git a/src/utils.c b/src/utils.c
new file mode 100644
index 0000000..855b503
--- /dev/null
+++ b/src/utils.c
@@ -0,0 +1,612 @@
+/*
+ * blogc: A blog compiler.
+ * Copyright (C) 2014-2016 Rafael G. Martins <rafael@rafaelmartins.eng.br>
+ *
+ * This program can be distributed under the terms of the BSD License.
+ * See the file LICENSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#define SB_STRING_CHUNK_SIZE 128
+
+#include <ctype.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "utils.h"
+
+
+void*
+sb_malloc(size_t size)
+{
+ // simple things simple!
+ void *rv = malloc(size);
+ if (rv == NULL) {
+ fprintf(stderr, "fatal: Failed to allocate memory!\n");
+ abort();
+ }
+ return rv;
+}
+
+
+void*
+sb_realloc(void *ptr, size_t size)
+{
+ // simple things even simpler :P
+ void *rv = realloc(ptr, size);
+ if (rv == NULL && size != 0) {
+ fprintf(stderr, "fatal: Failed to reallocate memory!\n");
+ free(ptr);
+ abort();
+ }
+ return rv;
+}
+
+
+sb_slist_t*
+sb_slist_append(sb_slist_t *l, void *data)
+{
+ sb_slist_t *node = sb_malloc(sizeof(sb_slist_t));
+ node->data = data;
+ node->next = NULL;
+ if (l == NULL) {
+ l = node;
+ }
+ else {
+ sb_slist_t *tmp;
+ for (tmp = l; tmp->next != NULL; tmp = tmp->next);
+ tmp->next = node;
+ }
+ return l;
+}
+
+
+sb_slist_t*
+sb_slist_prepend(sb_slist_t *l, void *data)
+{
+ sb_slist_t *node = sb_malloc(sizeof(sb_slist_t));
+ node->data = data;
+ node->next = l;
+ l = node;
+ return l;
+}
+
+
+void
+sb_slist_free_full(sb_slist_t *l, sb_free_func_t free_func)
+{
+ while (l != NULL) {
+ sb_slist_t *tmp = l->next;
+ if ((free_func != NULL) && (l->data != NULL))
+ free_func(l->data);
+ free(l);
+ l = tmp;
+ }
+}
+
+
+void
+sb_slist_free(sb_slist_t *l)
+{
+ sb_slist_free_full(l, NULL);
+}
+
+
+size_t
+sb_slist_length(sb_slist_t *l)
+{
+ if (l == NULL)
+ return 0;
+ size_t i;
+ sb_slist_t *tmp;
+ for (tmp = l, i = 0; tmp != NULL; tmp = tmp->next, i++);
+ return i;
+}
+
+
+char*
+sb_strdup(const char *s)
+{
+ if (s == NULL)
+ return NULL;
+ size_t l = strlen(s);
+ char *tmp = malloc(l + 1);
+ if (tmp == NULL)
+ return NULL;
+ memcpy(tmp, s, l + 1);
+ return tmp;
+}
+
+
+char*
+sb_strndup(const char *s, size_t n)
+{
+ if (s == NULL)
+ return NULL;
+ size_t l = strnlen(s, n);
+ char *tmp = malloc(l + 1);
+ if (tmp == NULL)
+ return NULL;
+ memcpy(tmp, s, l);
+ tmp[l] = '\0';
+ return tmp;
+}
+
+
+char*
+sb_strdup_vprintf(const char *format, va_list ap)
+{
+ va_list ap2;
+ va_copy(ap2, ap);
+ int l = vsnprintf(NULL, 0, format, ap2);
+ va_end(ap2);
+ if (l < 0)
+ return NULL;
+ char *tmp = malloc(l + 1);
+ if (!tmp)
+ return NULL;
+ int l2 = vsnprintf(tmp, l + 1, format, ap);
+ if (l2 < 0) {
+ free(tmp);
+ return NULL;
+ }
+ return tmp;
+}
+
+
+char*
+sb_strdup_printf(const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ char *tmp = sb_strdup_vprintf(format, ap);
+ va_end(ap);
+ return tmp;
+}
+
+
+bool
+sb_str_starts_with(const char *str, const char *prefix)
+{
+ int str_l = strlen(str);
+ int str_lp = strlen(prefix);
+ if (str_lp > str_l)
+ return false;
+ return strncmp(str, prefix, str_lp) == 0;
+}
+
+
+bool
+sb_str_ends_with(const char *str, const char *suffix)
+{
+ int str_l = strlen(str);
+ int str_ls = strlen(suffix);
+ if (str_ls > str_l)
+ return false;
+ return strcmp(str + str_l - str_ls, suffix) == 0;
+}
+
+
+char*
+sb_str_lstrip(char *str)
+{
+ if (str == NULL)
+ return NULL;
+ int i;
+ size_t str_len = strlen(str);
+ for (i = 0; i < str_len; i++) {
+ if ((str[i] != ' ') && (str[i] != '\t') && (str[i] != '\n') &&
+ (str[i] != '\r') && (str[i] != '\t') && (str[i] != '\f') &&
+ (str[i] != '\v'))
+ {
+ str += i;
+ break;
+ }
+ if (i == str_len - 1) {
+ str += str_len;
+ break;
+ }
+ }
+ return str;
+}
+
+
+char*
+sb_str_rstrip(char *str)
+{
+ if (str == NULL)
+ return NULL;
+ int i;
+ size_t str_len = strlen(str);
+ for (i = str_len - 1; i >= 0; i--) {
+ if ((str[i] != ' ') && (str[i] != '\t') && (str[i] != '\n') &&
+ (str[i] != '\r') && (str[i] != '\t') && (str[i] != '\f') &&
+ (str[i] != '\v'))
+ {
+ str[i + 1] = '\0';
+ break;
+ }
+ if (i == 0) {
+ str[0] = '\0';
+ break;
+ }
+ }
+ return str;
+}
+
+
+char*
+sb_str_strip(char *str)
+{
+ return sb_str_lstrip(sb_str_rstrip(str));
+}
+
+
+char**
+sb_str_split(const char *str, char c, unsigned int max_pieces)
+{
+ if (str == NULL)
+ return NULL;
+ char **rv = sb_malloc(sizeof(char*));
+ unsigned int i, start = 0, count = 0;
+ for (i = 0; i < strlen(str) + 1; i++) {
+ if (str[0] == '\0')
+ break;
+ if ((str[i] == c && (!max_pieces || count + 1 < max_pieces)) || str[i] == '\0') {
+ rv = sb_realloc(rv, (count + 1) * sizeof(char*));
+ rv[count] = sb_malloc(i - start + 1);
+ memcpy(rv[count], str + start, i - start);
+ rv[count++][i - start] = '\0';
+ start = i + 1;
+ }
+ }
+ rv = sb_realloc(rv, (count + 1) * sizeof(char*));
+ rv[count] = NULL;
+ return rv;
+}
+
+
+char*
+sb_str_replace(const char *str, const char search, const char *replace)
+{
+ char **pieces = sb_str_split(str, search, 0);
+ if (pieces == NULL)
+ return NULL;
+ char* rv = sb_strv_join(pieces, replace);
+ sb_strv_free(pieces);
+ if (rv == NULL)
+ return sb_strdup(str);
+ return rv;
+}
+
+
+void
+sb_strv_free(char **strv)
+{
+ if (strv == NULL)
+ return;
+ for (size_t i = 0; strv[i] != NULL; i++)
+ free(strv[i]);
+ free(strv);
+}
+
+
+char*
+sb_strv_join(char **strv, const char *separator)
+{
+ if (strv == NULL || separator == NULL)
+ return NULL;
+ sb_string_t *str = sb_string_new();
+ for (size_t i = 0; strv[i] != NULL; i++) {
+ str = sb_string_append(str, strv[i]);
+ if (strv[i + 1] != NULL)
+ str = sb_string_append(str, separator);
+ }
+ return sb_string_free(str, false);
+}
+
+
+size_t
+sb_strv_length(char **strv)
+{
+ if (strv == NULL)
+ return 0;
+ size_t i;
+ for (i = 0; strv[i] != NULL; i++);
+ return i;
+}
+
+
+sb_string_t*
+sb_string_new(void)
+{
+ sb_string_t* rv = sb_malloc(sizeof(sb_string_t));
+ rv->str = NULL;
+ rv->len = 0;
+ rv->allocated_len = 0;
+
+ // initialize with empty string
+ rv = sb_string_append(rv, "");
+
+ return rv;
+}
+
+
+char*
+sb_string_free(sb_string_t *str, bool free_str)
+{
+ if (str == NULL)
+ return NULL;
+ char *rv = NULL;
+ if (free_str)
+ free(str->str);
+ else
+ rv = str->str;
+ free(str);
+ return rv;
+}
+
+
+sb_string_t*
+sb_string_dup(sb_string_t *str)
+{
+ if (str == NULL)
+ return NULL;
+ sb_string_t* new = sb_string_new();
+ return sb_string_append_len(new, str->str, str->len);
+}
+
+
+sb_string_t*
+sb_string_append_len(sb_string_t *str, const char *suffix, size_t len)
+{
+ if (str == NULL)
+ return NULL;
+ if (suffix == NULL)
+ return str;
+ size_t old_len = str->len;
+ str->len += len;
+ if (str->len + 1 > str->allocated_len) {
+ str->allocated_len = (((str->len + 1) / SB_STRING_CHUNK_SIZE) + 1) * SB_STRING_CHUNK_SIZE;
+ str->str = sb_realloc(str->str, str->allocated_len);
+ }
+ memcpy(str->str + old_len, suffix, len);
+ str->str[str->len] = '\0';
+ return str;
+}
+
+
+sb_string_t*
+sb_string_append(sb_string_t *str, const char *suffix)
+{
+ if (str == NULL)
+ return NULL;
+ const char *my_suffix = suffix == NULL ? "" : suffix;
+ return sb_string_append_len(str, my_suffix, strlen(my_suffix));
+}
+
+
+sb_string_t*
+sb_string_append_c(sb_string_t *str, char c)
+{
+ if (str == NULL)
+ return NULL;
+ size_t old_len = str->len;
+ str->len += 1;
+ if (str->len + 1 > str->allocated_len) {
+ str->allocated_len = (((str->len + 1) / SB_STRING_CHUNK_SIZE) + 1) * SB_STRING_CHUNK_SIZE;
+ str->str = sb_realloc(str->str, str->allocated_len);
+ }
+ str->str[old_len] = c;
+ str->str[str->len] = '\0';
+ return str;
+}
+
+
+sb_string_t*
+sb_string_append_printf(sb_string_t *str, const char *format, ...)
+{
+ if (str == NULL)
+ return NULL;
+ va_list ap;
+ va_start(ap, format);
+ char *tmp = sb_strdup_vprintf(format, ap);
+ va_end(ap);
+ str = sb_string_append(str, tmp);
+ free(tmp);
+ return str;
+}
+
+
+sb_trie_t*
+sb_trie_new(sb_free_func_t free_func)
+{
+ sb_trie_t *trie = sb_malloc(sizeof(sb_trie_t));
+ trie->root = NULL;
+ trie->free_func = free_func;
+ return trie;
+}
+
+
+static void
+sb_trie_free_node(sb_trie_t *trie, sb_trie_node_t *node)
+{
+ if (trie == NULL || node == NULL)
+ return;
+ if (node->data != NULL && trie->free_func != NULL)
+ trie->free_func(node->data);
+ sb_trie_free_node(trie, node->next);
+ sb_trie_free_node(trie, node->child);
+ free(node);
+}
+
+
+void
+sb_trie_free(sb_trie_t *trie)
+{
+ if (trie == NULL)
+ return;
+ sb_trie_free_node(trie, trie->root);
+ free(trie);
+}
+
+
+void
+sb_trie_insert(sb_trie_t *trie, const char *key, void *data)
+{
+ if (trie == NULL || key == NULL || data == NULL)
+ return;
+
+ sb_trie_node_t *parent = NULL;
+ sb_trie_node_t *previous;
+ sb_trie_node_t *current;
+ sb_trie_node_t *tmp;
+
+ while (1) {
+
+ if (trie->root == NULL || (parent != NULL && parent->child == NULL)) {
+ current = sb_malloc(sizeof(sb_trie_node_t));
+ current->key = *key;
+ current->data = NULL;
+ current->next = NULL;
+ current->child = NULL;
+ if (trie->root == NULL)
+ trie->root = current;
+ else
+ parent->child = current;
+ parent = current;
+ goto clean;
+ }
+
+ tmp = parent == NULL ? trie->root : parent->child;
+ previous = NULL;
+
+ while (tmp != NULL && tmp->key != *key) {
+ previous = tmp;
+ tmp = tmp->next;
+ }
+
+ parent = tmp;
+
+ if (previous == NULL || parent != NULL)
+ goto clean;
+
+ current = sb_malloc(sizeof(sb_trie_node_t));
+ current->key = *key;
+ current->data = NULL;
+ current->next = NULL;
+ current->child = NULL;
+ previous->next = current;
+ parent = current;
+
+clean:
+ if (*key == '\0') {
+ if (parent->data != NULL && trie->free_func != NULL)
+ trie->free_func(parent->data);
+ parent->data = data;
+ break;
+ }
+ key++;
+ }
+}
+
+
+void*
+sb_trie_lookup(sb_trie_t *trie, const char *key)
+{
+ if (trie == NULL || trie->root == NULL || key == NULL)
+ return NULL;
+
+ sb_trie_node_t *parent = trie->root;
+ sb_trie_node_t *tmp;
+ while (1) {
+ for (tmp = parent; tmp != NULL; tmp = tmp->next) {
+
+ if (tmp->key == *key) {
+ if (tmp->key == '\0')
+ return tmp->data;
+ parent = tmp->child;
+ break;
+ }
+ }
+ if (tmp == NULL)
+ return NULL;
+
+ if (*key == '\0')
+ break;
+ key++;
+ }
+ return NULL;
+}
+
+
+static void
+sb_trie_size_node(sb_trie_node_t *node, size_t *count)
+{
+ if (node == NULL || count == NULL)
+ return;
+
+ if (node->key == '\0')
+ (*count)++;
+
+ sb_trie_size_node(node->next, count);
+ sb_trie_size_node(node->child, count);
+}
+
+
+size_t
+sb_trie_size(sb_trie_t *trie)
+{
+ if (trie == NULL)
+ return 0;
+
+ size_t count = 0;
+ sb_trie_size_node(trie->root, &count);
+ return count;
+}
+
+
+static void
+sb_trie_foreach_node(sb_trie_node_t *node, sb_string_t *str,
+ sb_trie_foreach_func_t func, void *user_data)
+{
+ if (node == NULL || str == NULL || func == NULL)
+ return;
+
+ if (node->key == '\0') {
+ char *tmp = sb_string_free(str, false);
+ func(tmp, node->data, user_data);
+ free(tmp);
+ }
+
+ if (node->child != NULL) {
+ sb_string_t *child = sb_string_dup(str);
+ child = sb_string_append_c(child, node->key);
+ sb_trie_foreach_node(node->child, child, func, user_data);
+ }
+
+ if (node->next != NULL)
+ sb_trie_foreach_node(node->next, str, func, user_data);
+
+ if (node->child != NULL && node->next == NULL)
+ sb_string_free(str, true);
+}
+
+
+void
+sb_trie_foreach(sb_trie_t *trie, sb_trie_foreach_func_t func,
+ void *user_data)
+{
+ if (trie == NULL || trie->root == NULL || func == NULL)
+ return;
+
+ sb_string_t *str = sb_string_new();
+ sb_trie_foreach_node(trie->root, str, func, user_data);
+}
diff --git a/src/utils.h b/src/utils.h
new file mode 100644
index 0000000..411295a
--- /dev/null
+++ b/src/utils.h
@@ -0,0 +1,102 @@
+/*
+ * blogc: A blog compiler.
+ * Copyright (C) 2014-2016 Rafael G. Martins <rafael@rafaelmartins.eng.br>
+ *
+ * This program can be distributed under the terms of the BSD License.
+ * See the file LICENSE.
+ */
+
+#ifndef _UTILS_H
+#define _UTILS_H
+
+#include <stddef.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdarg.h>
+#include <stdlib.h>
+
+
+// memory
+
+typedef void (*sb_free_func_t) (void *ptr);
+
+void* sb_malloc(size_t size);
+void* sb_realloc(void *ptr, size_t size);
+
+
+// slist
+
+typedef struct _sb_slist_t {
+ struct _sb_slist_t *next;
+ void *data;
+} sb_slist_t;
+
+sb_slist_t* sb_slist_append(sb_slist_t *l, void *data);
+sb_slist_t* sb_slist_prepend(sb_slist_t *l, void *data);
+void sb_slist_free(sb_slist_t *l);
+void sb_slist_free_full(sb_slist_t *l, sb_free_func_t free_func);
+size_t sb_slist_length(sb_slist_t *l);
+
+
+// strfuncs
+
+char* sb_strdup(const char *s);
+char* sb_strndup(const char *s, size_t n);
+char* sb_strdup_vprintf(const char *format, va_list ap);
+char* sb_strdup_printf(const char *format, ...);
+bool sb_str_starts_with(const char *str, const char *prefix);
+bool sb_str_ends_with(const char *str, const char *suffix);
+char* sb_str_lstrip(char *str);
+char* sb_str_rstrip(char *str);
+char* sb_str_strip(char *str);
+char** sb_str_split(const char *str, char c, unsigned int max_pieces);
+char* sb_str_replace(const char *str, const char search, const char *replace);
+void sb_strv_free(char **strv);
+char* sb_strv_join(char **strv, const char *separator);
+size_t sb_strv_length(char **strv);
+
+
+// string
+
+typedef struct {
+ char *str;
+ size_t len;
+ size_t allocated_len;
+} sb_string_t;
+
+sb_string_t* sb_string_new(void);
+char* sb_string_free(sb_string_t *str, bool free_str);
+sb_string_t* sb_string_dup(sb_string_t *str);
+sb_string_t* sb_string_append_len(sb_string_t *str, const char *suffix, size_t len);
+sb_string_t* sb_string_append(sb_string_t *str, const char *suffix);
+sb_string_t* sb_string_append_c(sb_string_t *str, char c);
+sb_string_t* sb_string_append_printf(sb_string_t *str, const char *format, ...);
+
+
+// trie
+
+typedef struct _sb_trie_node_t {
+ char key;
+ void *data;
+ struct _sb_trie_node_t *next, *child;
+} sb_trie_node_t;
+
+struct _sb_trie_t {
+ sb_trie_node_t *root;
+ sb_free_func_t free_func;
+};
+
+typedef struct _sb_trie_t sb_trie_t;
+
+typedef void (*sb_trie_foreach_func_t)(const char *key, void *data,
+ void *user_data);
+
+sb_trie_t* sb_trie_new(sb_free_func_t free_func);
+void sb_trie_free(sb_trie_t *trie);
+void sb_trie_insert(sb_trie_t *trie, const char *key, void *data);
+void* sb_trie_lookup(sb_trie_t *trie, const char *key);
+size_t sb_trie_size(sb_trie_t *trie);
+void sb_trie_foreach(sb_trie_t *trie, sb_trie_foreach_func_t func,
+ void *user_data);
+
+#endif /* _UTILS_H */
diff --git a/src/utils/mem.c b/src/utils/mem.c
deleted file mode 100644
index 693d555..0000000
--- a/src/utils/mem.c
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2016 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include "utils.h"
-
-
-void*
-b_malloc(size_t size)
-{
- // simple things simple!
- void *rv = malloc(size);
- if (rv == NULL) {
- fprintf(stderr, "fatal error: Failed to allocate memory!\n");
- exit(1);
- }
- return rv;
-}
-
-
-void*
-b_realloc(void *ptr, size_t size)
-{
- // simple things even simpler :P
- void *rv = realloc(ptr, size);
- if (rv == NULL && size != 0) {
- fprintf(stderr, "fatal error: Failed to reallocate memory!\n");
- free(ptr);
- exit(1);
- }
- return rv;
-}
diff --git a/src/utils/slist.c b/src/utils/slist.c
deleted file mode 100644
index 9753aa7..0000000
--- a/src/utils/slist.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2016 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <stdlib.h>
-#include "utils.h"
-
-
-b_slist_t*
-b_slist_append(b_slist_t *l, void *data)
-{
- b_slist_t *node = malloc(sizeof(b_slist_t));
- if (node == NULL) {
- l = NULL;
- return l;
- }
- node->data = data;
- node->next = NULL;
- if (l == NULL)
- l = node;
- else {
- b_slist_t *tmp;
- for (tmp = l; tmp->next != NULL; tmp = tmp->next);
- tmp->next = node;
- }
- return l;
-}
-
-
-void
-b_slist_free_full(b_slist_t *l, b_free_func_t free_func)
-{
- while (l != NULL) {
- b_slist_t *tmp = l->next;
- free_func(l->data);
- free(l);
- l = tmp;
- }
-}
-
-
-void
-b_slist_free(b_slist_t *l)
-{
- while (l != NULL) {
- b_slist_t *tmp = l->next;
- free(l);
- l = tmp;
- }
-}
-
-
-unsigned int
-b_slist_length(b_slist_t *l)
-{
- unsigned int i;
- b_slist_t *tmp;
- for (tmp = l, i = 0; tmp != NULL; tmp = tmp->next, i++);
- return i;
-}
diff --git a/src/utils/strings.c b/src/utils/strings.c
deleted file mode 100644
index 3151612..0000000
--- a/src/utils/strings.c
+++ /dev/null
@@ -1,314 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2016 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <ctype.h>
-#include <string.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "utils.h"
-
-
-char*
-b_strdup(const char *s)
-{
- if (s == NULL)
- return NULL;
- size_t l = strlen(s);
- char *tmp = malloc(l + 1);
- if (tmp == NULL)
- return NULL;
- memcpy(tmp, s, l + 1);
- return tmp;
-}
-
-
-char*
-b_strndup(const char *s, size_t n)
-{
- if (s == NULL)
- return NULL;
- size_t l = strnlen(s, n);
- char *tmp = malloc(l + 1);
- if (tmp == NULL)
- return NULL;
- memcpy(tmp, s, l);
- tmp[l] = '\0';
- return tmp;
-}
-
-
-char*
-b_strdup_vprintf(const char *format, va_list ap)
-{
- va_list ap2;
- va_copy(ap2, ap);
- int l = vsnprintf(NULL, 0, format, ap2);
- va_end(ap2);
- if (l < 0)
- return NULL;
- char *tmp = malloc(l + 1);
- if (!tmp)
- return NULL;
- int l2 = vsnprintf(tmp, l + 1, format, ap);
- if (l2 < 0) {
- free(tmp);
- return NULL;
- }
- return tmp;
-}
-
-
-char*
-b_strdup_printf(const char *format, ...)
-{
- va_list ap;
- va_start(ap, format);
- char *tmp = b_strdup_vprintf(format, ap);
- va_end(ap);
- return tmp;
-}
-
-
-bool
-b_str_starts_with(const char *str, const char *prefix)
-{
- int str_l = strlen(str);
- int str_lp = strlen(prefix);
- if (str_lp > str_l)
- return false;
- return strncmp(str, prefix, str_lp) == 0;
-}
-
-
-bool
-b_str_ends_with(const char *str, const char *suffix)
-{
- int str_l = strlen(str);
- int str_ls = strlen(suffix);
- if (str_ls > str_l)
- return false;
- return strcmp(str + str_l - str_ls, suffix) == 0;
-}
-
-
-char*
-b_str_lstrip(char *str)
-{
- if (str == NULL)
- return NULL;
- int i;
- size_t str_len = strlen(str);
- for (i = 0; i < str_len; i++) {
- if ((str[i] != ' ') && (str[i] != '\t') && (str[i] != '\n') &&
- (str[i] != '\r') && (str[i] != '\t') && (str[i] != '\f') &&
- (str[i] != '\v'))
- {
- str += i;
- break;
- }
- if (i == str_len - 1) {
- str += str_len;
- break;
- }
- }
- return str;
-}
-
-
-char*
-b_str_rstrip(char *str)
-{
- if (str == NULL)
- return NULL;
- int i;
- size_t str_len = strlen(str);
- for (i = str_len - 1; i >= 0; i--) {
- if ((str[i] != ' ') && (str[i] != '\t') && (str[i] != '\n') &&
- (str[i] != '\r') && (str[i] != '\t') && (str[i] != '\f') &&
- (str[i] != '\v'))
- {
- str[i + 1] = '\0';
- break;
- }
- if (i == 0) {
- str[0] = '\0';
- break;
- }
- }
- return str;
-}
-
-
-char*
-b_str_strip(char *str)
-{
- return b_str_lstrip(b_str_rstrip(str));
-}
-
-
-char**
-b_str_split(const char *str, char c, unsigned int max_pieces)
-{
- if (!str)
- return NULL;
- char **rv = b_malloc(sizeof(char*));
- unsigned int i, start = 0, count = 0;
- for (i = 0; i < strlen(str) + 1; i++) {
- if (str[0] == '\0')
- break;
- if ((str[i] == c && (!max_pieces || count + 1 < max_pieces)) || str[i] == '\0') {
- rv = b_realloc(rv, (count + 1) * sizeof(char*));
- rv[count] = b_malloc(i - start + 1);
- memcpy(rv[count], str + start, i - start);
- rv[count++][i - start] = '\0';
- start = i + 1;
- }
- }
- rv = b_realloc(rv, (count + 1) * sizeof(char*));
- rv[count] = NULL;
- return rv;
-}
-
-
-char*
-b_str_replace(const char *str, const char search, const char *replace)
-{
- char **pieces = b_str_split(str, search, 0);
- if (pieces == NULL)
- return NULL;
- char* rv = b_strv_join((const char**) pieces, replace);
- b_strv_free(pieces);
- return rv;
-}
-
-
-void
-b_strv_free(char **strv)
-{
- if (strv == NULL)
- return;
- unsigned int i;
- for (i = 0; strv[i] != NULL; i++)
- free(strv[i]);
- free(strv);
-}
-
-
-char*
-b_strv_join(const char **strv, const char *separator)
-{
- if (strv == NULL)
- return NULL;
- unsigned int i = 0;
- b_string_t *str = b_string_new();
- for (i = 0; strv[i] != NULL; i++) {
- str = b_string_append(str, strv[i]);
- if (strv[i+1] != NULL)
- str = b_string_append(str, separator);
- }
- return b_string_free(str, false);
-}
-
-
-unsigned int
-b_strv_length(char **strv)
-{
- if (!strv)
- return 0;
- unsigned int i;
- for (i = 0; strv[i] != NULL; i++);
- return i;
-}
-
-
-b_string_t*
-b_string_new(void)
-{
- b_string_t* rv = b_malloc(sizeof(b_string_t));
- rv->str = NULL;
- rv->len = 0;
- rv->allocated_len = 0;
-
- // initialize with empty string
- rv = b_string_append(rv, "");
-
- return rv;
-}
-
-
-char*
-b_string_free(b_string_t *str, bool free_str)
-{
- char *rv = NULL;
- if (free_str)
- free(str->str);
- else
- rv = str->str;
- free(str);
- return rv;
-}
-
-
-b_string_t*
-b_string_append_len(b_string_t *str, const char *suffix, size_t len)
-{
- if (suffix == NULL)
- return str;
- size_t old_len = str->len;
- str->len += len;
- if (str->len + 1 > str->allocated_len) {
- str->allocated_len = (((str->len + 1) / B_STRING_CHUNK_SIZE) + 1) * B_STRING_CHUNK_SIZE;
- str->str = b_realloc(str->str, str->allocated_len);
- }
- memcpy(str->str + old_len, suffix, len);
- str->str[str->len] = '\0';
- return str;
-}
-
-
-b_string_t*
-b_string_append(b_string_t *str, const char *suffix)
-{
- if (suffix == NULL)
- return str;
- return b_string_append_len(str, suffix, strlen(suffix));
-}
-
-
-b_string_t*
-b_string_append_c(b_string_t *str, char c)
-{
- size_t old_len = str->len;
- str->len += 1;
- if (str->len + 1 > str->allocated_len) {
- str->allocated_len = (((str->len + 1) / B_STRING_CHUNK_SIZE) + 1) * B_STRING_CHUNK_SIZE;
- str->str = b_realloc(str->str, str->allocated_len);
- }
- str->str[old_len] = c;
- str->str[str->len] = '\0';
- return str;
-}
-
-
-b_string_t*
-b_string_append_printf(b_string_t *str, const char *format, ...)
-{
- va_list ap;
- va_start(ap, format);
- char *tmp = b_strdup_vprintf(format, ap);
- va_end(ap);
- str = b_string_append(str, tmp);
- free(tmp);
- return str;
-}
diff --git a/src/utils/trie.c b/src/utils/trie.c
deleted file mode 100644
index 2e6a0d8..0000000
--- a/src/utils/trie.c
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2016 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <stdlib.h>
-#include "utils.h"
-
-
-b_trie_t*
-b_trie_new(b_free_func_t free_func)
-{
- b_trie_t *trie = b_malloc(sizeof(b_trie_t));
- trie->root = NULL;
- trie->free_func = free_func;
- return trie;
-}
-
-
-static void
-b_trie_free_node(b_trie_t *trie, b_trie_node_t *node)
-{
- if (node == NULL)
- return;
- if (node->data != NULL && trie->free_func != NULL)
- trie->free_func(node->data);
- b_trie_free_node(trie, node->next);
- b_trie_free_node(trie, node->child);
- free(node);
-}
-
-
-void
-b_trie_free(b_trie_t *trie)
-{
- if (trie == NULL)
- return;
- b_trie_free_node(trie, trie->root);
- free(trie);
-}
-
-
-void
-b_trie_insert(b_trie_t *trie, const char *key, void *data)
-{
- if (data == NULL || key == NULL)
- return;
-
- b_trie_node_t *parent = NULL;
- b_trie_node_t *previous;
- b_trie_node_t *current;
- b_trie_node_t *tmp;
-
- while (1) {
-
- if (trie->root == NULL || (parent != NULL && parent->child == NULL)) {
- current = b_malloc(sizeof(b_trie_node_t));
- current->key = *key;
- current->data = NULL;
- current->next = NULL;
- current->child = NULL;
- if (trie->root == NULL)
- trie->root = current;
- else
- parent->child = current;
- parent = current;
- goto clean;
- }
-
- tmp = parent == NULL ? trie->root : parent->child;
- previous = NULL;
-
- while (tmp != NULL && tmp->key != *key) {
- previous = tmp;
- tmp = tmp->next;
- }
-
- parent = tmp;
-
- if (previous == NULL || parent != NULL)
- goto clean;
-
- current = b_malloc(sizeof(b_trie_node_t));
- current->key = *key;
- current->data = NULL;
- current->next = NULL;
- current->child = NULL;
- previous->next = current;
- parent = current;
-
-clean:
- if (*key == '\0') {
- if (parent->data != NULL && trie->free_func != NULL)
- trie->free_func(parent->data);
- parent->data = data;
- break;
- }
- key++;
- }
-}
-
-
-void*
-b_trie_lookup(b_trie_t *trie, const char *key)
-{
- if (trie == NULL || trie->root == NULL || key == NULL)
- return NULL;
-
- b_trie_node_t *parent = trie->root;
- b_trie_node_t *tmp;
- while (1) {
- for (tmp = parent; tmp != NULL; tmp = tmp->next) {
-
- if (tmp->key == *key) {
- if (tmp->key == '\0')
- return tmp->data;
- parent = tmp->child;
- break;
- }
- }
- if (tmp == NULL)
- return NULL;
-
- if (*key == '\0')
- break;
- key++;
- }
- return NULL;
-}
-
-
-static void
-b_trie_size_node(b_trie_node_t *node, unsigned int *count)
-{
- if (node == NULL)
- return;
-
- if (node->key == '\0')
- (*count)++;
-
- b_trie_size_node(node->next, count);
- b_trie_size_node(node->child, count);
-}
-
-
-unsigned int
-b_trie_size(b_trie_t *trie)
-{
- if (trie == NULL)
- return 0;
-
- unsigned int count = 0;
- b_trie_size_node(trie->root, &count);
- return count;
-}
-
-
-static void
-b_trie_foreach_node(b_trie_node_t *node, b_string_t *str, void (*func)(const char *key, void *data))
-{
- if (node == NULL)
- return;
-
- if (node->key == '\0') {
- func(str->str, node->data);
- b_string_free(str, true);
- }
-
- if (node->child != NULL) {
- b_string_t *child = b_string_new();
- child = b_string_append(child, str->str);
- child = b_string_append_c(child, node->key);
- b_trie_foreach_node(node->child, child, func);
- }
-
- if (node->next != NULL)
- b_trie_foreach_node(node->next, str, func);
-
- if (node->child != NULL && node->next == NULL)
- b_string_free(str, true);
-}
-
-
-void
-b_trie_foreach(b_trie_t *trie, void (*func)(const char *key, void *data))
-{
- if (trie->root == NULL)
- return;
-
- b_string_t *str = b_string_new();
- b_trie_foreach_node(trie->root, str, func);
-}
diff --git a/src/utils/utils.h b/src/utils/utils.h
deleted file mode 100644
index dc67497..0000000
--- a/src/utils/utils.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2016 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#ifndef _UTILS_UTILS_H
-#define _UTILS_UTILS_H
-
-#include <stdbool.h>
-#include <stdlib.h>
-#include <stdarg.h>
-
-#define B_STRING_CHUNK_SIZE 128
-
-typedef void (*b_free_func_t) (void *ptr);
-
-typedef struct _b_slist_t {
- struct _b_slist_t *next;
- void *data;
-} b_slist_t;
-
-typedef struct _b_string_t {
- char *str;
- size_t len;
- size_t allocated_len;
-} b_string_t;
-
-typedef struct _b_trie_node_t {
- char key;
- void *data;
- struct _b_trie_node_t *next, *child;
-} b_trie_node_t;
-
-typedef struct _b_trie_t {
- b_trie_node_t *root;
- b_free_func_t free_func;
-} b_trie_t;
-
-b_slist_t* b_slist_append(b_slist_t *l, void *data);
-void b_slist_free_full(b_slist_t *l, b_free_func_t free_func);
-void b_slist_free(b_slist_t *l);
-unsigned int b_slist_length(b_slist_t *l);
-
-char* b_strdup(const char *s);
-char* b_strndup(const char *s, size_t n);
-char* b_strdup_vprintf(const char *format, va_list ap);
-char* b_strdup_printf(const char *format, ...);
-bool b_str_starts_with(const char *str, const char *prefix);
-bool b_str_ends_with(const char *str, const char *suffix);
-char* b_str_lstrip(char *str);
-char* b_str_rstrip(char *str);
-char* b_str_strip(char *str);
-char** b_str_split(const char *str, char c, unsigned int max_pieces);
-char* b_str_replace(const char *str, const char search, const char *replace);
-void b_strv_free(char **strv);
-char* b_strv_join(const char **strv, const char *separator);
-unsigned int b_strv_length(char **strv);
-
-b_string_t* b_string_new(void);
-char* b_string_free(b_string_t *str, bool free_str);
-b_string_t* b_string_append_len(b_string_t *str, const char *suffix, size_t len);
-b_string_t* b_string_append(b_string_t *str, const char *suffix);
-b_string_t* b_string_append_c(b_string_t *str, char c);
-b_string_t* b_string_append_printf(b_string_t *str, const char *format, ...);
-
-b_trie_t* b_trie_new(b_free_func_t free_func);
-void b_trie_free(b_trie_t *trie);
-void b_trie_insert(b_trie_t *trie, const char *key, void *data);
-void* b_trie_lookup(b_trie_t *trie, const char *key);
-unsigned int b_trie_size(b_trie_t *trie);
-void b_trie_foreach(b_trie_t *trie, void (*func)(const char *key, void *data));
-
-void* b_malloc(size_t size);
-void* b_realloc(void *ptr, size_t size);
-
-#endif /* _UTILS_UTILS_H */