static void dump_selector(CSSSimpleSelector *ss) { CSSStyleSheetAttributeEntry *ae; switch (ss->tree_op) { case CSS_TREE_OP_DESCENDANT: dump_selector(ss->next); printf(" "); break; case CSS_TREE_OP_CHILD: dump_selector(ss->next); printf(" > "); break; case CSS_TREE_OP_PRECEEDED: dump_selector(ss->next); printf(" + "); break; default: break; } printf("%s", css_ident_str(ss->tag)); if (ss->pclasses & CSS_PCLASS_FIRST_CHILD) printf(":first-child"); if (ss->tag_id) printf("#%s", css_ident_str(ss->tag_id)); ae = ss->attrs; while (ae != NULL) { printf("[%s", css_ident_str(ae->attr)); switch (ae->op) { case CSS_ATTR_OP_EQUAL: printf("=%s", ae->value); break; case CSS_ATTR_OP_IN_LIST: printf("~=%s", ae->value); break; case CSS_ATTR_OP_IN_HLIST: printf("|=%s", ae->value); break; } printf("]"); ae = ae->next; } }
static int parse_tag(XMLState *s, const char *buf) { char tag[256], *q, len, eot; char attr_name[256]; char value[2048]; const char *p; CSSIdent css_tag; CSSBox *box, *box1; CSSAttribute *first_attr, **pattr, *attr; p = buf; /* ignore XML commands */ if (p[0] == '!' || p[0] == '?') return XML_STATE_TEXT; /* end of tag check */ eot = 0; if (*p == '/') { p++; eot = 1; } /* parse the tag name */ get_str(&p, tag, sizeof(tag), "/"); if (tag[0] == '\0') { /* special closing tag */ if (eot) { css_tag = CSS_ID_NIL; goto end_of_tag; } else { xml_error(s, "invalid null tag"); return XML_STATE_TEXT; } } if (s->ignore_case) css_strtolower(tag, sizeof(tag)); css_tag = css_new_ident(tag); /* XXX: should test html_syntax, but need more patches */ if (s->is_html && (css_tag == CSS_ID_style || css_tag == CSS_ID_script)) goto pretag; if (eot) goto end_of_tag; /* parse attributes */ first_attr = NULL; pattr = &first_attr; for (;;) { skip_spaces(&p); if (*p == '\0' || *p == '/') break; get_str(&p, attr_name, sizeof(attr_name), "=/"); if (s->ignore_case) css_strtolower(attr_name, sizeof(attr_name)); if (*p == '=') { int och, ch; p++; skip_spaces(&p); och = *p; /* in html, we can put non string values */ if (och != '\'' && och != '\"') { if (!s->html_syntax) xml_error(s, "string expected for attribute '%s'", attr_name); q = value; while (*p != '\0' && !strchr(" \t\n\r<>", *p)) { ch = parse_entity(&p); if ((q - value) < (int)sizeof(value) - 1) *q++ = ch; } *q = '\0'; } else { p++; q = value; while (*p != och && *p != '\0' && *p != '<') { ch = parse_entity(&p); if ((q - value) < (int)sizeof(value) - 1) *q++ = ch; } *q = '\0'; if (*p != och) { xml_error(s, "malformed string in attribute '%s'", attr_name); } else { p++; } } } else { value[0] = '\0'; } attr = box_new_attr(css_new_ident(attr_name), value); if (attr) { *pattr = attr; pattr = &attr->next; } } /* close some tags (correct HTML mistakes) */ if (s->html_syntax) { CSSBox *box1; const HTMLClosedTags *ct; ct = html_closed_tags; for (;;) { if (!ct->tag) break; if (css_tag == ct->tag) { box1 = s->box; while (box1 != NULL && css_get_enum(css_ident_str(box1->tag), ct->tag_closed) >= 0) { html_eval_tag(s, box1); box1 = box1->parent; } if (box1) { s->box = box1; } break; } ct++; } } /* create the new box and add it */ box = css_new_box(css_tag, NULL); box->attrs = first_attr; if (!s->box) { s->root_box = box; } else { css_make_child_box(s->box); css_add_box(s->box, box); } s->box = box; if ((s->flags & XML_DOCBOOK) && css_tag == CSS_ID_programlisting) { pretag: pstrcpy(s->pretag, sizeof(s->pretag), tag); s->pretaglen = strlen(s->pretag); return XML_STATE_PRETAG; } len = strlen(buf); /* end of tag. If html, check also some common mistakes. FORM is considered as self closing to avoid any content problems */ if ((len > 0 && buf[len - 1] == '/') || (s->html_syntax && (css_tag == CSS_ID_br || css_tag == CSS_ID_hr || css_tag == CSS_ID_meta || css_tag == CSS_ID_link || css_tag == CSS_ID_form || css_tag == CSS_ID_base || css_tag == CSS_ID_input || css_tag == CSS_ID_basefont || css_tag == CSS_ID_img))) { end_of_tag: box1 = s->box; if (box1) { if (s->html_syntax) { if (css_tag != CSS_ID_NIL) { /* close all non matching tags */ while (box1 != NULL && box1->tag != css_tag) { html_eval_tag(s, box1); box1 = box1->parent; } } if (!box1) { if (css_tag != CSS_ID_form) xml_error(s, "unmatched closing tag </%s>", css_ident_str(css_tag)); } else { html_eval_tag(s, box1); s->box = box1->parent; } } else { if (css_tag != CSS_ID_NIL && box1->tag != css_tag) { xml_error(s, "unmatched closing tag </%s> for <%s>", css_ident_str(css_tag), css_ident_str(box1->tag)); } else { if (s->is_html) html_eval_tag(s, box1); s->box = box1->parent; } } } } return XML_STATE_TEXT; }
void css_dump_properties(CSSProperty *prop) { const CSSPropertyDef *def; int val, j; CSSPropertyValue *value; while (prop != NULL) { def = css_properties + prop->property; val = prop->value.u.val; printf("%s: ", def->name); if (val == CSS_AUTO) { printf("auto"); } else if (val == CSS_INHERIT) { printf("inherit"); } else { value = &prop->value; for (j = 0; j < prop-> nb_values; j++) { val = value->u.val; switch (value->type) { case CSS_UNIT_EX: printf("%0.1fex", (double)val / CSS_LENGTH_FRAC_BASE); break; case CSS_UNIT_EM: printf("%0.1fem", (double)val / CSS_LENGTH_FRAC_BASE); break; case CSS_UNIT_PERCENT: printf("%0.0f%%", (double)val / CSS_LENGTH_FRAC_BASE); break; case CSS_VALUE_COLOR: printf("#%06X", val); break; case CSS_UNIT_NONE: { const char *p, *p1; int i, len; char buf[100]; if (def->type & CSS_TYPE_BORDER_STYLE) p = border_style_enum; else p = def->name + strlen(def->name) + 1; i = 0; for (;;) { p1 = strchr(p, ','); if (i == val) { if (!p1) len = strlen(p); else len = p1 - p; memcpy(buf, p, len); buf[len] = '\0'; printf("%s", buf); break; } if (!p1) { printf("[%d]", val); break; } i++; p = p1 + 1; } } break; case CSS_VALUE_STRING: printf("\"%s\"", value->u.str); break; case CSS_VALUE_ATTR: printf("attr(%s)", css_ident_str(value->u.attr_id)); break; case CSS_VALUE_COUNTER: printf("counter(%s,%d)", css_ident_str(value->u.counter.counter_id), value->u.counter.type); break; case CSS_VALUE_INTEGER: printf("%d", val); break; case CSS_VALUE_IDENT: printf("%s", css_ident_str(value->u.attr_id)); break; default: printf("[%d]", val); break; } if (j != (prop->nb_values - 1)) printf(" "); value++; } } printf("; "); prop = prop->next; } }