aboutsummaryrefslogtreecommitdiffstats
path: root/parsetagx.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--parsetagx.c296
1 files changed, 296 insertions, 0 deletions
diff --git a/parsetagx.c b/parsetagx.c
new file mode 100644
index 0000000..6bcc787
--- /dev/null
+++ b/parsetagx.c
@@ -0,0 +1,296 @@
+/* $Id: parsetagx.c,v 1.14 2003/02/05 16:44:00 ukai Exp $ */
+#include "fm.h"
+#include "myctype.h"
+#include "indep.h"
+#include "Str.h"
+#include "parsetagx.h"
+#include "hash.h"
+
+#include "html.c"
+
+/* parse HTML tag */
+
+static int noConv(char *, char **);
+static int toNumber(char *, int *);
+static int toLength(char *, int *);
+static int toAlign(char *, int *);
+static int toVAlign(char *, int *);
+
+/* *INDENT-OFF* */
+static int (*toValFunc[]) () = {
+ noConv, /* VTYPE_NONE */
+ noConv, /* VTYPE_STR */
+ toNumber, /* VTYPE_NUMBER */
+ toLength, /* VTYPE_LENGTH */
+ toAlign, /* VTYPE_ALIGN */
+ toVAlign, /* VTYPE_VALIGN */
+ noConv, /* VTYPE_ACTION */
+ noConv, /* VTYPE_ENCTYPE */
+ noConv, /* VTYPE_METHOD */
+ noConv, /* VTYPE_MLENGTH */
+ noConv, /* VTYPE_TYPE */
+};
+/* *INDENT-ON* */
+
+static int
+noConv(char *oval, char **str)
+{
+ *str = oval;
+ return 1;
+}
+
+static int
+toNumber(char *oval, int *num)
+{
+ char *ep;
+ int x;
+
+ x = strtol(oval, &ep, 10);
+
+ if (ep > oval) {
+ *num = x;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+static int
+toLength(char *oval, int *len)
+{
+ int w;
+ if (!IS_DIGIT(oval[0]))
+ return 0;
+ w = atoi(oval);
+ if (w < 0)
+ return 0;
+ if (w == 0)
+ w = 1;
+ if (oval[strlen(oval) - 1] == '%')
+ *len = -w;
+ else
+ *len = w;
+ return 1;
+}
+
+static int
+toAlign(char *oval, int *align)
+{
+ if (strcasecmp(oval, "left") == 0)
+ *align = ALIGN_LEFT;
+ else if (strcasecmp(oval, "right") == 0)
+ *align = ALIGN_RIGHT;
+ else if (strcasecmp(oval, "center") == 0)
+ *align = ALIGN_CENTER;
+ else if (strcasecmp(oval, "top") == 0)
+ *align = ALIGN_TOP;
+ else if (strcasecmp(oval, "bottom") == 0)
+ *align = ALIGN_BOTTOM;
+ else if (strcasecmp(oval, "middle") == 0)
+ *align = ALIGN_MIDDLE;
+ else
+ return 0;
+ return 1;
+}
+
+static int
+toVAlign(char *oval, int *valign)
+{
+ if (strcasecmp(oval, "top") == 0 || strcasecmp(oval, "baseline") == 0)
+ *valign = VALIGN_TOP;
+ else if (strcasecmp(oval, "bottom") == 0)
+ *valign = VALIGN_BOTTOM;
+ else if (strcasecmp(oval, "middle") == 0)
+ *valign = VALIGN_MIDDLE;
+ else
+ return 0;
+ return 1;
+}
+
+extern Hash_si tagtable;
+#define MAX_TAG_LEN 64
+
+struct parsed_tag *
+parse_tag(char **s, int internal)
+{
+ struct parsed_tag *tag = NULL;
+ int tag_id;
+ char tagname[MAX_TAG_LEN], attrname[MAX_TAG_LEN];
+ char *p, *q;
+ int i, attr_id = 0, nattr;
+
+ /* Parse tag name */
+ q = (*s) + 1;
+ p = tagname;
+ if (*q == '/') {
+ *(p++) = *(q++);
+ SKIP_BLANKS(q);
+ }
+ while (*q && !IS_SPACE(*q) && !(tagname[0] != '/' && *q == '/') &&
+ *q != '>' && p - tagname < MAX_TAG_LEN - 1) {
+ *(p++) = TOLOWER(*q);
+ q++;
+ }
+ *p = '\0';
+ while (*q && !IS_SPACE(*q) && !(tagname[0] != '/' && *q == '/') &&
+ *q != '>')
+ q++;
+
+ tag_id = getHash_si(&tagtable, tagname, HTML_UNKNOWN);
+
+ if (tag_id == HTML_UNKNOWN ||
+ (!internal && TagMAP[tag_id].flag & TFLG_INT))
+ goto skip_parse_tagarg;
+
+ tag = New(struct parsed_tag);
+ bzero(tag, sizeof(struct parsed_tag));
+ tag->tagid = tag_id;
+
+ if ((nattr = TagMAP[tag_id].max_attribute) > 0) {
+ tag->attrid = NewAtom_N(unsigned char, nattr);
+ tag->value = New_N(char *, nattr);
+ tag->map = NewAtom_N(unsigned char, MAX_TAGATTR);
+ memset(tag->map, MAX_TAGATTR, MAX_TAGATTR);
+ memset(tag->attrid, ATTR_UNKNOWN, nattr);
+ for (i = 0; i < nattr; i++)
+ tag->map[TagMAP[tag_id].accept_attribute[i]] = i;
+ }
+
+ /* Parse tag arguments */
+ SKIP_BLANKS(q);
+ while (1) {
+ Str value = NULL;
+ if (*q == '>' || *q == '\0')
+ goto done_parse_tag;
+ p = attrname;
+ while (*q && *q != '=' && !IS_SPACE(*q) &&
+ *q != '>' && p - attrname < MAX_TAG_LEN - 1) {
+ *(p++) = TOLOWER(*q);
+ q++;
+ }
+ *p = '\0';
+ while (*q && *q != '=' && !IS_SPACE(*q) && *q != '>')
+ q++;
+ SKIP_BLANKS(q);
+ if (*q == '=') {
+ /* get value */
+ value = Strnew();
+ q++;
+ SKIP_BLANKS(q);
+ if (*q == '"') {
+ q++;
+ while (*q && *q != '"') {
+ if (*q != '\n')
+ Strcat_char(value, *q);
+ if (!tag->need_reconstruct && is_html_quote(*q))
+ tag->need_reconstruct = TRUE;
+ q++;
+ }
+ if (*q == '"')
+ q++;
+ }
+ else if (*q == '\'') {
+ q++;
+ while (*q && *q != '\'') {
+ if (*q != '\n')
+ Strcat_char(value, *q);
+ if (!tag->need_reconstruct && is_html_quote(*q))
+ tag->need_reconstruct = TRUE;
+ q++;
+ }
+ if (*q == '\'')
+ q++;
+ }
+ else if (*q) {
+ while (*q && !IS_SPACE(*q) && *q != '>') {
+ Strcat_char(value, *q);
+ if (!tag->need_reconstruct && is_html_quote(*q))
+ tag->need_reconstruct = TRUE;
+ q++;
+ }
+ }
+ }
+ for (i = 0; i < nattr; i++) {
+ if ((tag)->attrid[i] == ATTR_UNKNOWN &&
+ strcmp(AttrMAP[TagMAP[tag_id].accept_attribute[i]].name,
+ attrname) == 0) {
+ attr_id = TagMAP[tag_id].accept_attribute[i];
+ break;
+ }
+ }
+ if (i != nattr) {
+ if (!internal &&
+ ((AttrMAP[attr_id].flag & AFLG_INT) ||
+ (value && AttrMAP[attr_id].vtype == VTYPE_METHOD &&
+ !strcasecmp(value->ptr, "internal")))) {
+ tag->need_reconstruct = TRUE;
+ continue;
+ }
+ tag->attrid[i] = attr_id;
+ if (value)
+ tag->value[i] = html_unquote(value->ptr);
+ else
+ tag->value[i] = NULL;
+ }
+ else {
+ tag->need_reconstruct = TRUE;
+ }
+ }
+
+ skip_parse_tagarg:
+ while (*q != '>' && *q)
+ q++;
+ done_parse_tag:
+ if (*q == '>')
+ q++;
+ *s = q;
+ return tag;
+}
+
+int
+parsedtag_set_value(struct parsed_tag *tag, int id, char *value)
+{
+ int i;
+
+ if (!parsedtag_accepts(tag, id))
+ return 0;
+
+ i = tag->map[id];
+ tag->attrid[i] = id;
+ if (value)
+ tag->value[i] = allocStr(value, -1);
+ else
+ tag->value[i] = NULL;
+ tag->need_reconstruct = TRUE;
+ return 1;
+}
+
+int
+parsedtag_get_value(struct parsed_tag *tag, int id, void *value)
+{
+ int i;
+ if (!parsedtag_exists(tag, id) || !tag->value[i = tag->map[id]])
+ return 0;
+ return toValFunc[AttrMAP[id].vtype] (tag->value[i], value);
+}
+
+Str
+parsedtag2str(struct parsed_tag *tag)
+{
+ int i;
+ int tag_id = tag->tagid;
+ int nattr = TagMAP[tag_id].max_attribute;
+ Str tagstr = Strnew();
+ Strcat_char(tagstr, '<');
+ Strcat_charp(tagstr, TagMAP[tag_id].name);
+ for (i = 0; i < nattr; i++) {
+ if (tag->attrid[i] != ATTR_UNKNOWN) {
+ Strcat_char(tagstr, ' ');
+ Strcat_charp(tagstr, AttrMAP[tag->attrid[i]].name);
+ if (tag->value[i])
+ Strcat(tagstr, Sprintf("=\"%s\"", html_quote(tag->value[i])));
+ }
+ }
+ Strcat_char(tagstr, '>');
+ return tagstr;
+}