summaryrefslogtreecommitdiff
path: root/dpip/dpip.c
diff options
context:
space:
mode:
authorjcid <devnull@localhost>2007-10-07 00:36:34 +0200
committerjcid <devnull@localhost>2007-10-07 00:36:34 +0200
commit93715c46a99c96d6c866968312691ec9ab0f6a03 (patch)
tree573f19ec6aa740844f53a7c0eb7114f04096bf64 /dpip/dpip.c
Initial revision
Diffstat (limited to 'dpip/dpip.c')
-rw-r--r--dpip/dpip.c168
1 files changed, 168 insertions, 0 deletions
diff --git a/dpip/dpip.c b/dpip/dpip.c
new file mode 100644
index 00000000..846f61b0
--- /dev/null
+++ b/dpip/dpip.c
@@ -0,0 +1,168 @@
+/*
+ * File: dpip.c
+ *
+ * Copyright 2005 Jorge Arellano Cid <jcid@dillo.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "../dlib/dlib.h"
+#include "dpip.h"
+#include "d_size.h"
+
+static char Quote = '\'';
+
+/*
+ * Basically the syntax of a dpip tag is:
+ *
+ * "<"[*alpha] *(<name>"="Quote<escaped_value>Quote) " "Quote">"
+ *
+ * 1.- No space is allowed around the "=" sign between a name and its value.
+ * 2.- The Quote character is not allowed in <name>.
+ * 3.- Attribute values stuff Quote as QuoteQuote.
+ *
+ * e.g. (with ' as Quote):
+ *
+ * <a='b' b='c' '> OK
+ * <dpi a='b i' b='12' '> OK
+ * <a='>' '> OK
+ * <a='ain''t no doubt' '> OK
+ * <a='ain''t b=''no'' b='' doubt' '> OK
+ * <a = '>' '> Wrong
+ *
+ * Notes:
+ *
+ * Restriction #1 is for easy finding of end of tag (EOT=Space+Quote+>).
+ * Restriction #2 can be removed, but what for? ;)
+ * The functions here provide for this functionality.
+ */
+
+typedef enum {
+ SEEK_NAME,
+ MATCH_NAME,
+ SKIP_VALUE,
+ SKIP_QUOTE,
+ FOUND
+} DpipTagParsingState;
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * Printf like function for building dpip commands.
+ * It takes care of dpip escaping of its arguments.
+ * NOTE : It ONLY accepts string parameters, and
+ * only one %s per parameter.
+ */
+char *a_Dpip_build_cmd(const char *format, ...)
+{
+ va_list argp;
+ char *p, *q, *s;
+ Dstr *cmd;
+
+ /* Don't allow Quote characters in attribute names */
+ if (strchr(format, Quote))
+ return NULL;
+
+ cmd = dStr_sized_new(64);
+ dStr_append_c(cmd, '<');
+ va_start(argp, format);
+ for (p = q = (char*)format; *q; ) {
+ p = strstr(q, "%s");
+ if (!p) {
+ dStr_append(cmd, q);
+ break;
+ } else {
+ /* Copy format's part */
+ while (q != p)
+ dStr_append_c(cmd, *q++);
+ q += 2;
+
+ dStr_append_c(cmd, Quote);
+ /* Stuff-copy of argument */
+ s = va_arg (argp, char *);
+ for ( ; *s; ++s) {
+ dStr_append_c(cmd, *s);
+ if (*s == Quote)
+ dStr_append_c(cmd, *s);
+ }
+ dStr_append_c(cmd, Quote);
+ }
+ }
+ va_end(argp);
+ dStr_append_c(cmd, ' ');
+ dStr_append_c(cmd, Quote);
+ dStr_append_c(cmd, '>');
+
+ p = cmd->str;
+ dStr_free(cmd, FALSE);
+ return p;
+}
+
+/*
+ * Task: given a tag and an attribute name, return its value.
+ * (stuffing of ' is removed here)
+ * Return value: the attribute value, or NULL if not present or malformed.
+ */
+char *a_Dpip_get_attr(char *tag, size_t tagsize, char *attrname)
+{
+ uint_t i, n = 0, found = 0;
+ char *p, *q, *start, *val = NULL;
+ DpipTagParsingState state = SEEK_NAME;
+
+ if (!attrname || !*attrname)
+ return NULL;
+
+ for (i = 1; i < tagsize && !found; ++i) {
+ switch (state) {
+ case SEEK_NAME:
+ if (tag[i] == attrname[0] && (tag[i-1] == ' ' || tag[i-1] == '<')) {
+ n = 1;
+ state = MATCH_NAME;
+ } else if (tag[i] == Quote && tag[i-1] == '=')
+ state = SKIP_VALUE;
+ break;
+ case MATCH_NAME:
+ if (tag[i] == attrname[n])
+ ++n;
+ else if (tag[i] == '=' && !attrname[n])
+ state = FOUND;
+ else
+ state = SEEK_NAME;
+ break;
+ case SKIP_VALUE:
+ if (tag[i] == Quote)
+ state = (tag[i+1] == Quote) ? SKIP_QUOTE : SEEK_NAME;
+ break;
+ case SKIP_QUOTE:
+ state = SKIP_VALUE;
+ break;
+ case FOUND:
+ found = 1;
+ break;
+ }
+ }
+
+ if (found) {
+ p = start = tag + i;
+ while ((q = strchr(p, Quote)) && q[1] == Quote)
+ p = q + 2;
+ if (q && q[1] == ' ') {
+ val = dStrndup(start, (uint_t)(q - start));
+ for (p = q = val; (*q = *p); ++p, ++q)
+ if (*p == Quote && p[1] == p[0])
+ ++p;
+ }
+ }
+ return val;
+}
+
+/* ------------------------------------------------------------------------- */
+