w3m

Unnamed repository; edit this file to name it for gitweb.
git clone https://logand.com/git/w3m.git/
Log | Files | Refs | README

parsetagx.c (7068B)


      1 /* $Id$ */
      2 #include "fm.h"
      3 #include "myctype.h"
      4 #include "indep.h"
      5 #include "Str.h"
      6 #include "parsetagx.h"
      7 #include "hash.h"
      8 
      9 #include "html.c"
     10 
     11 /* parse HTML tag */
     12 
     13 static int noConv(char *, char **);
     14 static int toNumber(char *, int *);
     15 static int toLength(char *, int *);
     16 static int toAlign(char *, int *);
     17 static int toVAlign(char *, int *);
     18 
     19 /* *INDENT-OFF* */
     20 static int (*toValFunc[]) () = {
     21     noConv,		/* VTYPE_NONE    */
     22     noConv,		/* VTYPE_STR     */
     23     toNumber,		/* VTYPE_NUMBER  */
     24     toLength,		/* VTYPE_LENGTH  */
     25     toAlign,		/* VTYPE_ALIGN   */
     26     toVAlign,		/* VTYPE_VALIGN  */
     27     noConv,		/* VTYPE_ACTION  */
     28     noConv,		/* VTYPE_ENCTYPE */
     29     noConv,		/* VTYPE_METHOD  */
     30     noConv,		/* VTYPE_MLENGTH */
     31     noConv,		/* VTYPE_TYPE    */
     32 };
     33 /* *INDENT-ON* */
     34 
     35 static int
     36 noConv(char *oval, char **str)
     37 {
     38     *str = oval;
     39     return 1;
     40 }
     41 
     42 static int
     43 toNumber(char *oval, int *num)
     44 {
     45     char *ep;
     46     int x;
     47 
     48     x = strtol(oval, &ep, 10);
     49 
     50     if (ep > oval) {
     51 	*num = x;
     52 	return 1;
     53     }
     54     else
     55 	return 0;
     56 }
     57 
     58 static int
     59 toLength(char *oval, int *len)
     60 {
     61     int w;
     62     if (!IS_DIGIT(oval[0]))
     63 	return 0;
     64     w = atoi(oval);
     65     if (w < 0)
     66 	return 0;
     67     if (w == 0)
     68 	w = 1;
     69     if (oval[strlen(oval) - 1] == '%')
     70 	*len = -w;
     71     else
     72 	*len = w;
     73     return 1;
     74 }
     75 
     76 static int
     77 toAlign(char *oval, int *align)
     78 {
     79     if (strcasecmp(oval, "left") == 0)
     80 	*align = ALIGN_LEFT;
     81     else if (strcasecmp(oval, "right") == 0)
     82 	*align = ALIGN_RIGHT;
     83     else if (strcasecmp(oval, "center") == 0)
     84 	*align = ALIGN_CENTER;
     85     else if (strcasecmp(oval, "top") == 0)
     86 	*align = ALIGN_TOP;
     87     else if (strcasecmp(oval, "bottom") == 0)
     88 	*align = ALIGN_BOTTOM;
     89     else if (strcasecmp(oval, "middle") == 0)
     90 	*align = ALIGN_MIDDLE;
     91     else
     92 	return 0;
     93     return 1;
     94 }
     95 
     96 static int
     97 toVAlign(char *oval, int *valign)
     98 {
     99     if (strcasecmp(oval, "top") == 0 || strcasecmp(oval, "baseline") == 0)
    100 	*valign = VALIGN_TOP;
    101     else if (strcasecmp(oval, "bottom") == 0)
    102 	*valign = VALIGN_BOTTOM;
    103     else if (strcasecmp(oval, "middle") == 0)
    104 	*valign = VALIGN_MIDDLE;
    105     else
    106 	return 0;
    107     return 1;
    108 }
    109 
    110 extern Hash_si tagtable;
    111 #define MAX_TAG_LEN 64
    112 
    113 struct parsed_tag *
    114 parse_tag(char **s, int internal)
    115 {
    116     struct parsed_tag *tag = NULL;
    117     int tag_id;
    118     char tagname[MAX_TAG_LEN], attrname[MAX_TAG_LEN];
    119     char *p, *q;
    120     int i, attr_id = 0, nattr;
    121 
    122     /* Parse tag name */
    123     q = (*s) + 1;
    124     p = tagname;
    125     if (*q == '/') {
    126 	*(p++) = *(q++);
    127 	SKIP_BLANKS(q);
    128     }
    129     while (*q && !IS_SPACE(*q) && !(tagname[0] != '/' && *q == '/') &&
    130 	   *q != '>' && p - tagname < MAX_TAG_LEN - 1) {
    131 	*(p++) = TOLOWER(*q);
    132 	q++;
    133     }
    134     *p = '\0';
    135     while (*q && !IS_SPACE(*q) && !(tagname[0] != '/' && *q == '/') &&
    136 	   *q != '>')
    137 	q++;
    138 
    139     tag_id = getHash_si(&tagtable, tagname, HTML_UNKNOWN);
    140 
    141     if (tag_id == HTML_UNKNOWN ||
    142 	(!internal && TagMAP[tag_id].flag & TFLG_INT))
    143 	goto skip_parse_tagarg;
    144 
    145     tag = New(struct parsed_tag);
    146     bzero(tag, sizeof(struct parsed_tag));
    147     tag->tagid = tag_id;
    148 
    149     if ((nattr = TagMAP[tag_id].max_attribute) > 0) {
    150 	tag->attrid = NewAtom_N(unsigned char, nattr);
    151 	tag->value = New_N(char *, nattr);
    152 	tag->map = NewAtom_N(unsigned char, MAX_TAGATTR);
    153 	memset(tag->map, MAX_TAGATTR, MAX_TAGATTR);
    154 	memset(tag->attrid, ATTR_UNKNOWN, nattr);
    155 	for (i = 0; i < nattr; i++)
    156 	    tag->map[TagMAP[tag_id].accept_attribute[i]] = i;
    157     }
    158 
    159     /* Parse tag arguments */
    160     SKIP_BLANKS(q);
    161     while (1) {
    162        Str value = NULL, value_tmp = NULL;
    163 	if (*q == '>' || *q == '\0')
    164 	    goto done_parse_tag;
    165 	p = attrname;
    166 	while (*q && *q != '=' && !IS_SPACE(*q) &&
    167 	       *q != '>' && p - attrname < MAX_TAG_LEN - 1) {
    168 	    *(p++) = TOLOWER(*q);
    169 	    q++;
    170 	}
    171 	*p = '\0';
    172 	while (*q && *q != '=' && !IS_SPACE(*q) && *q != '>')
    173 	    q++;
    174 	SKIP_BLANKS(q);
    175 	if (*q == '=') {
    176 	    /* get value */
    177 	    value_tmp = Strnew();
    178 	    q++;
    179 	    SKIP_BLANKS(q);
    180 	    if (*q == '"') {
    181 		q++;
    182 		while (*q && *q != '"') {
    183 		    Strcat_char(value_tmp, *q);
    184 		    if (!tag->need_reconstruct && is_html_quote(*q))
    185 			tag->need_reconstruct = TRUE;
    186 		    q++;
    187 		}
    188 		if (*q == '"')
    189 		    q++;
    190 	    }
    191 	    else if (*q == '\'') {
    192 		q++;
    193 		while (*q && *q != '\'') {
    194 		    Strcat_char(value_tmp, *q);
    195 		    if (!tag->need_reconstruct && is_html_quote(*q))
    196 			tag->need_reconstruct = TRUE;
    197 		    q++;
    198 		}
    199 		if (*q == '\'')
    200 		    q++;
    201 	    }
    202 	    else if (*q) {
    203 		while (*q && !IS_SPACE(*q) && *q != '>') {
    204                    Strcat_char(value_tmp, *q);
    205 		    if (!tag->need_reconstruct && is_html_quote(*q))
    206 			tag->need_reconstruct = TRUE;
    207 		    q++;
    208 		}
    209 	    }
    210 	}
    211 	for (i = 0; i < nattr; i++) {
    212 	    if ((tag)->attrid[i] == ATTR_UNKNOWN &&
    213 		strcmp(AttrMAP[TagMAP[tag_id].accept_attribute[i]].name,
    214 		       attrname) == 0) {
    215 		attr_id = TagMAP[tag_id].accept_attribute[i];
    216 		break;
    217 	    }
    218 	}
    219 
    220        if (value_tmp) {
    221          int j, hidden=FALSE;
    222          for (j=0; j<i; j++) {
    223            if (tag->attrid[j] == ATTR_TYPE &&
    224                strcmp("hidden",tag->value[j]) == 0) {
    225              hidden=TRUE;
    226              break;
    227            }
    228          }
    229          if ((tag_id == HTML_INPUT || tag_id == HTML_INPUT_ALT) &&
    230              attr_id == ATTR_VALUE && hidden) {
    231            value = value_tmp;
    232          } else {
    233            char *x;
    234            value = Strnew();
    235            for (x = value_tmp->ptr; *x; x++) {
    236              if (*x != '\n')
    237                Strcat_char(value, *x);
    238            }
    239          }
    240        }
    241 
    242 	if (i != nattr) {
    243 	    if (!internal &&
    244 		((AttrMAP[attr_id].flag & AFLG_INT) ||
    245 		 (value && AttrMAP[attr_id].vtype == VTYPE_METHOD &&
    246 		  !strcasecmp(value->ptr, "internal")))) {
    247 		tag->need_reconstruct = TRUE;
    248 		continue;
    249 	    }
    250 	    tag->attrid[i] = attr_id;
    251 	    if (value)
    252 		tag->value[i] = html_unquote(value->ptr);
    253 	    else
    254 		tag->value[i] = NULL;
    255 	}
    256 	else {
    257 	    tag->need_reconstruct = TRUE;
    258 	}
    259     }
    260 
    261   skip_parse_tagarg:
    262     while (*q != '>' && *q)
    263 	q++;
    264   done_parse_tag:
    265     if (*q == '>')
    266 	q++;
    267     *s = q;
    268     return tag;
    269 }
    270 
    271 int
    272 parsedtag_set_value(struct parsed_tag *tag, int id, char *value)
    273 {
    274     int i;
    275 
    276     if (!parsedtag_accepts(tag, id))
    277 	return 0;
    278 
    279     i = tag->map[id];
    280     tag->attrid[i] = id;
    281     if (value)
    282 	tag->value[i] = allocStr(value, -1);
    283     else
    284 	tag->value[i] = NULL;
    285     tag->need_reconstruct = TRUE;
    286     return 1;
    287 }
    288 
    289 int
    290 parsedtag_get_value(struct parsed_tag *tag, int id, void *value)
    291 {
    292     int i;
    293     if (!parsedtag_exists(tag, id) || !tag->value[i = tag->map[id]])
    294 	return 0;
    295     return toValFunc[AttrMAP[id].vtype] (tag->value[i], value);
    296 }
    297 
    298 Str
    299 parsedtag2str(struct parsed_tag *tag)
    300 {
    301     int i;
    302     int tag_id = tag->tagid;
    303     int nattr = TagMAP[tag_id].max_attribute;
    304     Str tagstr = Strnew();
    305     Strcat_char(tagstr, '<');
    306     Strcat_charp(tagstr, TagMAP[tag_id].name);
    307     for (i = 0; i < nattr; i++) {
    308 	if (tag->attrid[i] != ATTR_UNKNOWN) {
    309 	    Strcat_char(tagstr, ' ');
    310 	    Strcat_charp(tagstr, AttrMAP[tag->attrid[i]].name);
    311 	    if (tag->value[i])
    312 		Strcat(tagstr, Sprintf("=\"%s\"", html_quote(tag->value[i])));
    313 	}
    314     }
    315     Strcat_char(tagstr, '>');
    316     return tagstr;
    317 }