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 }