summaryrefslogtreecommitdiff
path: root/src/block-parser.c
diff options
context:
space:
mode:
authorTomas Bzatek <tbzatek@users.sourceforge.net>2011-06-04 17:30:12 +0200
committerTomas Bzatek <tbzatek@users.sourceforge.net>2011-06-04 17:30:12 +0200
commitfb5a52884dd17d17bab47de7f53c17c05ced6e1b (patch)
treefdb3873d295b615bfb1689c54fb76e3abb4e273f /src/block-parser.c
parent960c477148cf832f79e89a4cdf9f3ce3389c7b06 (diff)
downloadcataract-fb5a52884dd17d17bab47de7f53c17c05ced6e1b.tar.xz
Introduce conditional system
This is very basic scripting support - simple value retrieval and block conditionals. Defines could be either static from theme setup or programatically added during page generation.
Diffstat (limited to 'src/block-parser.c')
-rw-r--r--src/block-parser.c133
1 files changed, 114 insertions, 19 deletions
diff --git a/src/block-parser.c b/src/block-parser.c
index d4fcccb..cfe9047 100644
--- a/src/block-parser.c
+++ b/src/block-parser.c
@@ -23,7 +23,6 @@
#include <unistd.h>
#include <glib.h>
-#include <glib/gprintf.h>
#include "block-parser.h"
#include "gallery-utils.h"
@@ -38,6 +37,8 @@ struct BlockParser {
GHashTable *table;
GQueue *active_tree;
gchar *current_line;
+ GHashTable *conditionals;
+ guint ignore_level;
};
typedef struct {
@@ -45,6 +46,10 @@ typedef struct {
gchar *data;
gboolean used;
gboolean finished;
+
+ gboolean is_conditional;
+ gchar *conditional_key;
+ gboolean should_ignore;
} BlockData;
@@ -59,6 +64,7 @@ block_parser_destroy_notify (gpointer data)
g_free (d->replace_key);
g_free (d->data);
+ g_free (d->conditional_key);
g_free (d);
}
@@ -84,6 +90,17 @@ block_parser_free (BlockParser *parser)
g_free (parser);
}
+/*
+ * block_parser_set_conditionals: set a hash table to be used for conditionals lookup
+ *
+ */
+void
+block_parser_set_conditionals (BlockParser *parser, GHashTable *conditionals)
+{
+ g_return_if_fail (parser != NULL);
+
+ parser->conditionals = conditionals;
+}
/*
* block_parser_register_key: tell parser to expect the key to catch
@@ -103,10 +120,10 @@ block_parser_register_key (BlockParser *parser, const gchar *key, const gchar *r
if (replace_key)
data->replace_key = g_strdup_printf ("<!-- $(%s) -->", replace_key);
data->used = TRUE; /* buffer is empty, mask it for block_parser_has_unused_data() */
+ data->is_conditional = FALSE;
g_hash_table_replace (parser->table, g_strdup (key), data);
}
-
/*
* block_parser_get_data: return retrieved data or NULL if none read yet
* returns newly allocated string, caller is responsible for freeing
@@ -174,8 +191,18 @@ push_string (BlockParser *parser, const gchar *piece)
{
BlockData *data;
gchar *s;
+ guint i;
- data = g_queue_peek_head (parser->active_tree);
+ /* Test if the data should be ignored */
+ if (parser->ignore_level > 0)
+ return;
+
+ /* Not ignoring, find first non-conditional record */
+ for (i = 0; (data = g_queue_peek_nth (parser->active_tree, i)) != NULL; i++)
+ if (! data->is_conditional)
+ break;
+
+ /* Actually push the string */
if (data) {
if (data->data)
s = g_strdup_printf ("%s%s", data->data, piece);
@@ -192,6 +219,25 @@ push_string (BlockParser *parser, const gchar *piece)
}
}
+static gchar *
+extract_arg (const gchar *str)
+{
+ const gchar *start;
+ const gchar *end;
+
+ start = strstr (str, "(");
+ if (start == NULL)
+ return NULL;
+ start++;
+
+ end = strstr (str, ")");
+ if (end == NULL)
+ return NULL;
+ end++;
+
+ return g_strndup (start, end - start - 1);
+}
+
/*
* block_parser_read_and_parse: reads input from the file and returns parsed line
* - if there's a multiline block, string before the opening placeholder and
@@ -210,8 +256,8 @@ block_parser_read_and_parse (BlockParser *parser, FILE *stream)
gchar *token;
gchar *start, *end;
gchar *s;
- GList *keys;
- GList *l;
+ GHashTableIter iter;
+ gchar *key;
BlockData *data;
gboolean handled;
@@ -224,8 +270,6 @@ block_parser_read_and_parse (BlockParser *parser, FILE *stream)
}
parser->current_line = g_strdup ("");
- keys = g_hash_table_get_keys (parser->table);
-
/* find tokens */
b = buffer;
while ((token = get_next_token (b, &start, &end, NULL))) {
@@ -236,25 +280,77 @@ block_parser_read_and_parse (BlockParser *parser, FILE *stream)
push_string (parser, s);
g_free (s);
+ /* match conditionals */
+ if (parser->conditionals && (g_str_has_prefix (token, "ifdef(") || g_str_has_prefix (token, "ifndef("))) {
+ data = g_new0 (BlockData, 1);
+ data->is_conditional = TRUE;
+ data->conditional_key = extract_arg (token);
+ data->should_ignore = ((g_str_has_prefix (token, "ifdef(") && g_hash_table_lookup (parser->conditionals, data->conditional_key) == NULL) ||
+ (g_str_has_prefix (token, "ifndef(") && g_hash_table_lookup (parser->conditionals, data->conditional_key) != NULL));
+ if (data->should_ignore && parser->ignore_level == 0)
+ parser->ignore_level = 1;
+ else
+ if (parser->ignore_level > 0)
+ parser->ignore_level++;
+ g_queue_push_head (parser->active_tree, data);
+ handled = TRUE;
+ }
+
+ if (parser->conditionals && g_str_has_prefix (token, "endif(")) {
+ s = extract_arg (token);
+ data = g_queue_peek_head (parser->active_tree);
+ if (data == NULL || !data->is_conditional || strcmp (data->conditional_key, s) != 0) {
+ log_error ("block_parser_read_and_parse: something is wrong with the parser table: expected '%s' but got '%s'\n", s, data->conditional_key);
+ }
+ else {
+ g_queue_pop_head (parser->active_tree);
+ if (parser->ignore_level > 0)
+ parser->ignore_level--;
+ block_parser_destroy_notify (data);
+ handled = TRUE;
+ }
+ g_free (s);
+ }
+
+ if (parser->conditionals && g_str_has_prefix (token, "else(")) {
+ s = extract_arg (token);
+ data = g_queue_peek_head (parser->active_tree);
+ if (data == NULL || !data->is_conditional || strcmp (data->conditional_key, s) != 0) {
+ log_error ("block_parser_read_and_parse: something is wrong with the parser table: expected '%s' but got '%s'\n", s, data->conditional_key);
+ }
+ else {
+ data->should_ignore = ! data->should_ignore;
+ /* if we're not ignoring, level is zero, let's start ignoring by setting to one */
+ if (data->should_ignore && parser->ignore_level == 0)
+ parser->ignore_level = 1;
+ else
+ /* if we're ignoring but should not, let's go down to zero */
+ if (! data->should_ignore && parser->ignore_level == 1)
+ parser->ignore_level = 0;
+ /* in all other cases (level > 1) we're ignoring already and we're not the topmost block, so let's keep being ignored */
+ handled = TRUE;
+ }
+ g_free (s);
+ }
+
/* match known tags */
- for (l = keys; l != NULL; l = l->next) {
+ g_hash_table_iter_init (&iter, parser->table);
+ while (!handled && g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &data)) {
/* test BEGIN_ tokens */
- s = g_strdup_printf ("BEGIN_%s", (gchar *) l->data);
- if (strcmp (s, token) == 0) {
- data = g_hash_table_lookup (parser->table, (gchar *) l->data);
- if (data) {
- g_queue_push_head (parser->active_tree, data);
- handled = TRUE;
- }
+ s = g_strdup_printf ("BEGIN_%s", key);
+ if (strcmp (s, token) == 0 && data) {
+ g_queue_push_head (parser->active_tree, data);
+ handled = TRUE;
}
g_free (s);
+ if (handled)
+ break;
/* test END_ tokens */
- s = g_strdup_printf ("END_%s", (gchar *) l->data);
+ s = g_strdup_printf ("END_%s", key);
if (strcmp (s, token) == 0) {
- data = g_hash_table_lookup (parser->table, (gchar *) l->data);
if (data == NULL || data != g_queue_peek_head (parser->active_tree)) {
- log_error ("block_parser_read_and_parse: something is wrong with the parser table: expected '%s'\n", (gchar *) l->data);
+ log_error ("block_parser_read_and_parse: something is wrong with the parser table: expected '%s'\n", key);
}
else {
g_queue_pop_head (parser->active_tree);
@@ -282,7 +378,6 @@ block_parser_read_and_parse (BlockParser *parser, FILE *stream)
/* push rest of the buffer till the end of the line */
push_string (parser, b);
- g_list_free (keys);
g_free (buffer);
return parser->current_line;
}