From 23ec03c90f2fdc91dfad16e2de69e466d58f0a42 Mon Sep 17 00:00:00 2001 From: John Mark Bell Date: Fri, 28 Nov 2008 18:57:34 +0000 Subject: Tidy things up somewhat. css21 is now language, as everything will share the same parsing rules (although there is facility to alter behaviour based upon the language level -- consult language->sheet->level and then decide what to do) svn path=/trunk/libcss/; revision=5815 --- src/parse/Makefile | 2 +- src/parse/css21.c | 1291 ------------- src/parse/css21.h | 25 - src/parse/css21props.c | 4801 ----------------------------------------------- src/parse/language.c | 1002 ++++++++++ src/parse/language.h | 25 + src/parse/properties.c | 4801 +++++++++++++++++++++++++++++++++++++++++++++++ src/parse/propstrings.h | 305 +++ src/stylesheet.c | 18 +- 9 files changed, 6139 insertions(+), 6131 deletions(-) delete mode 100644 src/parse/css21.c delete mode 100644 src/parse/css21.h delete mode 100644 src/parse/css21props.c create mode 100644 src/parse/language.c create mode 100644 src/parse/language.h create mode 100644 src/parse/properties.c create mode 100644 src/parse/propstrings.h diff --git a/src/parse/Makefile b/src/parse/Makefile index fc27e8e..7d42214 100644 --- a/src/parse/Makefile +++ b/src/parse/Makefile @@ -35,7 +35,7 @@ d := $(DIR) CFLAGS := $(CFLAGS) -I$(d) # Sources -SRCS_$(d) := parse.c css21.c +SRCS_$(d) := parse.c language.c # Append to sources for component SOURCES += $(addprefix $(d), $(SRCS_$(d))) diff --git a/src/parse/css21.c b/src/parse/css21.c deleted file mode 100644 index 4303313..0000000 --- a/src/parse/css21.c +++ /dev/null @@ -1,1291 +0,0 @@ -/* - * This file is part of LibCSS. - * Licensed under the MIT License, - * http://www.opensource.org/licenses/mit-license.php - * Copyright 2008 John-Mark Bell - */ - -#include -#include - -#include - -#include "stylesheet.h" -#include "lex/lex.h" -#include "parse/css21.h" -#include "parse/parse.h" - -#include "utils/parserutilserror.h" -#include "utils/utils.h" - -enum { - /* At-rules */ - CHARSET, IMPORT, MEDIA, PAGE, - - /* Properties */ - FIRST_PROP, - - AZIMUTH = FIRST_PROP, BACKGROUND_ATTACHMENT, BACKGROUND_COLOR, - BACKGROUND_IMAGE, BACKGROUND_POSITION, BACKGROUND_REPEAT, - BORDER_BOTTOM_COLOR, BORDER_BOTTOM_STYLE, BORDER_BOTTOM_WIDTH, - BORDER_COLLAPSE, BORDER_LEFT_COLOR, BORDER_LEFT_STYLE, - BORDER_LEFT_WIDTH, BORDER_RIGHT_COLOR, BORDER_RIGHT_STYLE, - BORDER_RIGHT_WIDTH, BORDER_SPACING, BORDER_TOP_COLOR, BORDER_TOP_STYLE, - BORDER_TOP_WIDTH, BOTTOM, CAPTION_SIDE, CLEAR, CLIP, COLOR, CONTENT, - COUNTER_INCREMENT, COUNTER_RESET, CUE_AFTER, CUE_BEFORE, CURSOR, - DIRECTION, DISPLAY, ELEVATION, EMPTY_CELLS, FLOAT, FONT_FAMILY, - FONT_SIZE, FONT_STYLE, FONT_VARIANT, FONT_WEIGHT, HEIGHT, LEFT, - LETTER_SPACING, LINE_HEIGHT, LIST_STYLE_IMAGE, LIST_STYLE_POSITION, - LIST_STYLE_TYPE, MARGIN_BOTTOM, MARGIN_LEFT, MARGIN_RIGHT, MARGIN_TOP, - MAX_HEIGHT, MAX_WIDTH, MIN_HEIGHT, MIN_WIDTH, ORPHANS, OUTLINE_COLOR, - OUTLINE_STYLE, OUTLINE_WIDTH, OVERFLOW, PADDING_BOTTOM, PADDING_LEFT, - PADDING_RIGHT, PADDING_TOP, PAGE_BREAK_AFTER, PAGE_BREAK_BEFORE, - PAGE_BREAK_INSIDE, PAUSE_AFTER, PAUSE_BEFORE, PITCH_RANGE, PITCH, - PLAY_DURING, POSITION, QUOTES, RICHNESS, RIGHT, SPEAK_HEADER, - SPEAK_NUMERAL, SPEAK_PUNCTUATION, SPEAK, SPEECH_RATE, STRESS, - TABLE_LAYOUT, TEXT_ALIGN, TEXT_DECORATION, TEXT_INDENT, TEXT_TRANSFORM, - TOP, UNICODE_BIDI, VERTICAL_ALIGN, VISIBILITY, VOICE_FAMILY, VOLUME, - WHITE_SPACE, WIDOWS, WIDTH, WORD_SPACING, Z_INDEX, - - LAST_PROP = Z_INDEX, - - /* Other keywords */ - INHERIT, IMPORTANT, NONE, BOTH, FIXED, SCROLL, TRANSPARENT, - NO_REPEAT, REPEAT_X, REPEAT_Y, REPEAT, HIDDEN, DOTTED, DASHED, - SOLID, DOUBLE, GROOVE, RIDGE, INSET, OUTSET, THIN, MEDIUM, THICK, - COLLAPSE, SEPARATE, AUTO, LTR, RTL, INLINE, BLOCK, LIST_ITEM, RUN_IN, - INLINE_BLOCK, TABLE, INLINE_TABLE, TABLE_ROW_GROUP, TABLE_HEADER_GROUP, - TABLE_FOOTER_GROUP, TABLE_ROW, TABLE_COLUMN_GROUP, TABLE_COLUMN, - TABLE_CELL, TABLE_CAPTION, BELOW, LEVEL, ABOVE, HIGHER, LOWER, - SHOW, HIDE, XX_SMALL, X_SMALL, SMALL, LARGE, X_LARGE, XX_LARGE, - LARGER, SMALLER, NORMAL, ITALIC, OBLIQUE, SMALL_CAPS, BOLD, BOLDER, - LIGHTER, INSIDE, OUTSIDE, DISC, CIRCLE, SQUARE, DECIMAL, - DECIMAL_LEADING_ZERO, LOWER_ROMAN, UPPER_ROMAN, LOWER_GREEK, - LOWER_LATIN, UPPER_LATIN, ARMENIAN, GEORGIAN, LOWER_ALPHA, UPPER_ALPHA, - INVERT, VISIBLE, ALWAYS, AVOID, X_LOW, LOW, HIGH, X_HIGH, STATIC, - RELATIVE, ABSOLUTE, ONCE, DIGITS, CONTINUOUS, CODE, SPELL_OUT, X_SLOW, - SLOW, FAST, X_FAST, FASTER, SLOWER, CENTER, JUSTIFY, CAPITALIZE, - UPPERCASE, LOWERCASE, EMBED, BIDI_OVERRIDE, BASELINE, SUB, SUPER, - TEXT_TOP, MIDDLE, TEXT_BOTTOM, SILENT, X_SOFT, SOFT, LOUD, X_LOUD, - PRE, NOWRAP, PRE_WRAP, PRE_LINE, - - LAST_KNOWN -}; - -/* Must be synchronised with above enum */ -static struct { - const char *data; - size_t len; -} stringmap[LAST_KNOWN] = { - { "charset", SLEN("charset") }, - { "import", SLEN("import") }, - { "media", SLEN("media") }, - { "page", SLEN("page") }, - - { "azimuth", SLEN("azimuth") }, - { "background-attachment", SLEN("background-attachment") }, - { "background-color", SLEN("background-color") }, - { "background-image", SLEN("background-image") }, - { "background-position", SLEN("background-position") }, - { "background-repeat", SLEN("background-repeat") }, - { "border-bottom-color", SLEN("border-bottom-color") }, - { "border-bottom-style", SLEN("border-bottom-style") }, - { "border-bottom-width", SLEN("border-bottom-width") }, - { "border-collapse", SLEN("border-collapse") }, - { "border-left-color", SLEN("border-left-color") }, - { "border-left-style", SLEN("border-left-style") }, - { "border-left-width", SLEN("border-left-width") }, - { "border-right-color", SLEN("border-right-color") }, - { "border-right-style", SLEN("border-right-style") }, - { "border-right-width", SLEN("border-right-width") }, - { "border-spacing", SLEN("border-spacing") }, - { "border-top-color", SLEN("border-top-color") }, - { "border-top-style", SLEN("border-top-style") }, - { "border-top-width", SLEN("border-top-width") }, - { "bottom", SLEN("bottom") }, - { "caption-side", SLEN("caption-side") }, - { "clear", SLEN("clear") }, - { "clip", SLEN("clip") }, - { "color", SLEN("color") }, - { "content", SLEN("content") }, - { "counter-increment", SLEN("counter-increment") }, - { "counter-reset", SLEN("counter-reset") }, - { "cue-after", SLEN("cue-after") }, - { "cue-before", SLEN("cue-before") }, - { "cursor", SLEN("cursor") }, - { "direction", SLEN("direction") }, - { "display", SLEN("display") }, - { "elevation", SLEN("elevation") }, - { "empty-cells", SLEN("empty-cells") }, - { "float", SLEN("float") }, - { "font-family", SLEN("font-family") }, - { "font-size", SLEN("font-size") }, - { "font-style", SLEN("font-style") }, - { "font-variant", SLEN("font-variant") }, - { "font-weight", SLEN("font-weight") }, - { "height", SLEN("height") }, - { "left", SLEN("left") }, - { "letter-spacing", SLEN("letter-spacing") }, - { "line-height", SLEN("line-height") }, - { "list-style-image", SLEN("list-style-image") }, - { "list-style-position", SLEN("list-style-position") }, - { "list-style-type", SLEN("list-style-type") }, - { "margin-bottom", SLEN("margin-bottom") }, - { "margin-left", SLEN("margin-left") }, - { "margin-right", SLEN("margin-right") }, - { "margin-top", SLEN("margin-top") }, - { "max-height", SLEN("max-height") }, - { "max-width", SLEN("max-width") }, - { "min-height", SLEN("min-height") }, - { "min-width", SLEN("min-width") }, - { "orphans", SLEN("orphans") }, - { "outline-color", SLEN("outline-color") }, - { "outline-style", SLEN("outline-style") }, - { "outline-width", SLEN("outline-width") }, - { "overflow", SLEN("overflow") }, - { "padding-bottom", SLEN("padding-bottom") }, - { "padding-left", SLEN("padding-left") }, - { "padding-right", SLEN("padding-right") }, - { "padding-top", SLEN("padding-top") }, - { "page-break-after", SLEN("page-break-after") }, - { "page-break-before", SLEN("page-break-before") }, - { "page-break-inside", SLEN("page-break-inside") }, - { "pause-after", SLEN("pause-after") }, - { "pause-before", SLEN("pause-before") }, - { "pitch-range", SLEN("pitch-range") }, - { "pitch", SLEN("pitch") }, - { "play-during", SLEN("play-during") }, - { "position", SLEN("position") }, - { "quotes", SLEN("quotes") }, - { "richness", SLEN("richness") }, - { "right", SLEN("right") }, - { "speak-header", SLEN("speak-header") }, - { "speak-numeral", SLEN("speak-numeral") }, - { "speak-punctuation", SLEN("speak-punctuation") }, - { "speak", SLEN("speak") }, - { "speech-rate", SLEN("speech-rate") }, - { "stress", SLEN("stress") }, - { "table-layout", SLEN("table-layout") }, - { "text-align", SLEN("text-align") }, - { "text-decoration", SLEN("text-decoration") }, - { "text-indent", SLEN("text-indent") }, - { "text-transform", SLEN("text-transform") }, - { "top", SLEN("top") }, - { "unicode-bidi", SLEN("unicode-bidi") }, - { "vertical-align", SLEN("vertical-align") }, - { "visibility", SLEN("visibility") }, - { "voice-family", SLEN("voice-family") }, - { "volume", SLEN("volume") }, - { "white-space", SLEN("white-space") }, - { "widows", SLEN("widows") }, - { "width", SLEN("width") }, - { "word-spacing", SLEN("word-spacing") }, - { "z-index", SLEN("z-index") }, - - { "inherit", SLEN("inherit") }, - { "important", SLEN("important") }, - { "none", SLEN("none") }, - { "both", SLEN("both") }, - { "fixed", SLEN("fixed") }, - { "scroll", SLEN("scroll") }, - { "transparent", SLEN("transparent") }, - { "no-repeat", SLEN("no-repeat") }, - { "repeat-x", SLEN("repeat-x") }, - { "repeat-y", SLEN("repeat-y") }, - { "repeat", SLEN("repeat") }, - { "hidden", SLEN("hidden") }, - { "dotted", SLEN("dotted") }, - { "dashed", SLEN("dashed") }, - { "solid", SLEN("solid") }, - { "double", SLEN("double") }, - { "groove", SLEN("groove") }, - { "ridge", SLEN("ridge") }, - { "inset", SLEN("inset") }, - { "outset", SLEN("outset") }, - { "thin", SLEN("thin") }, - { "medium", SLEN("medium") }, - { "thick", SLEN("thick") }, - { "collapse", SLEN("collapse") }, - { "separate", SLEN("separate") }, - { "auto", SLEN("auto") }, - { "ltr", SLEN("ltr") }, - { "rtl", SLEN("rtl") }, - { "inline", SLEN("inline") }, - { "block", SLEN("block") }, - { "list-item", SLEN("list-item") }, - { "run-in", SLEN("run-in") }, - { "inline-block", SLEN("inline-block") }, - { "table", SLEN("table") }, - { "inline-table", SLEN("inline-table") }, - { "table-row-group", SLEN("table-row-group") }, - { "table-header-group", SLEN("table-header-group") }, - { "table-footer-group", SLEN("table-footer-group") }, - { "table-row", SLEN("table-row") }, - { "table-column-group", SLEN("table-column-group") }, - { "table-column", SLEN("table-column") }, - { "table-cell", SLEN("table-cell") }, - { "table-caption", SLEN("table-caption") }, - { "below", SLEN("below") }, - { "level", SLEN("level") }, - { "above", SLEN("above") }, - { "higher", SLEN("higher") }, - { "lower", SLEN("lower") }, - { "show", SLEN("show") }, - { "hide", SLEN("hide") }, - { "xx-small", SLEN("xx-small") }, - { "x-small", SLEN("x-small") }, - { "small", SLEN("small") }, - { "large", SLEN("large") }, - { "x-large", SLEN("x-large") }, - { "xx-large", SLEN("xx-large") }, - { "larger", SLEN("larger") }, - { "smaller", SLEN("smaller") }, - { "normal", SLEN("normal") }, - { "italic", SLEN("italic") }, - { "oblique", SLEN("oblique") }, - { "small-caps", SLEN("small-caps") }, - { "bold", SLEN("bold") }, - { "bolder", SLEN("bolder") }, - { "lighter", SLEN("lighter") }, - { "inside", SLEN("inside") }, - { "outside", SLEN("outside") }, - { "disc", SLEN("disc") }, - { "circle", SLEN("circle") }, - { "square", SLEN("square") }, - { "decimal", SLEN("decimal") }, - { "decimal-leading-zero", SLEN("decimal-leading-zero") }, - { "lower-roman", SLEN("lower-roman") }, - { "upper-roman", SLEN("upper-roman") }, - { "lower-greek", SLEN("lower-greek") }, - { "lower-latin", SLEN("lower-latin") }, - { "upper-latin", SLEN("upper-latin") }, - { "armenian", SLEN("armenian") }, - { "georgian", SLEN("georgian") }, - { "lower-alpha", SLEN("lower-alpha") }, - { "upper-alpha", SLEN("upper-alpha") }, - { "invert", SLEN("invert") }, - { "visible", SLEN("visible") }, - { "always", SLEN("always") }, - { "avoid", SLEN("avoid") }, - { "x-low", SLEN("x-low") }, - { "low", SLEN("low") }, - { "high", SLEN("high") }, - { "x-high", SLEN("x-high") }, - { "static", SLEN("static") }, - { "relative", SLEN("relative") }, - { "absolute", SLEN("absolute") }, - { "once", SLEN("once") }, - { "digits", SLEN("digits") }, - { "continuous", SLEN("continuous") }, - { "code", SLEN("code") }, - { "spell-out", SLEN("spell-out") }, - { "x-slow", SLEN("x-slow") }, - { "slow", SLEN("slow") }, - { "fast", SLEN("fast") }, - { "x-fast", SLEN("x-fast") }, - { "faster", SLEN("faster") }, - { "slower", SLEN("slower") }, - { "center", SLEN("center") }, - { "justify", SLEN("justify") }, - { "capitalize", SLEN("capitalize") }, - { "uppercase", SLEN("uppercase") }, - { "lowercase", SLEN("lowercase") }, - { "embed", SLEN("embed") }, - { "bidi-override", SLEN("bidi-override") }, - { "baseline", SLEN("baseline") }, - { "sub", SLEN("sub") }, - { "super", SLEN("super") }, - { "text-top", SLEN("text-top") }, - { "middle", SLEN("middle") }, - { "text-bottom", SLEN("text-bottom") }, - { "silent", SLEN("silent") }, - { "x-soft", SLEN("x-soft") }, - { "soft", SLEN("soft") }, - { "loud", SLEN("loud") }, - { "x-loud", SLEN("x-loud") }, - { "pre", SLEN("pre") }, - { "nowrap", SLEN("nowrap") }, - { "pre-wrap", SLEN("pre-wrap") }, - { "pre-line", SLEN("pre-line") }, -}; - -typedef struct context_entry { - css_parser_event type; /**< Type of entry */ - void *data; /**< Data for context */ -} context_entry; - -/** - * Context for a CSS 2.1 parser - */ -struct css_css21 { - css_stylesheet *sheet; /**< The stylesheet to parse for */ - css_parser *parser; /**< The underlying core parser */ - -#define STACK_CHUNK 32 - parserutils_stack *context; /**< Context stack */ - - enum { - BEFORE_CHARSET, - BEFORE_RULES, - HAD_RULE, - } state; /**< State flag, for at-rule handling */ - - const uint8_t *strings[LAST_KNOWN]; /**< Interned strings */ - - css_alloc alloc; /**< Memory (de)allocation function */ - void *pw; /**< Client's private data */ -}; - -/* Event handlers */ -static css_error css21_handle_event(css_parser_event type, - const parserutils_vector *tokens, void *pw); -static inline css_error handleStartStylesheet(css_css21 *c, - const parserutils_vector *vector); -static inline css_error handleEndStylesheet(css_css21 *c, - const parserutils_vector *vector); -static inline css_error handleStartRuleset(css_css21 *c, - const parserutils_vector *vector); -static inline css_error handleEndRuleset(css_css21 *c, - const parserutils_vector *vector); -static inline css_error handleStartAtRule(css_css21 *c, - const parserutils_vector *vector); -static inline css_error handleEndAtRule(css_css21 *c, - const parserutils_vector *vector); -static inline css_error handleStartBlock(css_css21 *c, - const parserutils_vector *vector); -static inline css_error handleEndBlock(css_css21 *c, - const parserutils_vector *vector); -static inline css_error handleBlockContent(css_css21 *c, - const parserutils_vector *vector); -static inline css_error handleDeclaration(css_css21 *c, - const parserutils_vector *vector); - -/* Selector list parsing */ -static inline css_error parseClass(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_selector_detail **specific); -static inline css_error parseAttrib(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_selector_detail **specific); -static inline css_error parsePseudo(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_selector_detail **specific); -static inline css_error parseSpecific(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_selector **parent); -static inline css_error parseSelectorSpecifics(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_selector **parent); -static inline css_error parseSimpleSelector(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_selector **result); -static inline css_error parseCombinator(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_combinator *result); -static inline css_error parseSelector(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_selector **result); -static inline css_error parseSelectorList(css_css21 *c, - const parserutils_vector *vector, css_rule *rule); - -/* Declaration parsing */ -static inline css_error parseProperty(css_css21 *c, - const css_token *property, const parserutils_vector *vector, - int *ctx, css_rule *rule); - -/* Helpers */ -static inline void consumeWhitespace(const parserutils_vector *vector, - int *ctx); -static inline bool tokenIsChar(const css_token *token, uint8_t c); - -/** - * Create a CSS 2.1 parser - * - * \param sheet The stylesheet object to parse for - * \param parser The core parser object to use - * \param alloc Memory (de)allocation function - * \param pw Pointer to client-specific private data - * \param css21 Pointer to location to receive parser object - * \return CSS_OK on success, - * CSS_BADPARM on bad parameters, - * CSS_NOMEM on memory exhaustion - */ -css_error css_css21_create(css_stylesheet *sheet, css_parser *parser, - css_alloc alloc, void *pw, void **css21) -{ - css_css21 *c; - css_parser_optparams params; - parserutils_error perror; - css_error error; - - if (sheet == NULL || parser == NULL || alloc == NULL || css21 == NULL) - return CSS_BADPARM; - - c = alloc(NULL, sizeof(css_css21), pw); - if (c == NULL) - return CSS_NOMEM; - - perror = parserutils_stack_create(sizeof(context_entry), - STACK_CHUNK, (parserutils_alloc) alloc, pw, - &c->context); - if (perror != PARSERUTILS_OK) { - alloc(c, 0, pw); - return css_error_from_parserutils_error(perror); - } - - /* Intern all known strings */ - for (int i = 0; i < LAST_KNOWN; i++) { - c->strings[i] = css_parser_dict_add(parser, - (const uint8_t *) stringmap[i].data, - stringmap[i].len); - if (c->strings[i] == NULL) { - parserutils_stack_destroy(c->context); - alloc(c, 0, pw); - return CSS_NOMEM; - } - } - - params.event_handler.handler = css21_handle_event; - params.event_handler.pw = c; - error = css_parser_setopt(parser, CSS_PARSER_EVENT_HANDLER, ¶ms); - if (error != CSS_OK) { - parserutils_stack_destroy(c->context); - alloc(c, 0, pw); - return error; - } - - c->sheet = sheet; - c->parser = parser; - c->state = BEFORE_CHARSET; - c->alloc = alloc; - c->pw = pw; - - *css21 = c; - - return CSS_OK; -} - -/** - * Destroy a CSS 2.1 parser - * - * \param css21 The parser to destroy - * \return CSS_OK on success, appropriate error otherwise - */ -css_error css_css21_destroy(css_css21 *css21) -{ - if (css21 == NULL) - return CSS_BADPARM; - - parserutils_stack_destroy(css21->context); - - css21->alloc(css21, 0, css21->pw); - - return CSS_OK; -} - -/** - * Handler for core parser events - * - * \param type The event type - * \param tokens Vector of tokens read since last event, or NULL - * \param pw Pointer to handler context - * \return CSS_OK on success, CSS_INVALID to indicate parse error, - * appropriate error otherwise. - */ -css_error css21_handle_event(css_parser_event type, - const parserutils_vector *tokens, void *pw) -{ - css_css21 *css21 = (css_css21 *) pw; - - switch (type) { - case CSS_PARSER_START_STYLESHEET: - return handleStartStylesheet(css21, tokens); - case CSS_PARSER_END_STYLESHEET: - return handleEndStylesheet(css21, tokens); - case CSS_PARSER_START_RULESET: - return handleStartRuleset(css21, tokens); - case CSS_PARSER_END_RULESET: - return handleEndRuleset(css21, tokens); - case CSS_PARSER_START_ATRULE: - return handleStartAtRule(css21, tokens); - case CSS_PARSER_END_ATRULE: - return handleEndAtRule(css21, tokens); - case CSS_PARSER_START_BLOCK: - return handleStartBlock(css21, tokens); - case CSS_PARSER_END_BLOCK: - return handleEndBlock(css21, tokens); - case CSS_PARSER_BLOCK_CONTENT: - return handleBlockContent(css21, tokens); - case CSS_PARSER_DECLARATION: - return handleDeclaration(css21, tokens); - } - - return CSS_OK; -} - -/****************************************************************************** - * Parser stages * - ******************************************************************************/ - -css_error handleStartStylesheet(css_css21 *c, const parserutils_vector *vector) -{ - parserutils_error perror; - context_entry entry = { CSS_PARSER_START_STYLESHEET, NULL }; - - UNUSED(vector); - - assert(c != NULL); - - perror = parserutils_stack_push(c->context, (void *) &entry); - if (perror != PARSERUTILS_OK) { - return css_error_from_parserutils_error(perror); - } - - return CSS_OK; -} - -css_error handleEndStylesheet(css_css21 *c, const parserutils_vector *vector) -{ - parserutils_error perror; - context_entry *entry; - - UNUSED(vector); - - assert(c != NULL); - - entry = parserutils_stack_get_current(c->context); - if (entry == NULL || entry->type != CSS_PARSER_START_STYLESHEET) - return CSS_INVALID; - - perror = parserutils_stack_pop(c->context, NULL); - if (perror != PARSERUTILS_OK) { - return css_error_from_parserutils_error(perror); - } - - return CSS_OK; -} - -css_error handleStartRuleset(css_css21 *c, const parserutils_vector *vector) -{ - parserutils_error perror; - css_error error; - context_entry entry = { CSS_PARSER_START_RULESET, NULL }; - css_rule *rule = NULL; - - assert(c != NULL); - - error = css_stylesheet_rule_create(c->sheet, CSS_RULE_SELECTOR, &rule); - if (error != CSS_OK) - return error; - - error = parseSelectorList(c, vector, rule); - if (error != CSS_OK) { - css_stylesheet_rule_destroy(c->sheet, rule); - return error; - } - - entry.data = rule; - - perror = parserutils_stack_push(c->context, (void *) &entry); - if (perror != PARSERUTILS_OK) { - css_stylesheet_rule_destroy(c->sheet, rule); - return css_error_from_parserutils_error(perror); - } - - error = css_stylesheet_add_rule(c->sheet, rule); - if (error != CSS_OK) { - parserutils_stack_pop(c->context, NULL); - css_stylesheet_rule_destroy(c->sheet, rule); - return error; - } - - /* Rule is now owned by the sheet, so no need to destroy it */ - - return CSS_OK; -} - -css_error handleEndRuleset(css_css21 *c, const parserutils_vector *vector) -{ - parserutils_error perror; - context_entry *entry; - - UNUSED(vector); - - assert(c != NULL); - - entry = parserutils_stack_get_current(c->context); - if (entry == NULL || entry->type != CSS_PARSER_START_RULESET) - return CSS_INVALID; - - perror = parserutils_stack_pop(c->context, NULL); - if (perror != PARSERUTILS_OK) { - return css_error_from_parserutils_error(perror); - } - - return CSS_OK; -} - -css_error handleStartAtRule(css_css21 *c, const parserutils_vector *vector) -{ - parserutils_error perror; - context_entry entry = { CSS_PARSER_START_ATRULE, NULL }; - - assert(c != NULL); - - /* vector contains: ATKEYWORD ws any0 */ - const css_token *token = NULL; - const css_token *atkeyword = NULL; - int32_t ctx = 0; - - atkeyword = parserutils_vector_iterate(vector, &ctx); - - consumeWhitespace(vector, &ctx); - - /* We now have an ATKEYWORD and the context for the start of any0, if - * there is one */ - assert(atkeyword != NULL && atkeyword->type == CSS_TOKEN_ATKEYWORD); - - if (atkeyword->lower.data == c->strings[CHARSET]) { - if (c->state == BEFORE_CHARSET) { - /* any0 = STRING */ - if (ctx == 0) - return CSS_INVALID; - - token = parserutils_vector_iterate(vector, &ctx); - if (token == NULL || token->type != CSS_TOKEN_STRING) - return CSS_INVALID; - - token = parserutils_vector_iterate(vector, &ctx); - if (token != NULL) - return CSS_INVALID; - - c->state = BEFORE_RULES; - } else { - return CSS_INVALID; - } - } else if (atkeyword->lower.data == c->strings[IMPORT]) { - if (c->state != HAD_RULE) { - /* any0 = (STRING | URI) ws - * (IDENT ws (',' ws IDENT ws)* )? */ - const css_token *uri = - parserutils_vector_iterate(vector, &ctx); - if (uri == NULL || (uri->type != CSS_TOKEN_STRING && - uri->type != CSS_TOKEN_URI)) - return CSS_INVALID; - - consumeWhitespace(vector, &ctx); - - /** \todo Media list */ - if (parserutils_vector_peek(vector, ctx) != NULL) { - } - - /** \todo trigger fetch of imported sheet */ - - c->state = BEFORE_RULES; - } else { - return CSS_INVALID; - } -#if 0 - /** \todo these depend on nested block support, so we'll disable them - * until we have such a thing. This means that we'll ignore the entire - * at-rule until then */ - } else if (atkeyword->lower.data == c->strings[MEDIA]) { - /** \todo any0 = IDENT ws (',' ws IDENT ws)* */ - } else if (atkeyword->lower.data == c->strings[PAGE]) { - /** \todo any0 = (':' IDENT)? ws */ -#endif - } else { - return CSS_INVALID; - } - - entry.data = atkeyword->lower.data; - - perror = parserutils_stack_push(c->context, (void *) &entry); - if (perror != PARSERUTILS_OK) { - return css_error_from_parserutils_error(perror); - } - - return CSS_OK; -} - -css_error handleEndAtRule(css_css21 *c, const parserutils_vector *vector) -{ - parserutils_error perror; - context_entry *entry; - - UNUSED(vector); - - assert(c != NULL); - - entry = parserutils_stack_get_current(c->context); - if (entry == NULL || entry->type != CSS_PARSER_START_ATRULE) - return CSS_INVALID; - - perror = parserutils_stack_pop(c->context, NULL); - if (perror != PARSERUTILS_OK) { - return css_error_from_parserutils_error(perror); - } - - return CSS_OK; -} - -css_error handleStartBlock(css_css21 *c, const parserutils_vector *vector) -{ - UNUSED(c); - UNUSED(vector); - - /* We don't care about blocks. In CSS2.1 they're always attached to - * rulesets or at-rules. */ - - return CSS_OK; -} - -css_error handleEndBlock(css_css21 *c, const parserutils_vector *vector) -{ - UNUSED(c); - UNUSED(vector); - - /* We don't care about blocks. In CSS 2.1 they're always attached to - * rulesets or at-rules. */ - - return CSS_OK; -} - -css_error handleBlockContent(css_css21 *c, const parserutils_vector *vector) -{ - UNUSED(c); - UNUSED(vector); - - /* In CSS 2.1, block content comprises either declarations (if the - * current block is associated with @page or a selector), or rulesets - * (if the current block is associated with @media). */ - - /** \todo implement nested blocks */ - - return CSS_OK; -} - -css_error handleDeclaration(css_css21 *c, const parserutils_vector *vector) -{ - css_error error; - const css_token *token, *ident; - int ctx = 0; - context_entry *entry; - css_rule *rule; - - /* Locations where declarations are permitted: - * - * + In @page - * + In ruleset - */ - entry = parserutils_stack_get_current(c->context); - if (entry == NULL || (entry->type != CSS_PARSER_START_RULESET && - entry->type != CSS_PARSER_START_ATRULE)) - return CSS_INVALID; - - rule = entry->data; - if (rule == NULL || (rule->type != CSS_RULE_SELECTOR && - rule->type != CSS_RULE_PAGE)) - return CSS_INVALID; - - /* IDENT ws ':' ws value - * - * In CSS 2.1, value is any1, so '{' or ATKEYWORD => parse error - */ - ident = parserutils_vector_iterate(vector, &ctx); - if (ident == NULL || ident->type != CSS_TOKEN_IDENT) - return CSS_INVALID; - - consumeWhitespace(vector, &ctx); - - token = parserutils_vector_iterate(vector, &ctx); - if (token == NULL || tokenIsChar(token, ':') == false) - return CSS_INVALID; - - consumeWhitespace(vector, &ctx); - - error = parseProperty(c, ident, vector, &ctx, rule); - if (error != CSS_OK) - return error; - - return CSS_OK; -} - -/****************************************************************************** - * Selector list parsing functions * - ******************************************************************************/ - -css_error parseClass(css_css21 *c, const parserutils_vector *vector, int *ctx, - css_selector_detail **specific) -{ - const css_token *token; - - /* class -> '.' IDENT */ - token = parserutils_vector_iterate(vector, ctx); - if (token == NULL || tokenIsChar(token, '.') == false) - return CSS_INVALID; - - token = parserutils_vector_iterate(vector, ctx); - if (token == NULL || token->type != CSS_TOKEN_IDENT) - return CSS_INVALID; - - return css_stylesheet_selector_detail_create(c->sheet, - CSS_SELECTOR_CLASS, &token->data, NULL, specific); -} - -css_error parseAttrib(css_css21 *c, const parserutils_vector *vector, int *ctx, - css_selector_detail **specific) -{ - const css_token *token, *name, *value = NULL; - css_selector_type type = CSS_SELECTOR_ATTRIBUTE; - - /* attrib -> '[' ws IDENT ws [ - * [ '=' | INCLUDES | DASHMATCH ] ws - * [ IDENT | STRING ] ws ]? ']' - */ - token = parserutils_vector_iterate(vector, ctx); - if (token == NULL || tokenIsChar(token, '[') == false) - return CSS_INVALID; - - consumeWhitespace(vector, ctx); - - token = parserutils_vector_iterate(vector, ctx); - if (token == NULL || token->type != CSS_TOKEN_IDENT) - return CSS_INVALID; - - name = token; - - consumeWhitespace(vector, ctx); - - token = parserutils_vector_iterate(vector, ctx); - if (token == NULL) - return CSS_INVALID; - - if (tokenIsChar(token, ']') == false) { - if (tokenIsChar(token, '=')) - type = CSS_SELECTOR_ATTRIBUTE_EQUAL; - else if (token->type == CSS_TOKEN_INCLUDES) - type = CSS_SELECTOR_ATTRIBUTE_INCLUDES; - else if (token->type == CSS_TOKEN_DASHMATCH) - type = CSS_SELECTOR_ATTRIBUTE_DASHMATCH; - else - return CSS_INVALID; - - consumeWhitespace(vector, ctx); - - token = parserutils_vector_iterate(vector, ctx); - if (token == NULL || (token->type != CSS_TOKEN_IDENT && - token->type != CSS_TOKEN_STRING)) - return CSS_INVALID; - - value = token; - - consumeWhitespace(vector, ctx); - - token = parserutils_vector_iterate(vector, ctx); - if (token == NULL || tokenIsChar(token, ']') == false) - return CSS_INVALID; - } - - return css_stylesheet_selector_detail_create(c->sheet, type, - &name->data, value != NULL ? &value->data : NULL, - specific); -} - -css_error parsePseudo(css_css21 *c, const parserutils_vector *vector, int *ctx, - css_selector_detail **specific) -{ - const css_token *token, *name, *value = NULL; - - /* pseudo -> ':' [ IDENT | FUNCTION ws IDENT? ws ')' ] */ - - token = parserutils_vector_iterate(vector, ctx); - if (token == NULL || tokenIsChar(token, ':') == false) - return CSS_INVALID; - - token = parserutils_vector_iterate(vector, ctx); - if (token == NULL || (token->type != CSS_TOKEN_IDENT && - token->type != CSS_TOKEN_FUNCTION)) - return CSS_INVALID; - - name = token; - - if (token->type == CSS_TOKEN_FUNCTION) { - consumeWhitespace(vector, ctx); - - token = parserutils_vector_iterate(vector, ctx); - - if (token != NULL && token->type == CSS_TOKEN_IDENT) { - value = token; - - consumeWhitespace(vector, ctx); - - token = parserutils_vector_iterate(vector, ctx); - } - - if (token == NULL || tokenIsChar(token, ')') == false) - return CSS_INVALID; - } - - return css_stylesheet_selector_detail_create(c->sheet, - CSS_SELECTOR_PSEUDO, &name->data, - value != NULL ? &value->data : NULL, specific); -} - -css_error parseSpecific(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_selector **parent) -{ - css_error error; - const css_token *token; - css_selector_detail *specific = NULL; - - /* specific -> [ HASH | class | attrib | pseudo ] */ - - token = parserutils_vector_peek(vector, *ctx); - if (token == NULL) - return CSS_INVALID; - - if (token->type == CSS_TOKEN_HASH) { - error = css_stylesheet_selector_detail_create(c->sheet, - CSS_SELECTOR_ID, &token->data, NULL, &specific); - if (error != CSS_OK) - return error; - - parserutils_vector_iterate(vector, ctx); - } else if (tokenIsChar(token, '.')) { - error = parseClass(c, vector, ctx, &specific); - if (error != CSS_OK) - return error; - } else if (tokenIsChar(token, '[')) { - error = parseAttrib(c, vector, ctx, &specific); - if (error != CSS_OK) - return error; - } else if (tokenIsChar(token, ':')) { - error = parsePseudo(c, vector, ctx, &specific); - if (error != CSS_OK) - return error; - } else { - return CSS_INVALID; - } - - error = css_stylesheet_selector_append_specific(c->sheet, parent, - specific); - if (error != CSS_OK) { - css_stylesheet_selector_detail_destroy(c->sheet, specific); - return error; - } - - return CSS_OK; -} - -css_error parseSelectorSpecifics(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_selector **parent) -{ - css_error error; - const css_token *token; - - /* specifics -> specific* */ - while ((token = parserutils_vector_peek(vector, *ctx)) != NULL && - token->type != CSS_TOKEN_S && - tokenIsChar(token, '+') == false && - tokenIsChar(token, '>') == false && - tokenIsChar(token, ',') == false) { - error = parseSpecific(c, vector, ctx, parent); - if (error != CSS_OK) - return error; - } - - return CSS_OK; -} - -css_error parseSimpleSelector(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_selector **result) -{ - css_error error; - const css_token *token; - css_selector *selector; - - /* simple_selector -> element_name specifics - * -> specific specifics - * element_name -> IDENT | '*' - */ - - token = parserutils_vector_peek(vector, *ctx); - if (token == NULL) - return CSS_INVALID; - - if (token->type == CSS_TOKEN_IDENT || tokenIsChar(token, '*')) { - /* Have element name */ - error = css_stylesheet_selector_create(c->sheet, - CSS_SELECTOR_ELEMENT, &token->data, NULL, - &selector); - if (error != CSS_OK) - return error; - - parserutils_vector_iterate(vector, ctx); - } else { - /* Universal selector */ - static css_string name = { 1, (uint8_t *) "*" }; - - error = css_stylesheet_selector_create(c->sheet, - CSS_SELECTOR_ELEMENT, &name, NULL, &selector); - if (error != CSS_OK) - return error; - - /* Ensure we have at least one specific selector */ - error = parseSpecific(c, vector, ctx, &selector); - if (error != CSS_OK) { - css_stylesheet_selector_destroy(c->sheet, selector); - return error; - } - } - - error = parseSelectorSpecifics(c, vector, ctx, &selector); - if (error != CSS_OK) { - css_stylesheet_selector_destroy(c->sheet, selector); - return error; - } - - *result = selector; - - return CSS_OK; -} - -css_error parseCombinator(css_css21 *c, const parserutils_vector *vector, - int *ctx, css_combinator *result) -{ - const css_token *token; - css_combinator comb = CSS_COMBINATOR_NONE; - - /* combinator -> ws '+' ws | ws '>' ws | ws1 */ - - UNUSED(c); - - while ((token = parserutils_vector_peek(vector, *ctx)) != NULL) { - if (tokenIsChar(token, '+')) - comb = CSS_COMBINATOR_SIBLING; - else if (tokenIsChar(token, '>')) - comb = CSS_COMBINATOR_PARENT; - else if (token->type == CSS_TOKEN_S) - comb = CSS_COMBINATOR_ANCESTOR; - else - break; - - parserutils_vector_iterate(vector, ctx); - - /* If we've seen a '+' or '>', we're done. */ - if (comb != CSS_COMBINATOR_ANCESTOR) - break; - } - - /* No valid combinator found */ - if (comb == CSS_COMBINATOR_NONE) - return CSS_INVALID; - - /* Consume any trailing whitespace */ - consumeWhitespace(vector, ctx); - - *result = comb; - - return CSS_OK; -} - -css_error parseSelector(css_css21 *c, const parserutils_vector *vector, - int *ctx, css_selector **result) -{ - css_error error; - const css_token *token = NULL; - css_selector *selector = NULL; - - /* selector -> simple_selector [ combinator simple_selector ]* ws - * - * Note, however, that, as combinator can be wholly whitespace, - * there's an ambiguity as to whether "ws" has been reached. We - * resolve this by attempting to extract a combinator, then - * recovering when we detect that we've reached the end of the - * selector. - */ - - error = parseSimpleSelector(c, vector, ctx, &selector); - if (error != CSS_OK) - return error; - *result = selector; - - while ((token = parserutils_vector_peek(vector, *ctx)) != NULL && - tokenIsChar(token, ',') == false) { - css_combinator comb = CSS_COMBINATOR_NONE; - css_selector *other = NULL; - - error = parseCombinator(c, vector, ctx, &comb); - if (error != CSS_OK) - return error; - - /* In the case of "html , body { ... }", the whitespace after - * "html" and "body" will be considered an ancestor combinator. - * This clearly is not the case, however. Therefore, as a - * special case, if we've got an ancestor combinator and there - * are no further tokens, or if the next token is a comma, - * we ignore the supposed combinator and continue. */ - if (comb == CSS_COMBINATOR_ANCESTOR && - ((token = parserutils_vector_peek(vector, - *ctx)) == NULL || - tokenIsChar(token, ','))) - continue; - - error = parseSimpleSelector(c, vector, ctx, &other); - if (error != CSS_OK) - return error; - - *result = other; - - error = css_stylesheet_selector_combine(c->sheet, - comb, selector, other); - if (error != CSS_OK) - return error; - - selector = other; - } - - return CSS_OK; -} - -css_error parseSelectorList(css_css21 *c, const parserutils_vector *vector, - css_rule *rule) -{ - css_error error; - const css_token *token = NULL; - css_selector *selector = NULL; - int ctx = 0; - - /* selector_list -> selector [ ',' ws selector ]* */ - - error = parseSelector(c, vector, &ctx, &selector); - if (error != CSS_OK) { - if (selector != NULL) - css_stylesheet_selector_destroy(c->sheet, selector); - return error; - } - - assert(selector != NULL); - - error = css_stylesheet_rule_add_selector(c->sheet, rule, selector); - if (error != CSS_OK) { - css_stylesheet_selector_destroy(c->sheet, selector); - return error; - } - - while ((token = parserutils_vector_peek(vector, ctx)) != NULL) { - token = parserutils_vector_iterate(vector, &ctx); - if (tokenIsChar(token, ',') == false) - return CSS_INVALID; - - consumeWhitespace(vector, &ctx); - - selector = NULL; - - error = parseSelector(c, vector, &ctx, &selector); - if (error != CSS_OK) { - if (selector != NULL) { - css_stylesheet_selector_destroy(c->sheet, - selector); - } - return error; - } - - assert(selector != NULL); - - error = css_stylesheet_rule_add_selector(c->sheet, rule, - selector); - if (error != CSS_OK) { - css_stylesheet_selector_destroy(c->sheet, selector); - return error; - } - } - - return CSS_OK; -} - -/****************************************************************************** - * Property parsing functions * - ******************************************************************************/ - -#include "css21props.c" - -css_error parseProperty(css_css21 *c, const css_token *property, - const parserutils_vector *vector, int *ctx, css_rule *rule) -{ - css_error error; - css_prop_handler handler = NULL; - int i = 0; - css_style *style = NULL; - - /* Find property index */ - /** \todo improve on this linear search */ - for (i = FIRST_PROP; i <= LAST_PROP; i++) { - if (property->lower.data == c->strings[i]) - break; - } - if (i == LAST_PROP + 1) - return CSS_INVALID; - - /* Get handler */ - handler = property_handlers[i - FIRST_PROP]; - assert(handler != NULL); - - /* Call it */ - error = handler(c, vector, ctx, &style); - if (error != CSS_OK) - return error; - - /** \todo we should probably assert this, but until we've implemented - * all the property parsers, this will have to suffice. */ - if (style != NULL) { - /* Append style to rule */ - error = css_stylesheet_rule_append_style(c->sheet, rule, style); - if (error != CSS_OK) { - css_stylesheet_style_destroy(c->sheet, style); - return error; - } - } - - /* Style owned or destroyed by stylesheet, so forget about it */ - - return CSS_OK; -} - -/****************************************************************************** - * Helper functions * - ******************************************************************************/ - -/** - * Consume all leading whitespace tokens - * - * \param vector The vector to consume from - * \param ctx The vector's context - */ -void consumeWhitespace(const parserutils_vector *vector, int *ctx) -{ - const css_token *token = NULL; - - while ((token = parserutils_vector_peek(vector, *ctx)) != NULL && - token->type == CSS_TOKEN_S) - token = parserutils_vector_iterate(vector, ctx); -} - -/** - * Determine if a token is a character - * - * \param token The token to consider - * \param c The character to match (lowercase ASCII only) - * \return True if the token matches, false otherwise - */ -bool tokenIsChar(const css_token *token, uint8_t c) -{ - return token != NULL && token->type == CSS_TOKEN_CHAR && - token->lower.len == 1 && token->lower.data[0] == c; -} - - diff --git a/src/parse/css21.h b/src/parse/css21.h deleted file mode 100644 index 8951308..0000000 --- a/src/parse/css21.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * This file is part of LibCSS. - * Licensed under the MIT License, - * http://www.opensource.org/licenses/mit-license.php - * Copyright 2008 John-Mark Bell - */ - -#ifndef css_parse_css21_h_ -#define css_parse_css21_h_ - -#include - -#include -#include - -#include "parse/parse.h" - -typedef struct css_css21 css_css21; - -css_error css_css21_create(css_stylesheet *sheet, css_parser *parser, - css_alloc alloc, void *pw, void **css21); -css_error css_css21_destroy(css_css21 *css21); - -#endif - diff --git a/src/parse/css21props.c b/src/parse/css21props.c deleted file mode 100644 index 43b0710..0000000 --- a/src/parse/css21props.c +++ /dev/null @@ -1,4801 +0,0 @@ -/* - * This file is part of LibCSS. - * Licensed under the MIT License, - * http://www.opensource.org/licenses/mit-license.php - * Copyright 2008 John-Mark Bell - */ - -#ifndef css_parse_css21props_c_ -#define css_parse_css21props_c_ - -#include "bytecode/bytecode.h" -#include "bytecode/opcodes.h" - -static css_error parse_azimuth(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_background_attachment(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_background_color(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_background_image(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_background_position(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_background_repeat(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_border_bottom_color(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_border_bottom_style(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_border_bottom_width(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_border_collapse(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_border_left_color(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_border_left_style(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_border_left_width(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_border_right_color(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_border_right_style(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_border_right_width(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_border_spacing(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_border_top_color(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_border_top_style(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_border_top_width(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_bottom(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_caption_side(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_clear(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_clip(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_color(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_content(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_counter_increment(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_counter_reset(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_cue_after(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_cue_before(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_cursor(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_direction(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_display(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_elevation(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_empty_cells(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_float(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_font_family(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_font_size(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_font_style(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_font_variant(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_font_weight(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_height(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_left(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_letter_spacing(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_line_height(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_list_style_image(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_list_style_position(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_list_style_type(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_margin_bottom(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_margin_left(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_margin_right(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_margin_top(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_max_height(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_max_width(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_min_height(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_min_width(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_orphans(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_outline_color(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_outline_style(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_outline_width(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_overflow(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_padding_bottom(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_padding_left(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_padding_right(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_padding_top(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_page_break_after(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_page_break_before(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_page_break_inside(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_pause_after(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_pause_before(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_pitch_range(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_pitch(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_play_during(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_position(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_quotes(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_richness(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_right(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_speak_header(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_speak_numeral(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_speak_punctuation(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_speak(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_speech_rate(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_stress(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_table_layout(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_text_align(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_text_decoration(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_text_indent(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_text_transform(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_top(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_unicode_bidi(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_vertical_align(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_visibility(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_voice_family(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_volume(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_white_space(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_widows(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_width(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_word_spacing(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); -static css_error parse_z_index(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); - -static inline css_error parse_important(css_css21 *c, - const parserutils_vector *vector, int *ctx, - uint8_t *result); -static inline css_error parse_colour_specifier(css_css21 *c, - const parserutils_vector *vector, int *ctx, - uint32_t *result); -static inline css_error parse_unit_specifier(css_css21 *c, - const parserutils_vector *vector, int *ctx, - fixed *length, uint32_t *unit); - -static inline css_error parse_border_side_color(css_css21 *c, - const parserutils_vector *vector, int *ctx, - uint16_t side, css_style **result); -static inline css_error parse_border_side_style(css_css21 *c, - const parserutils_vector *vector, int *ctx, - uint16_t side, css_style **result); -static inline css_error parse_border_side_width(css_css21 *c, - const parserutils_vector *vector, int *ctx, - uint16_t side, css_style **result); -static inline css_error parse_margin_side(css_css21 *c, - const parserutils_vector *vector, int *ctx, - uint16_t side, css_style **result); -static inline css_error parse_padding_side(css_css21 *c, - const parserutils_vector *vector, int *ctx, - uint16_t side, css_style **result); - -/** - * Type of property handler function - */ -typedef css_error (*css_prop_handler)(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result); - -/** - * Dispatch table of property handlers, indexed by property enum - */ -static const css_prop_handler property_handlers[LAST_PROP + 1 - FIRST_PROP] = -{ - parse_azimuth, - parse_background_attachment, - parse_background_color, - parse_background_image, - parse_background_position, - parse_background_repeat, - parse_border_bottom_color, - parse_border_bottom_style, - parse_border_bottom_width, - parse_border_collapse, - parse_border_left_color, - parse_border_left_style, - parse_border_left_width, - parse_border_right_color, - parse_border_right_style, - parse_border_right_width, - parse_border_spacing, - parse_border_top_color, - parse_border_top_style, - parse_border_top_width, - parse_bottom, - parse_caption_side, - parse_clear, - parse_clip, - parse_color, - parse_content, - parse_counter_increment, - parse_counter_reset, - parse_cue_after, - parse_cue_before, - parse_cursor, - parse_direction, - parse_display, - parse_elevation, - parse_empty_cells, - parse_float, - parse_font_family, - parse_font_size, - parse_font_style, - parse_font_variant, - parse_font_weight, - parse_height, - parse_left, - parse_letter_spacing, - parse_line_height, - parse_list_style_image, - parse_list_style_position, - parse_list_style_type, - parse_margin_bottom, - parse_margin_left, - parse_margin_right, - parse_margin_top, - parse_max_height, - parse_max_width, - parse_min_height, - parse_min_width, - parse_orphans, - parse_outline_color, - parse_outline_style, - parse_outline_width, - parse_overflow, - parse_padding_bottom, - parse_padding_left, - parse_padding_right, - parse_padding_top, - parse_page_break_after, - parse_page_break_before, - parse_page_break_inside, - parse_pause_after, - parse_pause_before, - parse_pitch_range, - parse_pitch, - parse_play_during, - parse_position, - parse_quotes, - parse_richness, - parse_right, - parse_speak_header, - parse_speak_numeral, - parse_speak_punctuation, - parse_speak, - parse_speech_rate, - parse_stress, - parse_table_layout, - parse_text_align, - parse_text_decoration, - parse_text_indent, - parse_text_transform, - parse_top, - parse_unicode_bidi, - parse_vertical_align, - parse_visibility, - parse_voice_family, - parse_volume, - parse_white_space, - parse_widows, - parse_width, - parse_word_spacing, - parse_z_index, -}; - -css_error parse_azimuth(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - /** \todo azimuth */ - UNUSED(c); - UNUSED(vector); - UNUSED(ctx); - UNUSED(result); - - return CSS_OK; -} - -css_error parse_background_attachment(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *ident; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - - /* IDENT (fixed, scroll, inherit) */ - ident = parserutils_vector_iterate(vector, ctx); - if (ident == NULL || ident->type != CSS_TOKEN_IDENT) - return CSS_INVALID; - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - if (ident->lower.data == c->strings[INHERIT]) { - flags |= FLAG_INHERIT; - } else if (ident->lower.data == c->strings[FIXED]) { - value = BACKGROUND_ATTACHMENT_FIXED; - } else if (ident->lower.data == c->strings[SCROLL]) { - value = BACKGROUND_ATTACHMENT_SCROLL; - } else - return CSS_INVALID; - - opv = buildOPV(OP_BACKGROUND_ATTACHMENT, flags, value); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - - return CSS_OK; -} - -css_error parse_background_color(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *token; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - uint32_t colour = 0; - uint32_t required_size; - - /* colour | IDENT (transparent, inherit) */ - token= parserutils_vector_peek(vector, *ctx); - if (token == NULL) - return CSS_INVALID; - - if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[INHERIT]) { - parserutils_vector_iterate(vector, ctx); - flags |= FLAG_INHERIT; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[TRANSPARENT]) { - parserutils_vector_iterate(vector, ctx); - value = BACKGROUND_COLOR_TRANSPARENT; - } else { - error = parse_colour_specifier(c, vector, ctx, &colour); - if (error != CSS_OK) - return error; - - value = BACKGROUND_COLOR_SET; - } - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - opv = buildOPV(OP_BACKGROUND_COLOR, flags, value); - - required_size = sizeof(opv); - if ((flags & FLAG_INHERIT) == false && value == BACKGROUND_COLOR_SET) - required_size += sizeof(colour); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, required_size, result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - if ((flags & FLAG_INHERIT) == false && value == BACKGROUND_COLOR_SET) { - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), - &colour, sizeof(colour)); - } - - return CSS_OK; -} - -css_error parse_background_image(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *token; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - uint32_t required_size; - - /* URI | IDENT (none, inherit) */ - token = parserutils_vector_iterate(vector, ctx); - if (token == NULL || (token->type != CSS_TOKEN_IDENT && - token->type != CSS_TOKEN_URI)) - return CSS_INVALID; - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[INHERIT]) { - flags |= FLAG_INHERIT; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[NONE]) { - value = BACKGROUND_IMAGE_NONE; - } else if (token->type == CSS_TOKEN_URI) { - value = BACKGROUND_IMAGE_URI; - } else - return CSS_INVALID; - - opv = buildOPV(OP_BACKGROUND_IMAGE, flags, value); - - required_size = sizeof(opv); - if ((flags & FLAG_INHERIT) == false && value == BACKGROUND_IMAGE_URI) - required_size += sizeof(uint8_t *) + sizeof(size_t); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, required_size, result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - if ((flags & FLAG_INHERIT) == false && value == BACKGROUND_IMAGE_URI) { - memcpy((uint8_t *) (*result)->bytecode + sizeof(opv), - &token->data.data, sizeof(uint8_t *)); - memcpy((uint8_t *) (*result)->bytecode + sizeof(opv) + - sizeof(uint8_t *), - &token->data.len, sizeof(size_t)); - } - - return CSS_OK; -} - -css_error parse_background_position(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - /** \todo background-position */ - UNUSED(c); - UNUSED(vector); - UNUSED(ctx); - UNUSED(result); - - return CSS_OK; -} - -css_error parse_background_repeat(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *ident; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - - /* IDENT (no-repeat, repeat-x, repeat-y, repeat, inherit) */ - ident = parserutils_vector_iterate(vector, ctx); - if (ident == NULL || ident->type != CSS_TOKEN_IDENT) - return CSS_INVALID; - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - if (ident->lower.data == c->strings[INHERIT]) { - flags |= FLAG_INHERIT; - } else if (ident->lower.data == c->strings[NO_REPEAT]) { - value = BACKGROUND_REPEAT_NO_REPEAT; - } else if (ident->lower.data == c->strings[REPEAT_X]) { - value = BACKGROUND_REPEAT_REPEAT_X; - } else if (ident->lower.data == c->strings[REPEAT_Y]) { - value = BACKGROUND_REPEAT_REPEAT_Y; - } else if (ident->lower.data == c->strings[REPEAT]) { - value = BACKGROUND_REPEAT_REPEAT; - } else - return CSS_INVALID; - - opv = buildOPV(OP_BACKGROUND_REPEAT, flags, value); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - - return CSS_OK; -} - -css_error parse_border_bottom_color(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - return parse_border_side_color(c, vector, ctx, SIDE_BOTTOM, result); -} - -css_error parse_border_bottom_style(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - return parse_border_side_style(c, vector, ctx, SIDE_BOTTOM, result); -} - -css_error parse_border_bottom_width(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - return parse_border_side_width(c, vector, ctx, SIDE_BOTTOM, result); -} - -css_error parse_border_collapse(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *ident; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - - /* IDENT (collapse, separate, inherit) */ - ident = parserutils_vector_iterate(vector, ctx); - if (ident == NULL || ident->type != CSS_TOKEN_IDENT) - return CSS_INVALID; - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - if (ident->lower.data == c->strings[INHERIT]) { - flags |= FLAG_INHERIT; - } else if (ident->lower.data == c->strings[COLLAPSE]) { - value = BORDER_COLLAPSE_COLLAPSE; - } else if (ident->lower.data == c->strings[SEPARATE]) { - value = BORDER_COLLAPSE_SEPARATE; - } else - return CSS_INVALID; - - opv = buildOPV(OP_BORDER_COLLAPSE, flags, value); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - - return CSS_OK; -} - -css_error parse_border_left_color(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - return parse_border_side_color(c, vector, ctx, SIDE_LEFT, result); -} - -css_error parse_border_left_style(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - return parse_border_side_style(c, vector, ctx, SIDE_LEFT, result); -} - -css_error parse_border_left_width(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - return parse_border_side_width(c, vector, ctx, SIDE_LEFT, result); -} - -css_error parse_border_right_color(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - return parse_border_side_color(c, vector, ctx, SIDE_RIGHT, result); -} - -css_error parse_border_right_style(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - return parse_border_side_style(c, vector, ctx, SIDE_RIGHT, result); -} - -css_error parse_border_right_width(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - return parse_border_side_width(c, vector, ctx, SIDE_RIGHT, result); -} - -css_error parse_border_spacing(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - /** \todo border-spacing */ - UNUSED(c); - UNUSED(vector); - UNUSED(ctx); - UNUSED(result); - - return CSS_OK; -} - -css_error parse_border_top_color(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - return parse_border_side_color(c, vector, ctx, SIDE_TOP, result); -} - -css_error parse_border_top_style(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - return parse_border_side_style(c, vector, ctx, SIDE_TOP, result); -} - -css_error parse_border_top_width(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - return parse_border_side_width(c, vector, ctx, SIDE_TOP, result); -} - -css_error parse_bottom(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *token; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - fixed length = 0; - uint32_t unit = 0; - uint32_t required_size; - - /* length | percentage | IDENT(auto, inherit) */ - token = parserutils_vector_peek(vector, *ctx); - if (token == NULL) - return CSS_INVALID; - - if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[INHERIT]) { - parserutils_vector_iterate(vector, ctx); - flags = FLAG_INHERIT; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[AUTO]) { - parserutils_vector_iterate(vector, ctx); - value = BOTTOM_AUTO; - } else { - error = parse_unit_specifier(c, vector, ctx, &length, &unit); - if (error != CSS_OK) - return error; - - if (unit & UNIT_ANGLE || unit & UNIT_TIME || unit & UNIT_FREQ) - return CSS_INVALID; - - value = BOTTOM_SET; - } - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - opv = buildOPV(OP_BOTTOM, flags, value); - - required_size = sizeof(opv); - if ((flags & FLAG_INHERIT) == false && value == BOTTOM_SET) - required_size += sizeof(length) + sizeof(unit); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, required_size, result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - if ((flags & FLAG_INHERIT) == false && value == BOTTOM_SET) { - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), - &length, sizeof(length)); - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + - sizeof(length), &unit, sizeof(unit)); - } - - return CSS_OK; -} - -css_error parse_caption_side(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *ident; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - - /* IDENT (top, bottom, inherit) */ - ident = parserutils_vector_iterate(vector, ctx); - if (ident == NULL || ident->type != CSS_TOKEN_IDENT) - return CSS_INVALID; - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - if (ident->lower.data == c->strings[INHERIT]) { - flags |= FLAG_INHERIT; - } else if (ident->lower.data == c->strings[TOP]) { - value = CAPTION_SIDE_TOP; - } else if (ident->lower.data == c->strings[BOTTOM]) { - value = CAPTION_SIDE_BOTTOM; - } else - return CSS_INVALID; - - opv = buildOPV(OP_CAPTION_SIDE, flags, value); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - - return CSS_OK; -} - -css_error parse_clear(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *ident; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - - /* IDENT (left, right, both, none, inherit) */ - ident = parserutils_vector_iterate(vector, ctx); - if (ident == NULL || ident->type != CSS_TOKEN_IDENT) - return CSS_INVALID; - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - if (ident->lower.data == c->strings[INHERIT]) { - flags |= FLAG_INHERIT; - } else if (ident->lower.data == c->strings[RIGHT]) { - value = CLEAR_RIGHT; - } else if (ident->lower.data == c->strings[LEFT]) { - value = CLEAR_LEFT; - } else if (ident->lower.data == c->strings[BOTH]) { - value = CLEAR_BOTH; - } else if (ident->lower.data == c->strings[NONE]) { - value = CLEAR_NONE; - } else - return CSS_INVALID; - - opv = buildOPV(OP_CLEAR, flags, value); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - - return CSS_OK; -} - -css_error parse_clip(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - /** \todo clip */ - UNUSED(c); - UNUSED(vector); - UNUSED(ctx); - UNUSED(result); - - return CSS_OK; -} - -css_error parse_color(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *token; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - uint32_t colour = 0; - uint32_t required_size; - - /* colour | IDENT (inherit) */ - token= parserutils_vector_peek(vector, *ctx); - if (token == NULL) - return CSS_INVALID; - - if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[INHERIT]) { - parserutils_vector_iterate(vector, ctx); - flags |= FLAG_INHERIT; - } else { - error = parse_colour_specifier(c, vector, ctx, &colour); - if (error != CSS_OK) - return error; - - value = COLOR_SET; - } - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - opv = buildOPV(OP_COLOR, flags, value); - - required_size = sizeof(opv); - if ((flags & FLAG_INHERIT) == false && value == COLOR_SET) - required_size += sizeof(colour); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, required_size, result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - if ((flags & FLAG_INHERIT) == false && value == COLOR_SET) { - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), - &colour, sizeof(colour)); - } - - return CSS_OK; -} - -css_error parse_content(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - /** \todo content */ - UNUSED(c); - UNUSED(vector); - UNUSED(ctx); - UNUSED(result); - - return CSS_OK; -} - -css_error parse_counter_increment(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - /** \todo counter-increment */ - UNUSED(c); - UNUSED(vector); - UNUSED(ctx); - UNUSED(result); - - return CSS_OK; -} - -css_error parse_counter_reset(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - /** \todo counter-reset */ - UNUSED(c); - UNUSED(vector); - UNUSED(ctx); - UNUSED(result); - - return CSS_OK; -} - -css_error parse_cue_after(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *token; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - uint32_t required_size; - - /* URI | IDENT (none, inherit) */ - token = parserutils_vector_iterate(vector, ctx); - if (token == NULL || (token->type != CSS_TOKEN_IDENT && - token->type != CSS_TOKEN_URI)) - return CSS_INVALID; - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[INHERIT]) { - flags |= FLAG_INHERIT; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[NONE]) { - value = CUE_AFTER_NONE; - } else if (token->type == CSS_TOKEN_URI) { - value = CUE_AFTER_URI; - } else - return CSS_INVALID; - - opv = buildOPV(OP_CUE_AFTER, flags, value); - - required_size = sizeof(opv); - if ((flags & FLAG_INHERIT) == false && value == CUE_AFTER_URI) - required_size += sizeof(uint8_t *) + sizeof(size_t); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, required_size, result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - if ((flags & FLAG_INHERIT) == false && value == CUE_AFTER_URI) { - memcpy((uint8_t *) (*result)->bytecode + sizeof(opv), - &token->data.data, sizeof(uint8_t *)); - memcpy((uint8_t *) (*result)->bytecode + sizeof(opv) + - sizeof(uint8_t *), - &token->data.len, sizeof(size_t)); - } - - return CSS_OK; -} - -css_error parse_cue_before(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *token; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - uint32_t required_size; - - /* URI | IDENT (none, inherit) */ - token = parserutils_vector_iterate(vector, ctx); - if (token == NULL || (token->type != CSS_TOKEN_IDENT && - token->type != CSS_TOKEN_URI)) - return CSS_INVALID; - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[INHERIT]) { - flags |= FLAG_INHERIT; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[NONE]) { - value = CUE_BEFORE_NONE; - } else if (token->type == CSS_TOKEN_URI) { - value = CUE_BEFORE_URI; - } else - return CSS_INVALID; - - opv = buildOPV(OP_CUE_BEFORE, flags, value); - - required_size = sizeof(opv); - if ((flags & FLAG_INHERIT) == false && value == CUE_BEFORE_URI) - required_size += sizeof(uint8_t *) + sizeof(size_t); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, required_size, result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - if ((flags & FLAG_INHERIT) == false && value == CUE_BEFORE_URI) { - memcpy((uint8_t *) (*result)->bytecode + sizeof(opv), - &token->data.data, sizeof(uint8_t *)); - memcpy((uint8_t *) (*result)->bytecode + sizeof(opv) + - sizeof(uint8_t *), - &token->data.len, sizeof(size_t)); - } - - return CSS_OK; -} - -css_error parse_cursor(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - /** \todo cursor */ - UNUSED(c); - UNUSED(vector); - UNUSED(ctx); - UNUSED(result); - - return CSS_OK; -} - -css_error parse_direction(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *ident; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - - /* IDENT (ltr, rtl, inherit) */ - ident = parserutils_vector_iterate(vector, ctx); - if (ident == NULL || ident->type != CSS_TOKEN_IDENT) - return CSS_INVALID; - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - if (ident->lower.data == c->strings[INHERIT]) { - flags |= FLAG_INHERIT; - } else if (ident->lower.data == c->strings[LTR]) { - value = DIRECTION_LTR; - } else if (ident->lower.data == c->strings[RTL]) { - value = DIRECTION_RTL; - } else - return CSS_INVALID; - - opv = buildOPV(OP_DIRECTION, flags, value); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - - return CSS_OK; -} - -css_error parse_display(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *ident; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - - /* IDENT (inline, block, list-item, run-in, inline-block, table, - * inline-table, table-row-group, table-header-group, - * table-footer-group, table-row, table-column-group, table-column, - * table-cell, table-caption, none, inherit) */ - ident = parserutils_vector_iterate(vector, ctx); - if (ident == NULL || ident->type != CSS_TOKEN_IDENT) - return CSS_INVALID; - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - if (ident->lower.data == c->strings[INHERIT]) { - flags |= FLAG_INHERIT; - } else if (ident->lower.data == c->strings[INLINE]) { - value = DISPLAY_INLINE; - } else if (ident->lower.data == c->strings[BLOCK]) { - value = DISPLAY_BLOCK; - } else if (ident->lower.data == c->strings[LIST_ITEM]) { - value = DISPLAY_LIST_ITEM; - } else if (ident->lower.data == c->strings[RUN_IN]) { - value = DISPLAY_RUN_IN; - } else if (ident->lower.data == c->strings[INLINE_BLOCK]) { - value = DISPLAY_INLINE_BLOCK; - } else if (ident->lower.data == c->strings[TABLE]) { - value = DISPLAY_TABLE; - } else if (ident->lower.data == c->strings[INLINE_TABLE]) { - value = DISPLAY_INLINE_TABLE; - } else if (ident->lower.data == c->strings[TABLE_ROW_GROUP]) { - value = DISPLAY_TABLE_ROW_GROUP; - } else if (ident->lower.data == c->strings[TABLE_HEADER_GROUP]) { - value = DISPLAY_TABLE_HEADER_GROUP; - } else if (ident->lower.data == c->strings[TABLE_FOOTER_GROUP]) { - value = DISPLAY_TABLE_FOOTER_GROUP; - } else if (ident->lower.data == c->strings[TABLE_ROW]) { - value = DISPLAY_TABLE_ROW; - } else if (ident->lower.data == c->strings[TABLE_COLUMN_GROUP]) { - value = DISPLAY_TABLE_COLUMN_GROUP; - } else if (ident->lower.data == c->strings[TABLE_COLUMN]) { - value = DISPLAY_TABLE_COLUMN; - } else if (ident->lower.data == c->strings[TABLE_CELL]) { - value = DISPLAY_TABLE_CELL; - } else if (ident->lower.data == c->strings[TABLE_CAPTION]) { - value = DISPLAY_TABLE_CAPTION; - } else if (ident->lower.data == c->strings[NONE]) { - value = DISPLAY_NONE; - } else - return CSS_INVALID; - - opv = buildOPV(OP_DISPLAY, flags, value); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - - return CSS_OK; -} - -css_error parse_elevation(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *token; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - fixed length = 0; - uint32_t unit = 0; - uint32_t required_size; - - /* angle | IDENT(below, level, above, higher, lower, inherit) */ - token = parserutils_vector_peek(vector, *ctx); - if (token == NULL) - return CSS_INVALID; - - if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[INHERIT]) { - parserutils_vector_iterate(vector, ctx); - flags = FLAG_INHERIT; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[BELOW]) { - parserutils_vector_iterate(vector, ctx); - value = ELEVATION_BELOW; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[LEVEL]) { - parserutils_vector_iterate(vector, ctx); - value = ELEVATION_LEVEL; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[ABOVE]) { - parserutils_vector_iterate(vector, ctx); - value = ELEVATION_ABOVE; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[HIGHER]) { - parserutils_vector_iterate(vector, ctx); - value = ELEVATION_HIGHER; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[LOWER]) { - parserutils_vector_iterate(vector, ctx); - value = ELEVATION_LOWER; - } else { - error = parse_unit_specifier(c, vector, ctx, &length, &unit); - if (error != CSS_OK) - return error; - - if ((unit & UNIT_ANGLE) == false) - return CSS_INVALID; - - value = ELEVATION_ANGLE; - } - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - opv = buildOPV(OP_ELEVATION, flags, value); - - required_size = sizeof(opv); - if ((flags & FLAG_INHERIT) == false && value == ELEVATION_ANGLE) - required_size += sizeof(length) + sizeof(unit); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, required_size, result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - if ((flags & FLAG_INHERIT) == false && value == ELEVATION_ANGLE) { - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), - &length, sizeof(length)); - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + - sizeof(length), &unit, sizeof(unit)); - } - - return CSS_OK; -} - -css_error parse_empty_cells(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *ident; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - - /* IDENT (show, hide, inherit) */ - ident = parserutils_vector_iterate(vector, ctx); - if (ident == NULL || ident->type != CSS_TOKEN_IDENT) - return CSS_INVALID; - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - if (ident->lower.data == c->strings[INHERIT]) { - flags |= FLAG_INHERIT; - } else if (ident->lower.data == c->strings[SHOW]) { - value = EMPTY_CELLS_SHOW; - } else if (ident->lower.data == c->strings[HIDE]) { - value = EMPTY_CELLS_HIDE; - } else - return CSS_INVALID; - - opv = buildOPV(OP_EMPTY_CELLS, flags, value); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - - return CSS_OK; -} - -css_error parse_float(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *ident; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - - /* IDENT (left, right, none, inherit) */ - ident = parserutils_vector_iterate(vector, ctx); - if (ident == NULL || ident->type != CSS_TOKEN_IDENT) - return CSS_INVALID; - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - if (ident->lower.data == c->strings[INHERIT]) { - flags |= FLAG_INHERIT; - } else if (ident->lower.data == c->strings[LEFT]) { - value = FLOAT_LEFT; - } else if (ident->lower.data == c->strings[RIGHT]) { - value = FLOAT_RIGHT; - } else if (ident->lower.data == c->strings[NONE]) { - value = FLOAT_NONE; - } else - return CSS_INVALID; - - opv = buildOPV(OP_FLOAT, flags, value); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - - return CSS_OK; -} - -css_error parse_font_family(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - /** \todo font-family */ - - UNUSED(c); - UNUSED(vector); - UNUSED(ctx); - UNUSED(result); - - return CSS_OK; -} - -css_error parse_font_size(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *token; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - fixed length = 0; - uint32_t unit = 0; - uint32_t required_size; - - /* length | percentage | IDENT(xx-small, x-small, small, medium, - * large, x-large, xx-large, larger, smaller, inherit) */ - token = parserutils_vector_peek(vector, *ctx); - if (token == NULL) - return CSS_INVALID; - - if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[INHERIT]) { - parserutils_vector_iterate(vector, ctx); - flags = FLAG_INHERIT; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[XX_SMALL]) { - parserutils_vector_iterate(vector, ctx); - value = FONT_SIZE_XX_SMALL; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[X_SMALL]) { - parserutils_vector_iterate(vector, ctx); - value = FONT_SIZE_X_SMALL; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[SMALL]) { - parserutils_vector_iterate(vector, ctx); - value = FONT_SIZE_SMALL; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[MEDIUM]) { - parserutils_vector_iterate(vector, ctx); - value = FONT_SIZE_MEDIUM; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[LARGE]) { - parserutils_vector_iterate(vector, ctx); - value = FONT_SIZE_LARGE; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[X_LARGE]) { - parserutils_vector_iterate(vector, ctx); - value = FONT_SIZE_X_LARGE; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[XX_LARGE]) { - parserutils_vector_iterate(vector, ctx); - value = FONT_SIZE_XX_LARGE; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[LARGER]) { - parserutils_vector_iterate(vector, ctx); - value = FONT_SIZE_LARGER; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[SMALLER]) { - parserutils_vector_iterate(vector, ctx); - value = FONT_SIZE_SMALLER; - } else { - error = parse_unit_specifier(c, vector, ctx, &length, &unit); - if (error != CSS_OK) - return error; - - if (unit & UNIT_ANGLE || unit & UNIT_TIME || unit & UNIT_FREQ) - return CSS_INVALID; - - value = FONT_SIZE_DIMENSION; - } - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - opv = buildOPV(OP_FONT_SIZE, flags, value); - - required_size = sizeof(opv); - if ((flags & FLAG_INHERIT) == false && value == FONT_SIZE_DIMENSION) - required_size += sizeof(length) + sizeof(unit); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, required_size, result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - if ((flags & FLAG_INHERIT) == false && value == FONT_SIZE_DIMENSION) { - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), - &length, sizeof(length)); - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + - sizeof(length), &unit, sizeof(unit)); - } - - return CSS_OK; -} - -css_error parse_font_style(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *ident; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - - /* IDENT (normal, italic, oblique, inherit) */ - ident = parserutils_vector_iterate(vector, ctx); - if (ident == NULL || ident->type != CSS_TOKEN_IDENT) - return CSS_INVALID; - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - if (ident->lower.data == c->strings[INHERIT]) { - flags |= FLAG_INHERIT; - } else if (ident->lower.data == c->strings[NORMAL]) { - value = FONT_STYLE_NORMAL; - } else if (ident->lower.data == c->strings[ITALIC]) { - value = FONT_STYLE_ITALIC; - } else if (ident->lower.data == c->strings[OBLIQUE]) { - value = FONT_STYLE_OBLIQUE; - } else - return CSS_INVALID; - - opv = buildOPV(OP_FONT_STYLE, flags, value); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - - return CSS_OK; -} - -css_error parse_font_variant(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *ident; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - - /* IDENT (normal, small-caps, inherit) */ - ident = parserutils_vector_iterate(vector, ctx); - if (ident == NULL || ident->type != CSS_TOKEN_IDENT) - return CSS_INVALID; - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - if (ident->lower.data == c->strings[INHERIT]) { - flags |= FLAG_INHERIT; - } else if (ident->lower.data == c->strings[NORMAL]) { - value = FONT_VARIANT_NORMAL; - } else if (ident->lower.data == c->strings[SMALL_CAPS]) { - value = FONT_VARIANT_SMALL_CAPS; - } else - return CSS_INVALID; - - opv = buildOPV(OP_FONT_VARIANT, flags, value); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - - return CSS_OK; -} - -css_error parse_font_weight(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *token; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - - /* NUMBER (100, 200, 300, 400, 500, 600, 700, 800, 900) | - * IDENT (normal, bold, bolder, lighter, inherit) */ - token = parserutils_vector_iterate(vector, ctx); - if (token == NULL || (token->type != CSS_TOKEN_IDENT && - token->type != CSS_TOKEN_NUMBER)) - return CSS_INVALID; - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - if (token->lower.data == c->strings[INHERIT]) { - flags |= FLAG_INHERIT; - } else if (token->type == CSS_TOKEN_NUMBER) { - size_t consumed = 0; - fixed num = number_from_css_string(&token->lower, &consumed); - int32_t intpart = FIXTOINT(num); - /* Invalid if there are trailing characters or it was a float */ - if (consumed != token->lower.len || num != intpart) - return CSS_INVALID; - switch (intpart) { - case 100: value = FONT_WEIGHT_100; break; - case 200: value = FONT_WEIGHT_200; break; - case 300: value = FONT_WEIGHT_300; break; - case 400: value = FONT_WEIGHT_400; break; - case 500: value = FONT_WEIGHT_500; break; - case 600: value = FONT_WEIGHT_600; break; - case 700: value = FONT_WEIGHT_700; break; - case 800: value = FONT_WEIGHT_800; break; - case 900: value = FONT_WEIGHT_900; break; - default: return CSS_INVALID; - } - } else if (token->lower.data == c->strings[NORMAL]) { - value = FONT_WEIGHT_NORMAL; - } else if (token->lower.data == c->strings[BOLD]) { - value = FONT_WEIGHT_BOLD; - } else if (token->lower.data == c->strings[BOLDER]) { - value = FONT_WEIGHT_BOLDER; - } else if (token->lower.data == c->strings[LIGHTER]) { - value = FONT_WEIGHT_LIGHTER; - } else - return CSS_INVALID; - - opv = buildOPV(OP_FONT_WEIGHT, flags, value); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - - return CSS_OK; -} - -css_error parse_height(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *token; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - fixed length = 0; - uint32_t unit = 0; - uint32_t required_size; - - /* length | percentage | IDENT(auto, inherit) */ - token = parserutils_vector_peek(vector, *ctx); - if (token == NULL) - return CSS_INVALID; - - if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[INHERIT]) { - parserutils_vector_iterate(vector, ctx); - flags = FLAG_INHERIT; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[AUTO]) { - parserutils_vector_iterate(vector, ctx); - value = HEIGHT_AUTO; - } else { - error = parse_unit_specifier(c, vector, ctx, &length, &unit); - if (error != CSS_OK) - return error; - - if (unit & UNIT_ANGLE || unit & UNIT_TIME || unit & UNIT_FREQ) - return CSS_INVALID; - - value = HEIGHT_SET; - } - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - opv = buildOPV(OP_HEIGHT, flags, value); - - required_size = sizeof(opv); - if ((flags & FLAG_INHERIT) == false && value == HEIGHT_SET) - required_size += sizeof(length) + sizeof(unit); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, required_size, result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - if ((flags & FLAG_INHERIT) == false && value == HEIGHT_SET) { - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), - &length, sizeof(length)); - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + - sizeof(length), &unit, sizeof(unit)); - } - - return CSS_OK; -} - -css_error parse_left(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *token; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - fixed length = 0; - uint32_t unit = 0; - uint32_t required_size; - - /* length | percentage | IDENT(auto, inherit) */ - token = parserutils_vector_peek(vector, *ctx); - if (token == NULL) - return CSS_INVALID; - - if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[INHERIT]) { - parserutils_vector_iterate(vector, ctx); - flags = FLAG_INHERIT; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[AUTO]) { - parserutils_vector_iterate(vector, ctx); - value = LEFT_AUTO; - } else { - error = parse_unit_specifier(c, vector, ctx, &length, &unit); - if (error != CSS_OK) - return error; - - if (unit & UNIT_ANGLE || unit & UNIT_TIME || unit & UNIT_FREQ) - return CSS_INVALID; - - value = LEFT_SET; - } - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - opv = buildOPV(OP_LEFT, flags, value); - - required_size = sizeof(opv); - if ((flags & FLAG_INHERIT) == false && value == LEFT_SET) - required_size += sizeof(length) + sizeof(unit); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, required_size, result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - if ((flags & FLAG_INHERIT) == false && value == LEFT_SET) { - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), - &length, sizeof(length)); - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + - sizeof(length), &unit, sizeof(unit)); - } - - return CSS_OK; -} - -css_error parse_letter_spacing(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *token; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - fixed length = 0; - uint32_t unit = 0; - uint32_t required_size; - - /* length | IDENT(normal, inherit) */ - token = parserutils_vector_peek(vector, *ctx); - if (token == NULL) - return CSS_INVALID; - - if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[INHERIT]) { - parserutils_vector_iterate(vector, ctx); - flags = FLAG_INHERIT; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[NORMAL]) { - parserutils_vector_iterate(vector, ctx); - value = LETTER_SPACING_NORMAL; - } else { - error = parse_unit_specifier(c, vector, ctx, &length, &unit); - if (error != CSS_OK) - return error; - - if (unit & UNIT_ANGLE || unit & UNIT_TIME || unit & UNIT_FREQ || - unit & UNIT_PCT) - return CSS_INVALID; - - value = LETTER_SPACING_SET; - } - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - opv = buildOPV(OP_LETTER_SPACING, flags, value); - - required_size = sizeof(opv); - if ((flags & FLAG_INHERIT) == false && value == LETTER_SPACING_SET) - required_size += sizeof(length) + sizeof(unit); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, required_size, result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - if ((flags & FLAG_INHERIT) == false && value == LETTER_SPACING_SET) { - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), - &length, sizeof(length)); - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + - sizeof(length), &unit, sizeof(unit)); - } - - return CSS_OK; -} - -css_error parse_line_height(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *token; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - fixed length = 0; - uint32_t unit = 0; - uint32_t required_size; - - /* number | length | percentage | IDENT(normal, inherit) */ - token = parserutils_vector_peek(vector, *ctx); - if (token == NULL) - return CSS_INVALID; - - if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[INHERIT]) { - parserutils_vector_iterate(vector, ctx); - flags = FLAG_INHERIT; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[NORMAL]) { - parserutils_vector_iterate(vector, ctx); - value = LINE_HEIGHT_NORMAL; - } else if (token->type == CSS_TOKEN_NUMBER) { - size_t consumed = 0; - length = number_from_css_string(&token->lower, &consumed); - if (consumed != token->lower.len) - return CSS_INVALID; - - value = LINE_HEIGHT_NUMBER; - } else { - error = parse_unit_specifier(c, vector, ctx, &length, &unit); - if (error != CSS_OK) - return error; - - if (unit & UNIT_ANGLE || unit & UNIT_TIME || unit & UNIT_FREQ) - return CSS_INVALID; - - value = LINE_HEIGHT_DIMENSION; - } - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - opv = buildOPV(OP_LINE_HEIGHT, flags, value); - - required_size = sizeof(opv); - if ((flags & FLAG_INHERIT) == false && value == LINE_HEIGHT_NUMBER) - required_size += sizeof(length); - else if ((flags & FLAG_INHERIT) == false && - value == LINE_HEIGHT_DIMENSION) - required_size += sizeof(length) + sizeof(unit); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, required_size, result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - if ((flags & FLAG_INHERIT) == false && (value == LINE_HEIGHT_NUMBER || - value == LINE_HEIGHT_DIMENSION)) - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), - &length, sizeof(length)); - if ((flags & FLAG_INHERIT) == false && value == LINE_HEIGHT_DIMENSION) - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + - sizeof(length), &unit, sizeof(unit)); - - return CSS_OK; -} - -css_error parse_list_style_image(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *token; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - uint32_t required_size; - - /* URI | IDENT (none, inherit) */ - token = parserutils_vector_iterate(vector, ctx); - if (token == NULL || (token->type != CSS_TOKEN_IDENT && - token->type != CSS_TOKEN_URI)) - return CSS_INVALID; - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[INHERIT]) { - flags |= FLAG_INHERIT; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[NONE]) { - value = LIST_STYLE_IMAGE_NONE; - } else if (token->type == CSS_TOKEN_URI) { - value = LIST_STYLE_IMAGE_URI; - } else - return CSS_INVALID; - - opv = buildOPV(OP_LIST_STYLE_IMAGE, flags, value); - - required_size = sizeof(opv); - if ((flags & FLAG_INHERIT) == false && value == LIST_STYLE_IMAGE_URI) - required_size += sizeof(uint8_t *) + sizeof(size_t); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, required_size, result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - if ((flags & FLAG_INHERIT) == false && value == LIST_STYLE_IMAGE_URI) { - memcpy((uint8_t *) (*result)->bytecode + sizeof(opv), - &token->data.data, sizeof(uint8_t *)); - memcpy((uint8_t *) (*result)->bytecode + sizeof(opv) + - sizeof(uint8_t *), - &token->data.len, sizeof(size_t)); - } - - return CSS_OK; -} - -css_error parse_list_style_position(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *ident; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - - /* IDENT (inside, outside, inherit) */ - ident = parserutils_vector_iterate(vector, ctx); - if (ident == NULL || ident->type != CSS_TOKEN_IDENT) - return CSS_INVALID; - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - if (ident->lower.data == c->strings[INHERIT]) { - flags |= FLAG_INHERIT; - } else if (ident->lower.data == c->strings[INSIDE]) { - value = LIST_STYLE_POSITION_INSIDE; - } else if (ident->lower.data == c->strings[OUTSIDE]) { - value = LIST_STYLE_POSITION_OUTSIDE; - } else - return CSS_INVALID; - - opv = buildOPV(OP_LIST_STYLE_POSITION, flags, value); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - - return CSS_OK; -} - -css_error parse_list_style_type(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *ident; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - - /* IDENT (disc, circle, square, decimal, decimal-leading-zero, - * lower-roman, upper-roman, lower-greek, lower-latin, - * upper-latin, armenian, georgian, lower-alpha, upper-alpha, - * none, inherit) - */ - ident = parserutils_vector_iterate(vector, ctx); - if (ident == NULL || ident->type != CSS_TOKEN_IDENT) - return CSS_INVALID; - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - if (ident->lower.data == c->strings[INHERIT]) { - flags |= FLAG_INHERIT; - } else if (ident->lower.data == c->strings[DISC]) { - value = LIST_STYLE_TYPE_DISC; - } else if (ident->lower.data == c->strings[CIRCLE]) { - value = LIST_STYLE_TYPE_CIRCLE; - } else if (ident->lower.data == c->strings[SQUARE]) { - value = LIST_STYLE_TYPE_SQUARE; - } else if (ident->lower.data == c->strings[DECIMAL]) { - value = LIST_STYLE_TYPE_DECIMAL; - } else if (ident->lower.data == c->strings[DECIMAL_LEADING_ZERO]) { - value = LIST_STYLE_TYPE_DECIMAL_LEADING_ZERO; - } else if (ident->lower.data == c->strings[LOWER_ROMAN]) { - value = LIST_STYLE_TYPE_LOWER_ROMAN; - } else if (ident->lower.data == c->strings[UPPER_ROMAN]) { - value = LIST_STYLE_TYPE_UPPER_ROMAN; - } else if (ident->lower.data == c->strings[LOWER_GREEK]) { - value = LIST_STYLE_TYPE_LOWER_GREEK; - } else if (ident->lower.data == c->strings[LOWER_LATIN]) { - value = LIST_STYLE_TYPE_LOWER_LATIN; - } else if (ident->lower.data == c->strings[UPPER_LATIN]) { - value = LIST_STYLE_TYPE_UPPER_LATIN; - } else if (ident->lower.data == c->strings[ARMENIAN]) { - value = LIST_STYLE_TYPE_ARMENIAN; - } else if (ident->lower.data == c->strings[GEORGIAN]) { - value = LIST_STYLE_TYPE_GEORGIAN; - } else if (ident->lower.data == c->strings[LOWER_ALPHA]) { - value = LIST_STYLE_TYPE_LOWER_ALPHA; - } else if (ident->lower.data == c->strings[UPPER_ALPHA]) { - value = LIST_STYLE_TYPE_UPPER_ALPHA; - } else if (ident->lower.data == c->strings[NONE]) { - value = LIST_STYLE_TYPE_NONE; - } else - return CSS_INVALID; - - opv = buildOPV(OP_LIST_STYLE_TYPE, flags, value); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - - return CSS_OK; -} - -css_error parse_margin_bottom(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - return parse_margin_side(c, vector, ctx, SIDE_BOTTOM, result); -} - -css_error parse_margin_left(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - return parse_margin_side(c, vector, ctx, SIDE_LEFT, result); -} - -css_error parse_margin_right(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - return parse_margin_side(c, vector, ctx, SIDE_RIGHT, result); -} - -css_error parse_margin_top(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - return parse_margin_side(c, vector, ctx, SIDE_TOP, result); -} - -css_error parse_max_height(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *token; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - fixed length = 0; - uint32_t unit = 0; - uint32_t required_size; - - /* length | percentage | IDENT(none, inherit) */ - token = parserutils_vector_peek(vector, *ctx); - if (token == NULL) - return CSS_INVALID; - - if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[INHERIT]) { - parserutils_vector_iterate(vector, ctx); - flags = FLAG_INHERIT; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[NONE]) { - parserutils_vector_iterate(vector, ctx); - value = MAX_HEIGHT_NONE; - } else { - error = parse_unit_specifier(c, vector, ctx, &length, &unit); - if (error != CSS_OK) - return error; - - if (unit & UNIT_ANGLE || unit & UNIT_TIME || unit & UNIT_FREQ) - return CSS_INVALID; - - value = MAX_HEIGHT_SET; - } - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - opv = buildOPV(OP_MAX_HEIGHT, flags, value); - - required_size = sizeof(opv); - if ((flags & FLAG_INHERIT) == false && value == MAX_HEIGHT_SET) - required_size += sizeof(length) + sizeof(unit); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, required_size, result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - if ((flags & FLAG_INHERIT) == false && value == MAX_HEIGHT_SET) { - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), - &length, sizeof(length)); - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + - sizeof(length), &unit, sizeof(unit)); - } - - return CSS_OK; -} - -css_error parse_max_width(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *token; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - fixed length = 0; - uint32_t unit = 0; - uint32_t required_size; - - /* length | percentage | IDENT(none, inherit) */ - token = parserutils_vector_peek(vector, *ctx); - if (token == NULL) - return CSS_INVALID; - - if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[INHERIT]) { - parserutils_vector_iterate(vector, ctx); - flags = FLAG_INHERIT; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[NONE]) { - parserutils_vector_iterate(vector, ctx); - value = MAX_WIDTH_NONE; - } else { - error = parse_unit_specifier(c, vector, ctx, &length, &unit); - if (error != CSS_OK) - return error; - - if (unit & UNIT_ANGLE || unit & UNIT_TIME || unit & UNIT_FREQ) - return CSS_INVALID; - - value = MAX_WIDTH_SET; - } - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - opv = buildOPV(OP_MAX_WIDTH, flags, value); - - required_size = sizeof(opv); - if ((flags & FLAG_INHERIT) == false && value == MAX_WIDTH_SET) - required_size += sizeof(length) + sizeof(unit); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, required_size, result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - if ((flags && FLAG_INHERIT) == false && value == MAX_WIDTH_SET) { - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), - &length, sizeof(length)); - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + - sizeof(length), &unit, sizeof(unit)); - } - - return CSS_OK; -} - -css_error parse_min_height(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *token; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - fixed length = 0; - uint32_t unit = 0; - uint32_t required_size; - - /* length | percentage | IDENT(inherit) */ - token = parserutils_vector_peek(vector, *ctx); - if (token == NULL) - return CSS_INVALID; - - if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[INHERIT]) { - parserutils_vector_iterate(vector, ctx); - flags = FLAG_INHERIT; - } else { - error = parse_unit_specifier(c, vector, ctx, &length, &unit); - if (error != CSS_OK) - return error; - - if (unit & UNIT_ANGLE || unit & UNIT_TIME || unit & UNIT_FREQ) - return CSS_INVALID; - - value = MIN_HEIGHT_SET; - } - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - opv = buildOPV(OP_MIN_HEIGHT, flags, value); - - required_size = sizeof(opv); - if ((flags & FLAG_INHERIT) == false && value == MIN_HEIGHT_SET) - required_size += sizeof(length) + sizeof(unit); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, required_size, result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - if ((flags & FLAG_INHERIT) == false && value == MIN_HEIGHT_SET) { - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), - &length, sizeof(length)); - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + - sizeof(length), &unit, sizeof(unit)); - } - - return CSS_OK; -} - -css_error parse_min_width(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *token; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - fixed length = 0; - uint32_t unit = 0; - uint32_t required_size; - - /* length | percentage | IDENT(inherit) */ - token = parserutils_vector_peek(vector, *ctx); - if (token == NULL) - return CSS_INVALID; - - if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[INHERIT]) { - parserutils_vector_iterate(vector, ctx); - flags = FLAG_INHERIT; - } else { - error = parse_unit_specifier(c, vector, ctx, &length, &unit); - if (error != CSS_OK) - return error; - - if (unit & UNIT_ANGLE || unit & UNIT_TIME || unit & UNIT_FREQ) - return CSS_INVALID; - - value = MIN_WIDTH_SET; - } - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - opv = buildOPV(OP_MIN_WIDTH, flags, value); - - required_size = sizeof(opv); - if ((flags & FLAG_INHERIT) == false && value == MIN_WIDTH_SET) - required_size += sizeof(length) + sizeof(unit); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, required_size, result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - if ((flags & FLAG_INHERIT) == false && value == MIN_WIDTH_SET) { - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), - &length, sizeof(length)); - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + - sizeof(length), &unit, sizeof(unit)); - } - - return CSS_OK; -} - -css_error parse_orphans(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *token; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - fixed num = 0; - uint32_t required_size; - - /* | IDENT (inherit) */ - token = parserutils_vector_iterate(vector, ctx); - if (token == NULL || (token->type != CSS_TOKEN_IDENT && - token->type != CSS_TOKEN_NUMBER)) - return CSS_INVALID; - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - if (token->lower.data == c->strings[INHERIT]) { - flags |= FLAG_INHERIT; - } else if (token->type == CSS_TOKEN_NUMBER) { - size_t consumed = 0; - num = number_from_css_string(&token->lower, &consumed); - int32_t intpart = FIXTOINT(num); - /* Invalid if there are trailing characters or it was a float */ - if (consumed != token->lower.len || num != intpart) - return CSS_INVALID; - - value = ORPHANS_SET; - } else - return CSS_INVALID; - - opv = buildOPV(OP_ORPHANS, flags, value); - - required_size = sizeof(opv); - if ((flags & FLAG_INHERIT) == false && value == ORPHANS_SET) - required_size += sizeof(num); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, required_size, result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - if ((flags & FLAG_INHERIT) == false && value == ORPHANS_SET) { - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), - &num, sizeof(num)); - } - - return CSS_OK; -} - -css_error parse_outline_color(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *token; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - uint32_t colour = 0; - uint32_t required_size; - - /* colour | IDENT (invert, inherit) */ - token= parserutils_vector_peek(vector, *ctx); - if (token == NULL) - return CSS_INVALID; - - if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[INHERIT]) { - parserutils_vector_iterate(vector, ctx); - flags |= FLAG_INHERIT; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[INVERT]) { - parserutils_vector_iterate(vector, ctx); - value = OUTLINE_COLOR_INVERT; - } else { - error = parse_colour_specifier(c, vector, ctx, &colour); - if (error != CSS_OK) - return error; - - value = OUTLINE_COLOR_SET; - } - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - opv = buildOPV(OP_OUTLINE_COLOR, flags, value); - - required_size = sizeof(opv); - if ((flags & FLAG_INHERIT) == false && value == OUTLINE_COLOR_SET) - required_size += sizeof(colour); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, required_size, result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - if ((flags & FLAG_INHERIT) == false && value == OUTLINE_COLOR_SET) { - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), - &colour, sizeof(colour)); - } - - return CSS_OK; -} - -css_error parse_outline_style(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - uint32_t opv; - uint8_t flags; - uint16_t value; - - /* Fake as border-left-style */ - error = parse_border_side_style(c, vector, ctx, SIDE_LEFT, result); - if (error != CSS_OK) - return error; - - /* Then change the opcode to outline-style, and clear the side bits */ - opv = *((uint32_t *) (*result)->bytecode); - - flags = getFlags(opv); - value = getValue(opv) & ~SIDE_LEFT; - - opv = buildOPV(OP_OUTLINE_STYLE, flags, value); - - *((uint32_t *) (*result)->bytecode) = opv; - - return CSS_OK; -} - -css_error parse_outline_width(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - uint32_t opv; - uint8_t flags; - uint16_t value; - - /* Fake as border-left-width */ - error = parse_border_side_width(c, vector, ctx, SIDE_LEFT, result); - if (error != CSS_OK) - return error; - - /* Then change the opcode to outline-width, and clear the side bits */ - opv = *((uint32_t *) (*result)->bytecode); - - flags = getFlags(opv); - value = getValue(opv) & ~SIDE_LEFT; - - opv = buildOPV(OP_OUTLINE_WIDTH, flags, value); - - *((uint32_t *) (*result)->bytecode) = opv; - - return CSS_OK; -} - -css_error parse_overflow(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *ident; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - - /* IDENT (visible, hidden, scroll, auto, inherit) */ - ident = parserutils_vector_iterate(vector, ctx); - if (ident == NULL || ident->type != CSS_TOKEN_IDENT) - return CSS_INVALID; - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - if (ident->lower.data == c->strings[INHERIT]) { - flags |= FLAG_INHERIT; - } else if (ident->lower.data == c->strings[VISIBLE]) { - value = OVERFLOW_VISIBLE; - } else if (ident->lower.data == c->strings[HIDDEN]) { - value = OVERFLOW_HIDDEN; - } else if (ident->lower.data == c->strings[SCROLL]) { - value = OVERFLOW_SCROLL; - } else if (ident->lower.data == c->strings[AUTO]) { - value = OVERFLOW_AUTO; - } else - return CSS_INVALID; - - opv = buildOPV(OP_OVERFLOW, flags, value); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - - return CSS_OK; -} - -css_error parse_padding_bottom(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - return parse_padding_side(c, vector, ctx, SIDE_BOTTOM, result); -} - -css_error parse_padding_left(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - return parse_padding_side(c, vector, ctx, SIDE_LEFT, result); -} - -css_error parse_padding_right(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - return parse_padding_side(c, vector, ctx, SIDE_RIGHT, result); -} - -css_error parse_padding_top(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - return parse_padding_side(c, vector, ctx, SIDE_TOP, result); -} - -css_error parse_page_break_after(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *ident; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - - /* IDENT (auto, always, avoid, left, right, inherit) */ - ident = parserutils_vector_iterate(vector, ctx); - if (ident == NULL || ident->type != CSS_TOKEN_IDENT) - return CSS_INVALID; - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - if (ident->lower.data == c->strings[INHERIT]) { - flags |= FLAG_INHERIT; - } else if (ident->lower.data == c->strings[AUTO]) { - value = PAGE_BREAK_AFTER_AUTO; - } else if (ident->lower.data == c->strings[ALWAYS]) { - value = PAGE_BREAK_AFTER_ALWAYS; - } else if (ident->lower.data == c->strings[AVOID]) { - value = PAGE_BREAK_AFTER_AVOID; - } else if (ident->lower.data == c->strings[LEFT]) { - value = PAGE_BREAK_AFTER_LEFT; - } else if (ident->lower.data == c->strings[RIGHT]) { - value = PAGE_BREAK_AFTER_RIGHT; - } else - return CSS_INVALID; - - opv = buildOPV(OP_PAGE_BREAK_AFTER, flags, value); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - - return CSS_OK; -} - -css_error parse_page_break_before(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *ident; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - - /* IDENT (auto, always, avoid, left, right, inherit) */ - ident = parserutils_vector_iterate(vector, ctx); - if (ident == NULL || ident->type != CSS_TOKEN_IDENT) - return CSS_INVALID; - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - if (ident->lower.data == c->strings[INHERIT]) { - flags |= FLAG_INHERIT; - } else if (ident->lower.data == c->strings[AUTO]) { - value = PAGE_BREAK_BEFORE_AUTO; - } else if (ident->lower.data == c->strings[ALWAYS]) { - value = PAGE_BREAK_BEFORE_ALWAYS; - } else if (ident->lower.data == c->strings[AVOID]) { - value = PAGE_BREAK_BEFORE_AVOID; - } else if (ident->lower.data == c->strings[LEFT]) { - value = PAGE_BREAK_BEFORE_LEFT; - } else if (ident->lower.data == c->strings[RIGHT]) { - value = PAGE_BREAK_BEFORE_RIGHT; - } else - return CSS_INVALID; - - opv = buildOPV(OP_PAGE_BREAK_BEFORE, flags, value); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - - return CSS_OK; -} - -css_error parse_page_break_inside(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *ident; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - - /* IDENT (auto, avoid, inherit) */ - ident = parserutils_vector_iterate(vector, ctx); - if (ident == NULL || ident->type != CSS_TOKEN_IDENT) - return CSS_INVALID; - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - if (ident->lower.data == c->strings[INHERIT]) { - flags |= FLAG_INHERIT; - } else if (ident->lower.data == c->strings[AUTO]) { - value = PAGE_BREAK_INSIDE_AUTO; - } else if (ident->lower.data == c->strings[AVOID]) { - value = PAGE_BREAK_INSIDE_AVOID; - } else - return CSS_INVALID; - - opv = buildOPV(OP_PAGE_BREAK_INSIDE, flags, value); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - - return CSS_OK; -} - -css_error parse_pause_after(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *token; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - fixed length = 0; - uint32_t unit = 0; - uint32_t required_size; - - /* time | percentage | IDENT(inherit) */ - token = parserutils_vector_peek(vector, *ctx); - if (token == NULL) - return CSS_INVALID; - - if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[INHERIT]) { - parserutils_vector_iterate(vector, ctx); - flags = FLAG_INHERIT; - } else { - error = parse_unit_specifier(c, vector, ctx, &length, &unit); - if (error != CSS_OK) - return error; - - if ((unit & UNIT_TIME) == false && (unit & UNIT_PCT) == false) - return CSS_INVALID; - - value = PAUSE_AFTER_SET; - } - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - opv = buildOPV(OP_PAUSE_AFTER, flags, value); - - required_size = sizeof(opv); - if ((flags & FLAG_INHERIT) == false && value == PAUSE_AFTER_SET) - required_size += sizeof(length) + sizeof(unit); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, required_size, result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - if ((flags & FLAG_INHERIT) == false && value == PAUSE_AFTER_SET) { - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), - &length, sizeof(length)); - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + - sizeof(length), &unit, sizeof(unit)); - } - - return CSS_OK; -} - -css_error parse_pause_before(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *token; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - fixed length = 0; - uint32_t unit = 0; - uint32_t required_size; - - /* time | percentage | IDENT(inherit) */ - token = parserutils_vector_peek(vector, *ctx); - if (token == NULL) - return CSS_INVALID; - - if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[INHERIT]) { - parserutils_vector_iterate(vector, ctx); - flags = FLAG_INHERIT; - } else { - error = parse_unit_specifier(c, vector, ctx, &length, &unit); - if (error != CSS_OK) - return error; - - if ((unit & UNIT_TIME) == false && (unit & UNIT_PCT) == false) - return CSS_INVALID; - - value = PAUSE_BEFORE_SET; - } - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - opv = buildOPV(OP_PAUSE_BEFORE, flags, value); - - required_size = sizeof(opv); - if ((flags & FLAG_INHERIT) == false && value == PAUSE_BEFORE_SET) - required_size += sizeof(length) + sizeof(unit); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, required_size, result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - if ((flags & FLAG_INHERIT) == false && value == PAUSE_BEFORE_SET) { - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), - &length, sizeof(length)); - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + - sizeof(length), &unit, sizeof(unit)); - } - - return CSS_OK; -} - -css_error parse_pitch_range(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *token; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - fixed num = 0; - uint32_t required_size; - - /* number | IDENT (inherit) */ - token = parserutils_vector_iterate(vector, ctx); - if (token == NULL || (token->type != CSS_TOKEN_IDENT && - token->type != CSS_TOKEN_NUMBER)) - return CSS_INVALID; - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - if (token->lower.data == c->strings[INHERIT]) { - flags |= FLAG_INHERIT; - } else if (token->type == CSS_TOKEN_NUMBER) { - size_t consumed = 0; - num = number_from_css_string(&token->lower, &consumed); - /* Invalid if there are trailing characters */ - if (consumed != token->lower.len) - return CSS_INVALID; - - value = PITCH_RANGE_SET; - } else - return CSS_INVALID; - - opv = buildOPV(OP_PITCH_RANGE, flags, value); - - required_size = sizeof(opv); - if ((flags & FLAG_INHERIT) == false && value == PITCH_RANGE_SET) - required_size += sizeof(num); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, required_size, result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - if ((flags & FLAG_INHERIT) == false && value == PITCH_RANGE_SET) { - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), - &num, sizeof(num)); - } - - return CSS_OK; -} - -css_error parse_pitch(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *token; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - fixed length = 0; - uint32_t unit = 0; - uint32_t required_size; - - /* frequency | IDENT(x-low, low, medium, high, x-high, inherit) */ - token = parserutils_vector_peek(vector, *ctx); - if (token == NULL) - return CSS_INVALID; - - if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[INHERIT]) { - parserutils_vector_iterate(vector, ctx); - flags = FLAG_INHERIT; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[X_LOW]) { - value = PITCH_X_LOW; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[LOW]) { - value = PITCH_LOW; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[MEDIUM]) { - value = PITCH_MEDIUM; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[HIGH]) { - value = PITCH_HIGH; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[X_HIGH]) { - value = PITCH_X_HIGH; - } else { - error = parse_unit_specifier(c, vector, ctx, &length, &unit); - if (error != CSS_OK) - return error; - - if ((unit & UNIT_FREQ) == false) - return CSS_INVALID; - - value = PITCH_FREQUENCY; - } - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - opv = buildOPV(OP_PITCH, flags, value); - - required_size = sizeof(opv); - if ((flags & FLAG_INHERIT) == false && value == PITCH_FREQUENCY) - required_size += sizeof(length) + sizeof(unit); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, required_size, result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - if ((flags & FLAG_INHERIT) == false && value == PITCH_FREQUENCY) { - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), - &length, sizeof(length)); - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + - sizeof(length), &unit, sizeof(unit)); - } - - return CSS_OK; -} - -css_error parse_play_during(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - /** \todo play-during */ - - UNUSED(c); - UNUSED(vector); - UNUSED(ctx); - UNUSED(result); - - return CSS_OK; -} - -css_error parse_position(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *ident; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - - /* IDENT (static, relative, absolute, fixed, inherit) */ - ident = parserutils_vector_iterate(vector, ctx); - if (ident == NULL || ident->type != CSS_TOKEN_IDENT) - return CSS_INVALID; - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - if (ident->lower.data == c->strings[INHERIT]) { - flags |= FLAG_INHERIT; - } else if (ident->lower.data == c->strings[STATIC]) { - value = POSITION_STATIC; - } else if (ident->lower.data == c->strings[RELATIVE]) { - value = POSITION_RELATIVE; - } else if (ident->lower.data == c->strings[ABSOLUTE]) { - value = POSITION_ABSOLUTE; - } else if (ident->lower.data == c->strings[FIXED]) { - value = POSITION_FIXED; - } else - return CSS_INVALID; - - opv = buildOPV(OP_POSITION, flags, value); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - - return CSS_OK; -} - -css_error parse_quotes(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - /** \todo quotes */ - - UNUSED(c); - UNUSED(vector); - UNUSED(ctx); - UNUSED(result); - - return CSS_OK; -} - -css_error parse_richness(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *token; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - fixed num = 0; - uint32_t required_size; - - /* number | IDENT (inherit) */ - token = parserutils_vector_iterate(vector, ctx); - if (token == NULL || (token->type != CSS_TOKEN_IDENT && - token->type != CSS_TOKEN_NUMBER)) - return CSS_INVALID; - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - if (token->lower.data == c->strings[INHERIT]) { - flags |= FLAG_INHERIT; - } else if (token->type == CSS_TOKEN_NUMBER) { - size_t consumed = 0; - num = number_from_css_string(&token->lower, &consumed); - /* Invalid if there are trailing characters */ - if (consumed != token->lower.len) - return CSS_INVALID; - - value = RICHNESS_SET; - } else - return CSS_INVALID; - - opv = buildOPV(OP_RICHNESS, flags, value); - - required_size = sizeof(opv); - if ((flags & FLAG_INHERIT) == false && value == RICHNESS_SET) - required_size += sizeof(num); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, required_size, result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - if ((flags & FLAG_INHERIT) == false && value == RICHNESS_SET) { - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), - &num, sizeof(num)); - } - - return CSS_OK; -} - -css_error parse_right(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *token; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - fixed length = 0; - uint32_t unit = 0; - uint32_t required_size; - - /* length | percentage | IDENT(auto, inherit) */ - token = parserutils_vector_peek(vector, *ctx); - if (token == NULL) - return CSS_INVALID; - - if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[INHERIT]) { - parserutils_vector_iterate(vector, ctx); - flags = FLAG_INHERIT; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[AUTO]) { - parserutils_vector_iterate(vector, ctx); - value = RIGHT_AUTO; - } else { - error = parse_unit_specifier(c, vector, ctx, &length, &unit); - if (error != CSS_OK) - return error; - - if (unit & UNIT_ANGLE || unit & UNIT_TIME || unit & UNIT_FREQ) - return CSS_INVALID; - - value = RIGHT_SET; - } - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - opv = buildOPV(OP_RIGHT, flags, value); - - required_size = sizeof(opv); - if ((flags & FLAG_INHERIT) == false && value == RIGHT_SET) - required_size += sizeof(length) + sizeof(unit); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, required_size, result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - if ((flags & FLAG_INHERIT) == false && value == RIGHT_SET) { - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), - &length, sizeof(length)); - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + - sizeof(length), &unit, sizeof(unit)); - } - - return CSS_OK; -} - -css_error parse_speak_header(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *ident; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - - /* IDENT (once, always, inherit) */ - ident = parserutils_vector_iterate(vector, ctx); - if (ident == NULL || ident->type != CSS_TOKEN_IDENT) - return CSS_INVALID; - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - if (ident->lower.data == c->strings[INHERIT]) { - flags |= FLAG_INHERIT; - } else if (ident->lower.data == c->strings[ONCE]) { - value = SPEAK_HEADER_ONCE; - } else if (ident->lower.data == c->strings[ALWAYS]) { - value = SPEAK_HEADER_ALWAYS; - } else - return CSS_INVALID; - - opv = buildOPV(OP_SPEAK_HEADER, flags, value); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - - return CSS_OK; -} - -css_error parse_speak_numeral(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *ident; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - - /* IDENT (digits, continuous, inherit) */ - ident = parserutils_vector_iterate(vector, ctx); - if (ident == NULL || ident->type != CSS_TOKEN_IDENT) - return CSS_INVALID; - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - if (ident->lower.data == c->strings[INHERIT]) { - flags |= FLAG_INHERIT; - } else if (ident->lower.data == c->strings[DIGITS]) { - value = SPEAK_NUMERAL_DIGITS; - } else if (ident->lower.data == c->strings[CONTINUOUS]) { - value = SPEAK_NUMERAL_CONTINUOUS; - } else - return CSS_INVALID; - - opv = buildOPV(OP_SPEAK_NUMERAL, flags, value); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - - return CSS_OK; -} - -css_error parse_speak_punctuation(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *ident; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - - /* IDENT (code, none, inherit) */ - ident = parserutils_vector_iterate(vector, ctx); - if (ident == NULL || ident->type != CSS_TOKEN_IDENT) - return CSS_INVALID; - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - if (ident->lower.data == c->strings[INHERIT]) { - flags |= FLAG_INHERIT; - } else if (ident->lower.data == c->strings[CODE]) { - value = SPEAK_PUNCTUATION_CODE; - } else if (ident->lower.data == c->strings[NONE]) { - value = SPEAK_PUNCTUATION_NONE; - } else - return CSS_INVALID; - - opv = buildOPV(OP_SPEAK_PUNCTUATION, flags, value); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - - return CSS_OK; -} - -css_error parse_speak(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *ident; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - - /* IDENT (normal, none, spell-out, inherit) */ - ident = parserutils_vector_iterate(vector, ctx); - if (ident == NULL || ident->type != CSS_TOKEN_IDENT) - return CSS_INVALID; - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - if (ident->lower.data == c->strings[INHERIT]) { - flags |= FLAG_INHERIT; - } else if (ident->lower.data == c->strings[NORMAL]) { - value = SPEAK_NORMAL; - } else if (ident->lower.data == c->strings[NONE]) { - value = SPEAK_NONE; - } else if (ident->lower.data == c->strings[SPELL_OUT]) { - value = SPEAK_SPELL_OUT; - } else - return CSS_INVALID; - - opv = buildOPV(OP_SPEAK, flags, value); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - - return CSS_OK; -} - -css_error parse_speech_rate(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *token; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - fixed num = 0; - uint32_t required_size; - - /* number | IDENT (x-slow, slow, medium, fast, x-fast, faster, slower, - * inherit) - */ - token = parserutils_vector_iterate(vector, ctx); - if (token == NULL || (token->type != CSS_TOKEN_IDENT && - token->type != CSS_TOKEN_NUMBER)) - return CSS_INVALID; - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[INHERIT]) { - flags |= FLAG_INHERIT; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[X_SLOW]) { - value = SPEECH_RATE_X_SLOW; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[SLOW]) { - value = SPEECH_RATE_SLOW; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[MEDIUM]) { - value = SPEECH_RATE_MEDIUM; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[FAST]) { - value = SPEECH_RATE_FAST; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[X_FAST]) { - value = SPEECH_RATE_X_FAST; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[FASTER]) { - value = SPEECH_RATE_FASTER; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[SLOWER]) { - value = SPEECH_RATE_SLOWER; - } else if (token->type == CSS_TOKEN_NUMBER) { - size_t consumed = 0; - num = number_from_css_string(&token->lower, &consumed); - /* Invalid if there are trailing characters */ - if (consumed != token->lower.len) - return CSS_INVALID; - - value = SPEECH_RATE_SET; - } else - return CSS_INVALID; - - opv = buildOPV(OP_SPEECH_RATE, flags, value); - - required_size = sizeof(opv); - if ((flags & FLAG_INHERIT) == false && value == SPEECH_RATE_SET) - required_size += sizeof(num); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, required_size, result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - if ((flags & FLAG_INHERIT) == false && value == SPEECH_RATE_SET) { - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), - &num, sizeof(num)); - } - - return CSS_OK; -} - -css_error parse_stress(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *token; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - fixed num = 0; - uint32_t required_size; - - /* number | IDENT (inherit) */ - token = parserutils_vector_iterate(vector, ctx); - if (token == NULL || (token->type != CSS_TOKEN_IDENT && - token->type != CSS_TOKEN_NUMBER)) - return CSS_INVALID; - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - if (token->lower.data == c->strings[INHERIT]) { - flags |= FLAG_INHERIT; - } else if (token->type == CSS_TOKEN_NUMBER) { - size_t consumed = 0; - num = number_from_css_string(&token->lower, &consumed); - /* Invalid if there are trailing characters */ - if (consumed != token->lower.len) - return CSS_INVALID; - - value = STRESS_SET; - } else - return CSS_INVALID; - - opv = buildOPV(OP_STRESS, flags, value); - - required_size = sizeof(opv); - if ((flags & FLAG_INHERIT) == false && value == STRESS_SET) - required_size += sizeof(num); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, required_size, result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - if ((flags & FLAG_INHERIT) == false && value == STRESS_SET) { - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), - &num, sizeof(num)); - } - - return CSS_OK; -} - -css_error parse_table_layout(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *ident; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - - /* IDENT (auto, fixed, inherit) */ - ident = parserutils_vector_iterate(vector, ctx); - if (ident == NULL || ident->type != CSS_TOKEN_IDENT) - return CSS_INVALID; - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - if (ident->lower.data == c->strings[INHERIT]) { - flags |= FLAG_INHERIT; - } else if (ident->lower.data == c->strings[AUTO]) { - value = TABLE_LAYOUT_AUTO; - } else if (ident->lower.data == c->strings[FIXED]) { - value = TABLE_LAYOUT_FIXED; - } else - return CSS_INVALID; - - opv = buildOPV(OP_TABLE_LAYOUT, flags, value); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - - return CSS_OK; -} - -css_error parse_text_align(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *ident; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - - /* IDENT (left, right, center, justify, inherit) */ - ident = parserutils_vector_iterate(vector, ctx); - if (ident == NULL || ident->type != CSS_TOKEN_IDENT) - return CSS_INVALID; - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - if (ident->lower.data == c->strings[INHERIT]) { - flags |= FLAG_INHERIT; - } else if (ident->lower.data == c->strings[LEFT]) { - value = TEXT_ALIGN_LEFT; - } else if (ident->lower.data == c->strings[RIGHT]) { - value = TEXT_ALIGN_RIGHT; - } else if (ident->lower.data == c->strings[CENTER]) { - value = TEXT_ALIGN_CENTER; - } else if (ident->lower.data == c->strings[JUSTIFY]) { - value = TEXT_ALIGN_JUSTIFY; - } else - return CSS_INVALID; - - opv = buildOPV(OP_TEXT_ALIGN, flags, value); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - - return CSS_OK; -} - -css_error parse_text_decoration(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - /** \todo text-decoration */ - - UNUSED(c); - UNUSED(vector); - UNUSED(ctx); - UNUSED(result); - - return CSS_OK; -} - -css_error parse_text_indent(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *token; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - fixed length = 0; - uint32_t unit = 0; - uint32_t required_size; - - /* length | percentage | IDENT(inherit) */ - token = parserutils_vector_peek(vector, *ctx); - if (token == NULL) - return CSS_INVALID; - - if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[INHERIT]) { - parserutils_vector_iterate(vector, ctx); - flags = FLAG_INHERIT; - } else { - error = parse_unit_specifier(c, vector, ctx, &length, &unit); - if (error != CSS_OK) - return error; - - if (unit & UNIT_ANGLE || unit & UNIT_TIME || unit & UNIT_FREQ) - return CSS_INVALID; - - value = TEXT_INDENT_SET; - } - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - opv = buildOPV(OP_TEXT_INDENT, flags, value); - - required_size = sizeof(opv); - if ((flags & FLAG_INHERIT) == false && value == TEXT_INDENT_SET) - required_size += sizeof(length) + sizeof(unit); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, required_size, result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - if ((flags & FLAG_INHERIT) == false && value == TEXT_INDENT_SET) { - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), - &length, sizeof(length)); - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + - sizeof(length), &unit, sizeof(unit)); - } - - return CSS_OK; -} - -css_error parse_text_transform(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *ident; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - - /* IDENT (capitalize, uppercase, lowercase, none, inherit) */ - ident = parserutils_vector_iterate(vector, ctx); - if (ident == NULL || ident->type != CSS_TOKEN_IDENT) - return CSS_INVALID; - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - if (ident->lower.data == c->strings[INHERIT]) { - flags |= FLAG_INHERIT; - } else if (ident->lower.data == c->strings[CAPITALIZE]) { - value = TEXT_TRANSFORM_CAPITALIZE; - } else if (ident->lower.data == c->strings[UPPERCASE]) { - value = TEXT_TRANSFORM_UPPERCASE; - } else if (ident->lower.data == c->strings[LOWERCASE]) { - value = TEXT_TRANSFORM_LOWERCASE; - } else if (ident->lower.data == c->strings[NONE]) { - value = TEXT_TRANSFORM_NONE; - } else - return CSS_INVALID; - - opv = buildOPV(OP_TEXT_TRANSFORM, flags, value); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - - return CSS_OK; -} - -css_error parse_top(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *token; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - fixed length = 0; - uint32_t unit = 0; - uint32_t required_size; - - /* length | percentage | IDENT(auto, inherit) */ - token = parserutils_vector_peek(vector, *ctx); - if (token == NULL) - return CSS_INVALID; - - if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[INHERIT]) { - parserutils_vector_iterate(vector, ctx); - flags = FLAG_INHERIT; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[AUTO]) { - parserutils_vector_iterate(vector, ctx); - value = TOP_AUTO; - } else { - error = parse_unit_specifier(c, vector, ctx, &length, &unit); - if (error != CSS_OK) - return error; - - if (unit & UNIT_ANGLE || unit & UNIT_TIME || unit & UNIT_FREQ) - return CSS_INVALID; - - value = TOP_SET; - } - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - opv = buildOPV(OP_TOP, flags, value); - - required_size = sizeof(opv); - if ((flags & FLAG_INHERIT) == false && value == TOP_SET) - required_size += sizeof(length) + sizeof(unit); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, required_size, result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - if ((flags & FLAG_INHERIT) == false && value == TOP_SET) { - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), - &length, sizeof(length)); - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + - sizeof(length), &unit, sizeof(unit)); - } - - return CSS_OK; -} - -css_error parse_unicode_bidi(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *ident; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - - /* IDENT (normal, embed, bidi-override, inherit) */ - ident = parserutils_vector_iterate(vector, ctx); - if (ident == NULL || ident->type != CSS_TOKEN_IDENT) - return CSS_INVALID; - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - if (ident->lower.data == c->strings[INHERIT]) { - flags |= FLAG_INHERIT; - } else if (ident->lower.data == c->strings[NORMAL]) { - value = UNICODE_BIDI_NORMAL; - } else if (ident->lower.data == c->strings[EMBED]) { - value = UNICODE_BIDI_EMBED; - } else if (ident->lower.data == c->strings[BIDI_OVERRIDE]) { - value = UNICODE_BIDI_BIDI_OVERRIDE; - } else - return CSS_INVALID; - - opv = buildOPV(OP_UNICODE_BIDI, flags, value); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - - return CSS_OK; -} - -css_error parse_vertical_align(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *token; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - fixed length = 0; - uint32_t unit = 0; - uint32_t required_size; - - /* length | percentage | IDENT(baseline, sub, super, top, text-top, - * middle, bottom, text-bottom, inherit) - */ - token = parserutils_vector_peek(vector, *ctx); - if (token == NULL) - return CSS_INVALID; - - if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[INHERIT]) { - parserutils_vector_iterate(vector, ctx); - flags = FLAG_INHERIT; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[BASELINE]) { - parserutils_vector_iterate(vector, ctx); - value = VERTICAL_ALIGN_BASELINE; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[SUB]) { - parserutils_vector_iterate(vector, ctx); - value = VERTICAL_ALIGN_SUB; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[SUPER]) { - parserutils_vector_iterate(vector, ctx); - value = VERTICAL_ALIGN_SUPER; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[TOP]) { - parserutils_vector_iterate(vector, ctx); - value = VERTICAL_ALIGN_TOP; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[TEXT_TOP]) { - parserutils_vector_iterate(vector, ctx); - value = VERTICAL_ALIGN_TEXT_TOP; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[MIDDLE]) { - parserutils_vector_iterate(vector, ctx); - value = VERTICAL_ALIGN_MIDDLE; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[BOTTOM]) { - parserutils_vector_iterate(vector, ctx); - value = VERTICAL_ALIGN_BOTTOM; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[TEXT_BOTTOM]) { - parserutils_vector_iterate(vector, ctx); - value = VERTICAL_ALIGN_TEXT_BOTTOM; - } else { - error = parse_unit_specifier(c, vector, ctx, &length, &unit); - if (error != CSS_OK) - return error; - - if (unit & UNIT_ANGLE || unit & UNIT_TIME || unit & UNIT_FREQ) - return CSS_INVALID; - - value = VERTICAL_ALIGN_SET; - } - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - opv = buildOPV(OP_VERTICAL_ALIGN, flags, value); - - required_size = sizeof(opv); - if ((flags & FLAG_INHERIT) == false && value == VERTICAL_ALIGN_SET) - required_size += sizeof(length) + sizeof(unit); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, required_size, result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - if ((flags & FLAG_INHERIT) == false && value == VERTICAL_ALIGN_SET) { - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), - &length, sizeof(length)); - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + - sizeof(length), &unit, sizeof(unit)); - } - - return CSS_OK; -} - -css_error parse_visibility(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *ident; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - - /* IDENT (visible, hidden, collapse, inherit) */ - ident = parserutils_vector_iterate(vector, ctx); - if (ident == NULL || ident->type != CSS_TOKEN_IDENT) - return CSS_INVALID; - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - if (ident->lower.data == c->strings[INHERIT]) { - flags |= FLAG_INHERIT; - } else if (ident->lower.data == c->strings[VISIBLE]) { - value = VISIBILITY_VISIBLE; - } else if (ident->lower.data == c->strings[HIDDEN]) { - value = VISIBILITY_HIDDEN; - } else if (ident->lower.data == c->strings[COLLAPSE]) { - value = VISIBILITY_COLLAPSE; - } else - return CSS_INVALID; - - opv = buildOPV(OP_VISIBILITY, flags, value); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - - return CSS_OK; -} - -css_error parse_voice_family(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - /** \todo voice-family */ - - UNUSED(c); - UNUSED(vector); - UNUSED(ctx); - UNUSED(result); - - return CSS_OK; -} - -css_error parse_volume(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *token; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - fixed length = 0; - uint32_t unit = 0; - uint32_t required_size; - - /* number | percentage | IDENT(silent, x-soft, soft, medium, loud, - * x-loud, inherit) - */ - token = parserutils_vector_peek(vector, *ctx); - if (token == NULL) - return CSS_INVALID; - - if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[INHERIT]) { - parserutils_vector_iterate(vector, ctx); - flags = FLAG_INHERIT; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[SILENT]) { - parserutils_vector_iterate(vector, ctx); - value = VOLUME_SILENT; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[X_SOFT]) { - parserutils_vector_iterate(vector, ctx); - value = VOLUME_X_SOFT; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[SOFT]) { - parserutils_vector_iterate(vector, ctx); - value = VOLUME_SOFT; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[MEDIUM]) { - parserutils_vector_iterate(vector, ctx); - value = VOLUME_MEDIUM; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[LOUD]) { - parserutils_vector_iterate(vector, ctx); - value = VOLUME_LOUD; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[X_LOUD]) { - parserutils_vector_iterate(vector, ctx); - value = VOLUME_X_LOUD; - } else if (token->type == CSS_TOKEN_NUMBER) { - size_t consumed = 0; - length = number_from_css_string(&token->lower, &consumed); - if (consumed != token->lower.len) - return CSS_INVALID; - - value = VOLUME_NUMBER; - } else { - error = parse_unit_specifier(c, vector, ctx, &length, &unit); - if (error != CSS_OK) - return error; - - if ((unit & UNIT_PCT) == false) - return CSS_INVALID; - - value = VOLUME_DIMENSION; - } - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - opv = buildOPV(OP_VOLUME, flags, value); - - required_size = sizeof(opv); - if ((flags & FLAG_INHERIT) == false && value == VOLUME_NUMBER) - required_size += sizeof(length); - else if ((flags & FLAG_INHERIT) == false && value == VOLUME_DIMENSION) - required_size += sizeof(length) + sizeof(unit); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, required_size, result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - if ((flags & FLAG_INHERIT) == false && (value == VOLUME_NUMBER || - value == VOLUME_DIMENSION)) - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), - &length, sizeof(length)); - if ((flags & FLAG_INHERIT) == false && value == VOLUME_DIMENSION) - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + - sizeof(length), &unit, sizeof(unit)); - - return CSS_OK; -} - -css_error parse_white_space(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *ident; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - - /* IDENT (normal, pre, nowrap, pre-wrap, pre-line, inherit) */ - ident = parserutils_vector_iterate(vector, ctx); - if (ident == NULL || ident->type != CSS_TOKEN_IDENT) - return CSS_INVALID; - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - if (ident->lower.data == c->strings[INHERIT]) { - flags |= FLAG_INHERIT; - } else if (ident->lower.data == c->strings[NORMAL]) { - value = WHITE_SPACE_NORMAL; - } else if (ident->lower.data == c->strings[PRE]) { - value = WHITE_SPACE_PRE; - } else if (ident->lower.data == c->strings[NOWRAP]) { - value = WHITE_SPACE_NOWRAP; - } else if (ident->lower.data == c->strings[PRE_WRAP]) { - value = WHITE_SPACE_PRE_WRAP; - } else if (ident->lower.data == c->strings[PRE_LINE]) { - value = WHITE_SPACE_PRE_LINE; - } else - return CSS_INVALID; - - opv = buildOPV(OP_WHITE_SPACE, flags, value); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - - return CSS_OK; -} - -css_error parse_widows(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *token; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - fixed num = 0; - uint32_t required_size; - - /* | IDENT (inherit) */ - token = parserutils_vector_iterate(vector, ctx); - if (token == NULL || (token->type != CSS_TOKEN_IDENT && - token->type != CSS_TOKEN_NUMBER)) - return CSS_INVALID; - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - if (token->lower.data == c->strings[INHERIT]) { - flags |= FLAG_INHERIT; - } else if (token->type == CSS_TOKEN_NUMBER) { - size_t consumed = 0; - num = number_from_css_string(&token->lower, &consumed); - int32_t intpart = FIXTOINT(num); - /* Invalid if there are trailing characters or it was a float */ - if (consumed != token->lower.len || num != intpart) - return CSS_INVALID; - - value = WIDOWS_SET; - } else - return CSS_INVALID; - - opv = buildOPV(OP_WIDOWS, flags, value); - - required_size = sizeof(opv); - if ((flags & FLAG_INHERIT) == false && value == WIDOWS_SET) - required_size += sizeof(num); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, required_size, result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - if ((flags & FLAG_INHERIT) == false && value == WIDOWS_SET) { - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), - &num, sizeof(num)); - } - - return CSS_OK; -} - -css_error parse_width(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *token; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - fixed length = 0; - uint32_t unit = 0; - uint32_t required_size; - - /* length | percentage | IDENT(auto, inherit) */ - token = parserutils_vector_peek(vector, *ctx); - if (token == NULL) - return CSS_INVALID; - - if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[INHERIT]) { - parserutils_vector_iterate(vector, ctx); - flags = FLAG_INHERIT; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[AUTO]) { - parserutils_vector_iterate(vector, ctx); - value = WIDTH_AUTO; - } else { - error = parse_unit_specifier(c, vector, ctx, &length, &unit); - if (error != CSS_OK) - return error; - - if (unit & UNIT_ANGLE || unit & UNIT_TIME || unit & UNIT_FREQ) - return CSS_INVALID; - - value = WIDTH_SET; - } - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - opv = buildOPV(OP_WIDTH, flags, value); - - required_size = sizeof(opv); - if ((flags & FLAG_INHERIT) == false && value == WIDTH_SET) - required_size += sizeof(length) + sizeof(unit); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, required_size, result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - if ((flags & FLAG_INHERIT) == false && value == WIDTH_SET) { - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), - &length, sizeof(length)); - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + - sizeof(length), &unit, sizeof(unit)); - } - - return CSS_OK; -} - -css_error parse_word_spacing(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *token; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - fixed length = 0; - uint32_t unit = 0; - uint32_t required_size; - - /* length | IDENT(normal, inherit) */ - token = parserutils_vector_peek(vector, *ctx); - if (token == NULL) - return CSS_INVALID; - - if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[INHERIT]) { - parserutils_vector_iterate(vector, ctx); - flags = FLAG_INHERIT; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[NORMAL]) { - parserutils_vector_iterate(vector, ctx); - value = WORD_SPACING_NORMAL; - } else { - error = parse_unit_specifier(c, vector, ctx, &length, &unit); - if (error != CSS_OK) - return error; - - if (unit & UNIT_ANGLE || unit & UNIT_TIME || unit & UNIT_FREQ || - unit & UNIT_PCT) - return CSS_INVALID; - - value = WORD_SPACING_SET; - } - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - opv = buildOPV(OP_WORD_SPACING, flags, value); - - required_size = sizeof(opv); - if ((flags & FLAG_INHERIT) == false && value == WORD_SPACING_SET) - required_size += sizeof(length) + sizeof(unit); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, required_size, result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - if ((flags & FLAG_INHERIT) == false && value == WORD_SPACING_SET) { - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), - &length, sizeof(length)); - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + - sizeof(length), &unit, sizeof(unit)); - } - - return CSS_OK; -} - -css_error parse_z_index(css_css21 *c, - const parserutils_vector *vector, int *ctx, - css_style **result) -{ - css_error error; - const css_token *token; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - fixed num = 0; - uint32_t required_size; - - /* | IDENT (auto, inherit) */ - token = parserutils_vector_iterate(vector, ctx); - if (token == NULL || (token->type != CSS_TOKEN_IDENT && - token->type != CSS_TOKEN_NUMBER)) - return CSS_INVALID; - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[INHERIT]) { - flags |= FLAG_INHERIT; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[AUTO]) { - value = Z_INDEX_AUTO; - } else if (token->type == CSS_TOKEN_NUMBER) { - size_t consumed = 0; - num = number_from_css_string(&token->lower, &consumed); - int32_t intpart = FIXTOINT(num); - /* Invalid if there are trailing characters or it was a float */ - if (consumed != token->lower.len || num != intpart) - return CSS_INVALID; - - value = Z_INDEX_SET; - } else - return CSS_INVALID; - - opv = buildOPV(OP_Z_INDEX, flags, value); - - required_size = sizeof(opv); - if ((flags & FLAG_INHERIT) == false && value == Z_INDEX_SET) - required_size += sizeof(num); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, required_size, result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - if ((flags & FLAG_INHERIT) == false && value == Z_INDEX_SET) { - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), - &num, sizeof(num)); - } - - return CSS_OK; -} - -css_error parse_important(css_css21 *c, - const parserutils_vector *vector, int *ctx, - uint8_t *result) -{ - const css_token *token; - - consumeWhitespace(vector, ctx); - - token = parserutils_vector_iterate(vector, ctx); - if (token != NULL && tokenIsChar(token, '!')) { - consumeWhitespace(vector, ctx); - - token = parserutils_vector_iterate(vector, ctx); - if (token == NULL || token->type != CSS_TOKEN_IDENT) - return CSS_INVALID; - - if (token->lower.data == c->strings[IMPORTANT]) - *result |= FLAG_IMPORTANT; - } else if (token != NULL) - return CSS_INVALID; - - return CSS_OK; -} - -css_error parse_colour_specifier(css_css21 *c, - const parserutils_vector *vector, int *ctx, - uint32_t *result) -{ - const css_token *token; - - UNUSED(c); - UNUSED(result); - - /** \todo Parse colours */ - - /* For now, consume everything up to the end of the declaration or !, - * whichever comes first */ - while ((token = parserutils_vector_peek(vector, *ctx)) != NULL && - tokenIsChar(token, '!') == false) - parserutils_vector_iterate(vector, ctx); - - return CSS_OK; -} - -css_error parse_unit_specifier(css_css21 *c, - const parserutils_vector *vector, int *ctx, - fixed *length, uint32_t *unit) -{ - const css_token *token; - - UNUSED(c); - UNUSED(length); - UNUSED(unit); - - /** \todo Parse units */ - - /* For now, consume everything up to the end of the declaration or !, - * whichever comes first */ - while ((token = parserutils_vector_peek(vector, *ctx)) != NULL && - tokenIsChar(token, '!') == false) - parserutils_vector_iterate(vector, ctx); - - return CSS_OK; -} - -css_error parse_border_side_color(css_css21 *c, - const parserutils_vector *vector, int *ctx, - uint16_t side, css_style **result) -{ - css_error error; - const css_token *token; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - uint32_t colour = 0; - uint32_t required_size; - - /* colour | IDENT (transparent, inherit) */ - token= parserutils_vector_peek(vector, *ctx); - if (token == NULL) - return CSS_INVALID; - - if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[INHERIT]) { - parserutils_vector_iterate(vector, ctx); - flags |= FLAG_INHERIT; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[TRANSPARENT]) { - parserutils_vector_iterate(vector, ctx); - value = BORDER_COLOR_TRANSPARENT; - } else { - error = parse_colour_specifier(c, vector, ctx, &colour); - if (error != CSS_OK) - return error; - - value = BORDER_COLOR_SET; - } - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - opv = buildOPV(OP_BORDER_TRBL_COLOR, flags, value | side); - - required_size = sizeof(opv); - if ((flags & FLAG_INHERIT) == false && value == BORDER_COLOR_SET) - required_size += sizeof(colour); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, required_size, result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - if ((flags & FLAG_INHERIT) == false && value == BORDER_COLOR_SET) { - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), - &colour, sizeof(colour)); - } - - return CSS_OK; -} - -css_error parse_border_side_style(css_css21 *c, - const parserutils_vector *vector, int *ctx, - uint16_t side, css_style **result) -{ - css_error error; - const css_token *ident; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - - /* IDENT (none, hidden, dotted, dashed, solid, double, groove, - * ridge, inset, outset, inherit) */ - ident = parserutils_vector_iterate(vector, ctx); - if (ident == NULL || ident->type != CSS_TOKEN_IDENT) - return CSS_INVALID; - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - if (ident->lower.data == c->strings[INHERIT]) { - flags |= FLAG_INHERIT; - } else if (ident->lower.data == c->strings[NONE]) { - value = BORDER_STYLE_NONE; - } else if (ident->lower.data == c->strings[HIDDEN]) { - value = BORDER_STYLE_HIDDEN; - } else if (ident->lower.data == c->strings[DOTTED]) { - value = BORDER_STYLE_DOTTED; - } else if (ident->lower.data == c->strings[DASHED]) { - value = BORDER_STYLE_DASHED; - } else if (ident->lower.data == c->strings[SOLID]) { - value = BORDER_STYLE_SOLID; - } else if (ident->lower.data == c->strings[DOUBLE]) { - value = BORDER_STYLE_DOUBLE; - } else if (ident->lower.data == c->strings[GROOVE]) { - value = BORDER_STYLE_GROOVE; - } else if (ident->lower.data == c->strings[RIDGE]) { - value = BORDER_STYLE_RIDGE; - } else if (ident->lower.data == c->strings[INSET]) { - value = BORDER_STYLE_INSET; - } else if (ident->lower.data == c->strings[OUTSET]) { - value = BORDER_STYLE_OUTSET; - } else - return CSS_INVALID; - - opv = buildOPV(OP_BORDER_TRBL_STYLE, flags, value | side); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - - return CSS_OK; -} - -css_error parse_border_side_width(css_css21 *c, - const parserutils_vector *vector, int *ctx, - uint16_t side, css_style **result) -{ - css_error error; - const css_token *token; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - fixed length = 0; - uint32_t unit = 0; - uint32_t required_size; - - /* length | IDENT(thin, medium, thick, inherit) */ - token= parserutils_vector_peek(vector, *ctx); - if (token == NULL) - return CSS_INVALID; - - if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[INHERIT]) { - parserutils_vector_iterate(vector, ctx); - flags |= FLAG_INHERIT; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[THIN]) { - parserutils_vector_iterate(vector, ctx); - value = BORDER_WIDTH_THIN; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[MEDIUM]) { - parserutils_vector_iterate(vector, ctx); - value = BORDER_WIDTH_MEDIUM; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[THICK]) { - parserutils_vector_iterate(vector, ctx); - value = BORDER_WIDTH_THICK; - } else { - error = parse_unit_specifier(c, vector, ctx, &length, &unit); - if (error != CSS_OK) - return error; - - if (unit == UNIT_PCT || unit & UNIT_ANGLE || - unit & UNIT_TIME || unit & UNIT_FREQ) - return CSS_INVALID; - - value = BORDER_WIDTH_SET; - } - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - opv = buildOPV(OP_BORDER_TRBL_WIDTH, flags, value | side); - - required_size = sizeof(opv); - if ((flags & FLAG_INHERIT) == false && value == BORDER_WIDTH_SET) - required_size += sizeof(length) + sizeof(unit); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, required_size, result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - if ((flags & FLAG_INHERIT) == false && value == BORDER_WIDTH_SET) { - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), - &length, sizeof(length)); - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + - sizeof(length), &unit, sizeof(unit)); - } - - return CSS_OK; -} - -css_error parse_margin_side(css_css21 *c, - const parserutils_vector *vector, int *ctx, - uint16_t side, css_style **result) -{ - css_error error; - const css_token *token; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - fixed length = 0; - uint32_t unit = 0; - uint32_t required_size; - - /* length | percentage | IDENT(auto, inherit) */ - token = parserutils_vector_peek(vector, *ctx); - if (token == NULL) - return CSS_INVALID; - - if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[INHERIT]) { - parserutils_vector_iterate(vector, ctx); - flags = FLAG_INHERIT; - } else if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[AUTO]) { - parserutils_vector_iterate(vector, ctx); - value = MARGIN_AUTO; - } else { - error = parse_unit_specifier(c, vector, ctx, &length, &unit); - if (error != CSS_OK) - return error; - - if (unit & UNIT_ANGLE || unit & UNIT_TIME || unit & UNIT_FREQ) - return CSS_INVALID; - - value = MARGIN_SET; - } - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - opv = buildOPV(OP_MARGIN_TRBL, flags, value | side); - - required_size = sizeof(opv); - if ((flags & FLAG_INHERIT) == false && value == MARGIN_SET) - required_size += sizeof(length) + sizeof(unit); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, required_size, result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - if ((flags & FLAG_INHERIT) == false && value == MARGIN_SET) { - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), - &length, sizeof(length)); - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + - sizeof(length), &unit, sizeof(unit)); - } - - return CSS_OK; -} - -css_error parse_padding_side(css_css21 *c, - const parserutils_vector *vector, int *ctx, - uint16_t side, css_style **result) -{ - css_error error; - const css_token *token; - uint8_t flags = 0; - uint16_t value = 0; - uint32_t opv; - fixed length = 0; - uint32_t unit = 0; - uint32_t required_size; - - /* length | percentage | IDENT(inherit) */ - token = parserutils_vector_peek(vector, *ctx); - if (token == NULL) - return CSS_INVALID; - - if (token->type == CSS_TOKEN_IDENT && - token->lower.data == c->strings[INHERIT]) { - parserutils_vector_iterate(vector, ctx); - flags = FLAG_INHERIT; - } else { - error = parse_unit_specifier(c, vector, ctx, &length, &unit); - if (error != CSS_OK) - return error; - - if (unit & UNIT_ANGLE || unit & UNIT_TIME || unit & UNIT_FREQ) - return CSS_INVALID; - - value = PADDING_SET; - } - - error = parse_important(c, vector, ctx, &flags); - if (error != CSS_OK) - return error; - - opv = buildOPV(OP_PADDING_TRBL, flags, value | side); - - required_size = sizeof(opv); - if ((flags & FLAG_INHERIT) == false && value == PADDING_SET) - required_size += sizeof(length) + sizeof(unit); - - /* Allocate result */ - error = css_stylesheet_style_create(c->sheet, required_size, result); - if (error != CSS_OK) - return error; - - /* Copy the bytecode to it */ - memcpy((*result)->bytecode, &opv, sizeof(opv)); - if ((flags & FLAG_INHERIT) == false && value == PADDING_SET) { - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), - &length, sizeof(length)); - memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + - sizeof(length), &unit, sizeof(unit)); - } - - return CSS_OK; -} - - -#endif diff --git a/src/parse/language.c b/src/parse/language.c new file mode 100644 index 0000000..4273658 --- /dev/null +++ b/src/parse/language.c @@ -0,0 +1,1002 @@ +/* + * This file is part of LibCSS. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2008 John-Mark Bell + */ + +#include +#include + +#include + +#include "stylesheet.h" +#include "lex/lex.h" +#include "parse/language.h" +#include "parse/parse.h" +#include "parse/propstrings.h" + +#include "utils/parserutilserror.h" +#include "utils/utils.h" + +typedef struct context_entry { + css_parser_event type; /**< Type of entry */ + void *data; /**< Data for context */ +} context_entry; + +/** + * Context for a CSS language parser + */ +struct css_language { + css_stylesheet *sheet; /**< The stylesheet to parse for */ + +#define STACK_CHUNK 32 + parserutils_stack *context; /**< Context stack */ + + enum { + BEFORE_CHARSET, + BEFORE_RULES, + HAD_RULE, + } state; /**< State flag, for at-rule handling */ + + /** \todo These should be statically allocated */ + const uint8_t *strings[LAST_KNOWN]; /**< Interned strings */ + + css_alloc alloc; /**< Memory (de)allocation function */ + void *pw; /**< Client's private data */ +}; + +/* Event handlers */ +static css_error language_handle_event(css_parser_event type, + const parserutils_vector *tokens, void *pw); +static inline css_error handleStartStylesheet(css_language *c, + const parserutils_vector *vector); +static inline css_error handleEndStylesheet(css_language *c, + const parserutils_vector *vector); +static inline css_error handleStartRuleset(css_language *c, + const parserutils_vector *vector); +static inline css_error handleEndRuleset(css_language *c, + const parserutils_vector *vector); +static inline css_error handleStartAtRule(css_language *c, + const parserutils_vector *vector); +static inline css_error handleEndAtRule(css_language *c, + const parserutils_vector *vector); +static inline css_error handleStartBlock(css_language *c, + const parserutils_vector *vector); +static inline css_error handleEndBlock(css_language *c, + const parserutils_vector *vector); +static inline css_error handleBlockContent(css_language *c, + const parserutils_vector *vector); +static inline css_error handleDeclaration(css_language *c, + const parserutils_vector *vector); + +/* Selector list parsing */ +static inline css_error parseClass(css_language *c, + const parserutils_vector *vector, int *ctx, + css_selector_detail **specific); +static inline css_error parseAttrib(css_language *c, + const parserutils_vector *vector, int *ctx, + css_selector_detail **specific); +static inline css_error parsePseudo(css_language *c, + const parserutils_vector *vector, int *ctx, + css_selector_detail **specific); +static inline css_error parseSpecific(css_language *c, + const parserutils_vector *vector, int *ctx, + css_selector **parent); +static inline css_error parseSelectorSpecifics(css_language *c, + const parserutils_vector *vector, int *ctx, + css_selector **parent); +static inline css_error parseSimpleSelector(css_language *c, + const parserutils_vector *vector, int *ctx, + css_selector **result); +static inline css_error parseCombinator(css_language *c, + const parserutils_vector *vector, int *ctx, + css_combinator *result); +static inline css_error parseSelector(css_language *c, + const parserutils_vector *vector, int *ctx, + css_selector **result); +static inline css_error parseSelectorList(css_language *c, + const parserutils_vector *vector, css_rule *rule); + +/* Declaration parsing */ +static inline css_error parseProperty(css_language *c, + const css_token *property, const parserutils_vector *vector, + int *ctx, css_rule *rule); + +/* Helpers */ +static inline void consumeWhitespace(const parserutils_vector *vector, + int *ctx); +static inline bool tokenIsChar(const css_token *token, uint8_t c); + +/** + * Create a CSS language parser + * + * \param sheet The stylesheet object to parse for + * \param parser The core parser object to use + * \param alloc Memory (de)allocation function + * \param pw Pointer to client-specific private data + * \param language Pointer to location to receive parser object + * \return CSS_OK on success, + * CSS_BADPARM on bad parameters, + * CSS_NOMEM on memory exhaustion + */ +css_error css_language_create(css_stylesheet *sheet, css_parser *parser, + css_alloc alloc, void *pw, void **language) +{ + css_language *c; + css_parser_optparams params; + parserutils_error perror; + css_error error; + + if (sheet == NULL || parser == NULL || alloc == NULL || + language == NULL) + return CSS_BADPARM; + + c = alloc(NULL, sizeof(css_language), pw); + if (c == NULL) + return CSS_NOMEM; + + perror = parserutils_stack_create(sizeof(context_entry), + STACK_CHUNK, (parserutils_alloc) alloc, pw, + &c->context); + if (perror != PARSERUTILS_OK) { + alloc(c, 0, pw); + return css_error_from_parserutils_error(perror); + } + + /* Intern all known strings */ + for (int i = 0; i < LAST_KNOWN; i++) { + c->strings[i] = css_parser_dict_add(parser, + (const uint8_t *) stringmap[i].data, + stringmap[i].len); + if (c->strings[i] == NULL) { + parserutils_stack_destroy(c->context); + alloc(c, 0, pw); + return CSS_NOMEM; + } + } + + params.event_handler.handler = language_handle_event; + params.event_handler.pw = c; + error = css_parser_setopt(parser, CSS_PARSER_EVENT_HANDLER, ¶ms); + if (error != CSS_OK) { + parserutils_stack_destroy(c->context); + alloc(c, 0, pw); + return error; + } + + c->sheet = sheet; + c->state = BEFORE_CHARSET; + c->alloc = alloc; + c->pw = pw; + + *language = c; + + return CSS_OK; +} + +/** + * Destroy a CSS language parser + * + * \param language The parser to destroy + * \return CSS_OK on success, appropriate error otherwise + */ +css_error css_language_destroy(css_language *language) +{ + if (language == NULL) + return CSS_BADPARM; + + parserutils_stack_destroy(language->context); + + language->alloc(language, 0, language->pw); + + return CSS_OK; +} + +/** + * Handler for core parser events + * + * \param type The event type + * \param tokens Vector of tokens read since last event, or NULL + * \param pw Pointer to handler context + * \return CSS_OK on success, CSS_INVALID to indicate parse error, + * appropriate error otherwise. + */ +css_error language_handle_event(css_parser_event type, + const parserutils_vector *tokens, void *pw) +{ + css_language *language = (css_language *) pw; + + switch (type) { + case CSS_PARSER_START_STYLESHEET: + return handleStartStylesheet(language, tokens); + case CSS_PARSER_END_STYLESHEET: + return handleEndStylesheet(language, tokens); + case CSS_PARSER_START_RULESET: + return handleStartRuleset(language, tokens); + case CSS_PARSER_END_RULESET: + return handleEndRuleset(language, tokens); + case CSS_PARSER_START_ATRULE: + return handleStartAtRule(language, tokens); + case CSS_PARSER_END_ATRULE: + return handleEndAtRule(language, tokens); + case CSS_PARSER_START_BLOCK: + return handleStartBlock(language, tokens); + case CSS_PARSER_END_BLOCK: + return handleEndBlock(language, tokens); + case CSS_PARSER_BLOCK_CONTENT: + return handleBlockContent(language, tokens); + case CSS_PARSER_DECLARATION: + return handleDeclaration(language, tokens); + } + + return CSS_OK; +} + +/****************************************************************************** + * Parser stages * + ******************************************************************************/ + +css_error handleStartStylesheet(css_language *c, + const parserutils_vector *vector) +{ + parserutils_error perror; + context_entry entry = { CSS_PARSER_START_STYLESHEET, NULL }; + + UNUSED(vector); + + assert(c != NULL); + + perror = parserutils_stack_push(c->context, (void *) &entry); + if (perror != PARSERUTILS_OK) { + return css_error_from_parserutils_error(perror); + } + + return CSS_OK; +} + +css_error handleEndStylesheet(css_language *c, const parserutils_vector *vector) +{ + parserutils_error perror; + context_entry *entry; + + UNUSED(vector); + + assert(c != NULL); + + entry = parserutils_stack_get_current(c->context); + if (entry == NULL || entry->type != CSS_PARSER_START_STYLESHEET) + return CSS_INVALID; + + perror = parserutils_stack_pop(c->context, NULL); + if (perror != PARSERUTILS_OK) { + return css_error_from_parserutils_error(perror); + } + + return CSS_OK; +} + +css_error handleStartRuleset(css_language *c, const parserutils_vector *vector) +{ + parserutils_error perror; + css_error error; + context_entry entry = { CSS_PARSER_START_RULESET, NULL }; + css_rule *rule = NULL; + + assert(c != NULL); + + error = css_stylesheet_rule_create(c->sheet, CSS_RULE_SELECTOR, &rule); + if (error != CSS_OK) + return error; + + error = parseSelectorList(c, vector, rule); + if (error != CSS_OK) { + css_stylesheet_rule_destroy(c->sheet, rule); + return error; + } + + entry.data = rule; + + perror = parserutils_stack_push(c->context, (void *) &entry); + if (perror != PARSERUTILS_OK) { + css_stylesheet_rule_destroy(c->sheet, rule); + return css_error_from_parserutils_error(perror); + } + + error = css_stylesheet_add_rule(c->sheet, rule); + if (error != CSS_OK) { + parserutils_stack_pop(c->context, NULL); + css_stylesheet_rule_destroy(c->sheet, rule); + return error; + } + + /* Rule is now owned by the sheet, so no need to destroy it */ + + return CSS_OK; +} + +css_error handleEndRuleset(css_language *c, const parserutils_vector *vector) +{ + parserutils_error perror; + context_entry *entry; + + UNUSED(vector); + + assert(c != NULL); + + entry = parserutils_stack_get_current(c->context); + if (entry == NULL || entry->type != CSS_PARSER_START_RULESET) + return CSS_INVALID; + + perror = parserutils_stack_pop(c->context, NULL); + if (perror != PARSERUTILS_OK) { + return css_error_from_parserutils_error(perror); + } + + return CSS_OK; +} + +css_error handleStartAtRule(css_language *c, const parserutils_vector *vector) +{ + parserutils_error perror; + context_entry entry = { CSS_PARSER_START_ATRULE, NULL }; + + assert(c != NULL); + + /* vector contains: ATKEYWORD ws any0 */ + const css_token *token = NULL; + const css_token *atkeyword = NULL; + int32_t ctx = 0; + + atkeyword = parserutils_vector_iterate(vector, &ctx); + + consumeWhitespace(vector, &ctx); + + /* We now have an ATKEYWORD and the context for the start of any0, if + * there is one */ + assert(atkeyword != NULL && atkeyword->type == CSS_TOKEN_ATKEYWORD); + + if (atkeyword->lower.data == c->strings[CHARSET]) { + if (c->state == BEFORE_CHARSET) { + /* any0 = STRING */ + if (ctx == 0) + return CSS_INVALID; + + token = parserutils_vector_iterate(vector, &ctx); + if (token == NULL || token->type != CSS_TOKEN_STRING) + return CSS_INVALID; + + token = parserutils_vector_iterate(vector, &ctx); + if (token != NULL) + return CSS_INVALID; + + c->state = BEFORE_RULES; + } else { + return CSS_INVALID; + } + } else if (atkeyword->lower.data == c->strings[IMPORT]) { + if (c->state != HAD_RULE) { + /* any0 = (STRING | URI) ws + * (IDENT ws (',' ws IDENT ws)* )? */ + const css_token *uri = + parserutils_vector_iterate(vector, &ctx); + if (uri == NULL || (uri->type != CSS_TOKEN_STRING && + uri->type != CSS_TOKEN_URI)) + return CSS_INVALID; + + consumeWhitespace(vector, &ctx); + + /** \todo Media list */ + if (parserutils_vector_peek(vector, ctx) != NULL) { + } + + /** \todo trigger fetch of imported sheet */ + + c->state = BEFORE_RULES; + } else { + return CSS_INVALID; + } +#if 0 + /** \todo these depend on nested block support, so we'll disable them + * until we have such a thing. This means that we'll ignore the entire + * at-rule until then */ + } else if (atkeyword->lower.data == c->strings[MEDIA]) { + /** \todo any0 = IDENT ws (',' ws IDENT ws)* */ + } else if (atkeyword->lower.data == c->strings[PAGE]) { + /** \todo any0 = (':' IDENT)? ws */ +#endif + } else { + return CSS_INVALID; + } + + entry.data = atkeyword->lower.data; + + perror = parserutils_stack_push(c->context, (void *) &entry); + if (perror != PARSERUTILS_OK) { + return css_error_from_parserutils_error(perror); + } + + return CSS_OK; +} + +css_error handleEndAtRule(css_language *c, const parserutils_vector *vector) +{ + parserutils_error perror; + context_entry *entry; + + UNUSED(vector); + + assert(c != NULL); + + entry = parserutils_stack_get_current(c->context); + if (entry == NULL || entry->type != CSS_PARSER_START_ATRULE) + return CSS_INVALID; + + perror = parserutils_stack_pop(c->context, NULL); + if (perror != PARSERUTILS_OK) { + return css_error_from_parserutils_error(perror); + } + + return CSS_OK; +} + +css_error handleStartBlock(css_language *c, const parserutils_vector *vector) +{ + UNUSED(c); + UNUSED(vector); + + /* We don't care about blocks. In CSS2.1 they're always attached to + * rulesets or at-rules. */ + + return CSS_OK; +} + +css_error handleEndBlock(css_language *c, const parserutils_vector *vector) +{ + UNUSED(c); + UNUSED(vector); + + /* We don't care about blocks. In CSS 2.1 they're always attached to + * rulesets or at-rules. */ + + return CSS_OK; +} + +css_error handleBlockContent(css_language *c, const parserutils_vector *vector) +{ + UNUSED(c); + UNUSED(vector); + + /* In CSS 2.1, block content comprises either declarations (if the + * current block is associated with @page or a selector), or rulesets + * (if the current block is associated with @media). */ + + /** \todo implement nested blocks */ + + return CSS_OK; +} + +css_error handleDeclaration(css_language *c, const parserutils_vector *vector) +{ + css_error error; + const css_token *token, *ident; + int ctx = 0; + context_entry *entry; + css_rule *rule; + + /* Locations where declarations are permitted: + * + * + In @page + * + In ruleset + */ + entry = parserutils_stack_get_current(c->context); + if (entry == NULL || (entry->type != CSS_PARSER_START_RULESET && + entry->type != CSS_PARSER_START_ATRULE)) + return CSS_INVALID; + + rule = entry->data; + if (rule == NULL || (rule->type != CSS_RULE_SELECTOR && + rule->type != CSS_RULE_PAGE)) + return CSS_INVALID; + + /* IDENT ws ':' ws value + * + * In CSS 2.1, value is any1, so '{' or ATKEYWORD => parse error + */ + ident = parserutils_vector_iterate(vector, &ctx); + if (ident == NULL || ident->type != CSS_TOKEN_IDENT) + return CSS_INVALID; + + consumeWhitespace(vector, &ctx); + + token = parserutils_vector_iterate(vector, &ctx); + if (token == NULL || tokenIsChar(token, ':') == false) + return CSS_INVALID; + + consumeWhitespace(vector, &ctx); + + error = parseProperty(c, ident, vector, &ctx, rule); + if (error != CSS_OK) + return error; + + return CSS_OK; +} + +/****************************************************************************** + * Selector list parsing functions * + ******************************************************************************/ + +css_error parseClass(css_language *c, const parserutils_vector *vector, + int *ctx, css_selector_detail **specific) +{ + const css_token *token; + + /* class -> '.' IDENT */ + token = parserutils_vector_iterate(vector, ctx); + if (token == NULL || tokenIsChar(token, '.') == false) + return CSS_INVALID; + + token = parserutils_vector_iterate(vector, ctx); + if (token == NULL || token->type != CSS_TOKEN_IDENT) + return CSS_INVALID; + + return css_stylesheet_selector_detail_create(c->sheet, + CSS_SELECTOR_CLASS, &token->data, NULL, specific); +} + +css_error parseAttrib(css_language *c, const parserutils_vector *vector, + int *ctx, css_selector_detail **specific) +{ + const css_token *token, *name, *value = NULL; + css_selector_type type = CSS_SELECTOR_ATTRIBUTE; + + /* attrib -> '[' ws IDENT ws [ + * [ '=' | INCLUDES | DASHMATCH ] ws + * [ IDENT | STRING ] ws ]? ']' + */ + token = parserutils_vector_iterate(vector, ctx); + if (token == NULL || tokenIsChar(token, '[') == false) + return CSS_INVALID; + + consumeWhitespace(vector, ctx); + + token = parserutils_vector_iterate(vector, ctx); + if (token == NULL || token->type != CSS_TOKEN_IDENT) + return CSS_INVALID; + + name = token; + + consumeWhitespace(vector, ctx); + + token = parserutils_vector_iterate(vector, ctx); + if (token == NULL) + return CSS_INVALID; + + if (tokenIsChar(token, ']') == false) { + if (tokenIsChar(token, '=')) + type = CSS_SELECTOR_ATTRIBUTE_EQUAL; + else if (token->type == CSS_TOKEN_INCLUDES) + type = CSS_SELECTOR_ATTRIBUTE_INCLUDES; + else if (token->type == CSS_TOKEN_DASHMATCH) + type = CSS_SELECTOR_ATTRIBUTE_DASHMATCH; + else + return CSS_INVALID; + + consumeWhitespace(vector, ctx); + + token = parserutils_vector_iterate(vector, ctx); + if (token == NULL || (token->type != CSS_TOKEN_IDENT && + token->type != CSS_TOKEN_STRING)) + return CSS_INVALID; + + value = token; + + consumeWhitespace(vector, ctx); + + token = parserutils_vector_iterate(vector, ctx); + if (token == NULL || tokenIsChar(token, ']') == false) + return CSS_INVALID; + } + + return css_stylesheet_selector_detail_create(c->sheet, type, + &name->data, value != NULL ? &value->data : NULL, + specific); +} + +css_error parsePseudo(css_language *c, const parserutils_vector *vector, + int *ctx, css_selector_detail **specific) +{ + const css_token *token, *name, *value = NULL; + + /* pseudo -> ':' [ IDENT | FUNCTION ws IDENT? ws ')' ] */ + + token = parserutils_vector_iterate(vector, ctx); + if (token == NULL || tokenIsChar(token, ':') == false) + return CSS_INVALID; + + token = parserutils_vector_iterate(vector, ctx); + if (token == NULL || (token->type != CSS_TOKEN_IDENT && + token->type != CSS_TOKEN_FUNCTION)) + return CSS_INVALID; + + name = token; + + if (token->type == CSS_TOKEN_FUNCTION) { + consumeWhitespace(vector, ctx); + + token = parserutils_vector_iterate(vector, ctx); + + if (token != NULL && token->type == CSS_TOKEN_IDENT) { + value = token; + + consumeWhitespace(vector, ctx); + + token = parserutils_vector_iterate(vector, ctx); + } + + if (token == NULL || tokenIsChar(token, ')') == false) + return CSS_INVALID; + } + + return css_stylesheet_selector_detail_create(c->sheet, + CSS_SELECTOR_PSEUDO, &name->data, + value != NULL ? &value->data : NULL, specific); +} + +css_error parseSpecific(css_language *c, + const parserutils_vector *vector, int *ctx, + css_selector **parent) +{ + css_error error; + const css_token *token; + css_selector_detail *specific = NULL; + + /* specific -> [ HASH | class | attrib | pseudo ] */ + + token = parserutils_vector_peek(vector, *ctx); + if (token == NULL) + return CSS_INVALID; + + if (token->type == CSS_TOKEN_HASH) { + error = css_stylesheet_selector_detail_create(c->sheet, + CSS_SELECTOR_ID, &token->data, NULL, &specific); + if (error != CSS_OK) + return error; + + parserutils_vector_iterate(vector, ctx); + } else if (tokenIsChar(token, '.')) { + error = parseClass(c, vector, ctx, &specific); + if (error != CSS_OK) + return error; + } else if (tokenIsChar(token, '[')) { + error = parseAttrib(c, vector, ctx, &specific); + if (error != CSS_OK) + return error; + } else if (tokenIsChar(token, ':')) { + error = parsePseudo(c, vector, ctx, &specific); + if (error != CSS_OK) + return error; + } else { + return CSS_INVALID; + } + + error = css_stylesheet_selector_append_specific(c->sheet, parent, + specific); + if (error != CSS_OK) { + css_stylesheet_selector_detail_destroy(c->sheet, specific); + return error; + } + + return CSS_OK; +} + +css_error parseSelectorSpecifics(css_language *c, + const parserutils_vector *vector, int *ctx, + css_selector **parent) +{ + css_error error; + const css_token *token; + + /* specifics -> specific* */ + while ((token = parserutils_vector_peek(vector, *ctx)) != NULL && + token->type != CSS_TOKEN_S && + tokenIsChar(token, '+') == false && + tokenIsChar(token, '>') == false && + tokenIsChar(token, ',') == false) { + error = parseSpecific(c, vector, ctx, parent); + if (error != CSS_OK) + return error; + } + + return CSS_OK; +} + +css_error parseSimpleSelector(css_language *c, + const parserutils_vector *vector, int *ctx, + css_selector **result) +{ + css_error error; + const css_token *token; + css_selector *selector; + + /* simple_selector -> element_name specifics + * -> specific specifics + * element_name -> IDENT | '*' + */ + + token = parserutils_vector_peek(vector, *ctx); + if (token == NULL) + return CSS_INVALID; + + if (token->type == CSS_TOKEN_IDENT || tokenIsChar(token, '*')) { + /* Have element name */ + error = css_stylesheet_selector_create(c->sheet, + CSS_SELECTOR_ELEMENT, &token->data, NULL, + &selector); + if (error != CSS_OK) + return error; + + parserutils_vector_iterate(vector, ctx); + } else { + /* Universal selector */ + static css_string name = { 1, (uint8_t *) "*" }; + + error = css_stylesheet_selector_create(c->sheet, + CSS_SELECTOR_ELEMENT, &name, NULL, &selector); + if (error != CSS_OK) + return error; + + /* Ensure we have at least one specific selector */ + error = parseSpecific(c, vector, ctx, &selector); + if (error != CSS_OK) { + css_stylesheet_selector_destroy(c->sheet, selector); + return error; + } + } + + error = parseSelectorSpecifics(c, vector, ctx, &selector); + if (error != CSS_OK) { + css_stylesheet_selector_destroy(c->sheet, selector); + return error; + } + + *result = selector; + + return CSS_OK; +} + +css_error parseCombinator(css_language *c, const parserutils_vector *vector, + int *ctx, css_combinator *result) +{ + const css_token *token; + css_combinator comb = CSS_COMBINATOR_NONE; + + /* combinator -> ws '+' ws | ws '>' ws | ws1 */ + + UNUSED(c); + + while ((token = parserutils_vector_peek(vector, *ctx)) != NULL) { + if (tokenIsChar(token, '+')) + comb = CSS_COMBINATOR_SIBLING; + else if (tokenIsChar(token, '>')) + comb = CSS_COMBINATOR_PARENT; + else if (token->type == CSS_TOKEN_S) + comb = CSS_COMBINATOR_ANCESTOR; + else + break; + + parserutils_vector_iterate(vector, ctx); + + /* If we've seen a '+' or '>', we're done. */ + if (comb != CSS_COMBINATOR_ANCESTOR) + break; + } + + /* No valid combinator found */ + if (comb == CSS_COMBINATOR_NONE) + return CSS_INVALID; + + /* Consume any trailing whitespace */ + consumeWhitespace(vector, ctx); + + *result = comb; + + return CSS_OK; +} + +css_error parseSelector(css_language *c, const parserutils_vector *vector, + int *ctx, css_selector **result) +{ + css_error error; + const css_token *token = NULL; + css_selector *selector = NULL; + + /* selector -> simple_selector [ combinator simple_selector ]* ws + * + * Note, however, that, as combinator can be wholly whitespace, + * there's an ambiguity as to whether "ws" has been reached. We + * resolve this by attempting to extract a combinator, then + * recovering when we detect that we've reached the end of the + * selector. + */ + + error = parseSimpleSelector(c, vector, ctx, &selector); + if (error != CSS_OK) + return error; + *result = selector; + + while ((token = parserutils_vector_peek(vector, *ctx)) != NULL && + tokenIsChar(token, ',') == false) { + css_combinator comb = CSS_COMBINATOR_NONE; + css_selector *other = NULL; + + error = parseCombinator(c, vector, ctx, &comb); + if (error != CSS_OK) + return error; + + /* In the case of "html , body { ... }", the whitespace after + * "html" and "body" will be considered an ancestor combinator. + * This clearly is not the case, however. Therefore, as a + * special case, if we've got an ancestor combinator and there + * are no further tokens, or if the next token is a comma, + * we ignore the supposed combinator and continue. */ + if (comb == CSS_COMBINATOR_ANCESTOR && + ((token = parserutils_vector_peek(vector, + *ctx)) == NULL || + tokenIsChar(token, ','))) + continue; + + error = parseSimpleSelector(c, vector, ctx, &other); + if (error != CSS_OK) + return error; + + *result = other; + + error = css_stylesheet_selector_combine(c->sheet, + comb, selector, other); + if (error != CSS_OK) + return error; + + selector = other; + } + + return CSS_OK; +} + +css_error parseSelectorList(css_language *c, const parserutils_vector *vector, + css_rule *rule) +{ + css_error error; + const css_token *token = NULL; + css_selector *selector = NULL; + int ctx = 0; + + /* selector_list -> selector [ ',' ws selector ]* */ + + error = parseSelector(c, vector, &ctx, &selector); + if (error != CSS_OK) { + if (selector != NULL) + css_stylesheet_selector_destroy(c->sheet, selector); + return error; + } + + assert(selector != NULL); + + error = css_stylesheet_rule_add_selector(c->sheet, rule, selector); + if (error != CSS_OK) { + css_stylesheet_selector_destroy(c->sheet, selector); + return error; + } + + while ((token = parserutils_vector_peek(vector, ctx)) != NULL) { + token = parserutils_vector_iterate(vector, &ctx); + if (tokenIsChar(token, ',') == false) + return CSS_INVALID; + + consumeWhitespace(vector, &ctx); + + selector = NULL; + + error = parseSelector(c, vector, &ctx, &selector); + if (error != CSS_OK) { + if (selector != NULL) { + css_stylesheet_selector_destroy(c->sheet, + selector); + } + return error; + } + + assert(selector != NULL); + + error = css_stylesheet_rule_add_selector(c->sheet, rule, + selector); + if (error != CSS_OK) { + css_stylesheet_selector_destroy(c->sheet, selector); + return error; + } + } + + return CSS_OK; +} + +/****************************************************************************** + * Property parsing functions * + ******************************************************************************/ + +#include "parse/properties.c" + +css_error parseProperty(css_language *c, const css_token *property, + const parserutils_vector *vector, int *ctx, css_rule *rule) +{ + css_error error; + css_prop_handler handler = NULL; + int i = 0; + css_style *style = NULL; + + /* Find property index */ + /** \todo improve on this linear search */ + for (i = FIRST_PROP; i <= LAST_PROP; i++) { + if (property->lower.data == c->strings[i]) + break; + } + if (i == LAST_PROP + 1) + return CSS_INVALID; + + /* Get handler */ + handler = property_handlers[i - FIRST_PROP]; + assert(handler != NULL); + + /* Call it */ + error = handler(c, vector, ctx, &style); + if (error != CSS_OK) + return error; + + /** \todo we should probably assert this, but until we've implemented + * all the property parsers, this will have to suffice. */ + if (style != NULL) { + /* Append style to rule */ + error = css_stylesheet_rule_append_style(c->sheet, rule, style); + if (error != CSS_OK) { + css_stylesheet_style_destroy(c->sheet, style); + return error; + } + } + + /* Style owned or destroyed by stylesheet, so forget about it */ + + return CSS_OK; +} + +/****************************************************************************** + * Helper functions * + ******************************************************************************/ + +/** + * Consume all leading whitespace tokens + * + * \param vector The vector to consume from + * \param ctx The vector's context + */ +void consumeWhitespace(const parserutils_vector *vector, int *ctx) +{ + const css_token *token = NULL; + + while ((token = parserutils_vector_peek(vector, *ctx)) != NULL && + token->type == CSS_TOKEN_S) + token = parserutils_vector_iterate(vector, ctx); +} + +/** + * Determine if a token is a character + * + * \param token The token to consider + * \param c The character to match (lowercase ASCII only) + * \return True if the token matches, false otherwise + */ +bool tokenIsChar(const css_token *token, uint8_t c) +{ + return token != NULL && token->type == CSS_TOKEN_CHAR && + token->lower.len == 1 && token->lower.data[0] == c; +} + + diff --git a/src/parse/language.h b/src/parse/language.h new file mode 100644 index 0000000..00317c6 --- /dev/null +++ b/src/parse/language.h @@ -0,0 +1,25 @@ +/* + * This file is part of LibCSS. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2008 John-Mark Bell + */ + +#ifndef css_parse_language_h_ +#define css_parse_language_h_ + +#include + +#include +#include + +#include "parse/parse.h" + +typedef struct css_language css_language; + +css_error css_language_create(css_stylesheet *sheet, css_parser *parser, + css_alloc alloc, void *pw, void **language); +css_error css_language_destroy(css_language *language); + +#endif + diff --git a/src/parse/properties.c b/src/parse/properties.c new file mode 100644 index 0000000..aceb720 --- /dev/null +++ b/src/parse/properties.c @@ -0,0 +1,4801 @@ +/* + * This file is part of LibCSS. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2008 John-Mark Bell + */ + +#ifndef css_parse_css21props_c_ +#define css_parse_css21props_c_ + +#include "bytecode/bytecode.h" +#include "bytecode/opcodes.h" + +static css_error parse_azimuth(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_background_attachment(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_background_color(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_background_image(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_background_position(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_background_repeat(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_border_bottom_color(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_border_bottom_style(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_border_bottom_width(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_border_collapse(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_border_left_color(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_border_left_style(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_border_left_width(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_border_right_color(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_border_right_style(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_border_right_width(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_border_spacing(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_border_top_color(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_border_top_style(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_border_top_width(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_bottom(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_caption_side(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_clear(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_clip(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_color(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_content(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_counter_increment(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_counter_reset(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_cue_after(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_cue_before(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_cursor(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_direction(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_display(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_elevation(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_empty_cells(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_float(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_font_family(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_font_size(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_font_style(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_font_variant(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_font_weight(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_height(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_left(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_letter_spacing(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_line_height(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_list_style_image(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_list_style_position(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_list_style_type(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_margin_bottom(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_margin_left(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_margin_right(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_margin_top(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_max_height(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_max_width(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_min_height(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_min_width(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_orphans(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_outline_color(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_outline_style(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_outline_width(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_overflow(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_padding_bottom(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_padding_left(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_padding_right(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_padding_top(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_page_break_after(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_page_break_before(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_page_break_inside(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_pause_after(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_pause_before(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_pitch_range(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_pitch(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_play_during(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_position(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_quotes(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_richness(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_right(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_speak_header(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_speak_numeral(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_speak_punctuation(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_speak(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_speech_rate(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_stress(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_table_layout(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_text_align(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_text_decoration(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_text_indent(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_text_transform(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_top(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_unicode_bidi(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_vertical_align(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_visibility(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_voice_family(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_volume(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_white_space(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_widows(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_width(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_word_spacing(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); +static css_error parse_z_index(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); + +static inline css_error parse_important(css_language *c, + const parserutils_vector *vector, int *ctx, + uint8_t *result); +static inline css_error parse_colour_specifier(css_language *c, + const parserutils_vector *vector, int *ctx, + uint32_t *result); +static inline css_error parse_unit_specifier(css_language *c, + const parserutils_vector *vector, int *ctx, + fixed *length, uint32_t *unit); + +static inline css_error parse_border_side_color(css_language *c, + const parserutils_vector *vector, int *ctx, + uint16_t side, css_style **result); +static inline css_error parse_border_side_style(css_language *c, + const parserutils_vector *vector, int *ctx, + uint16_t side, css_style **result); +static inline css_error parse_border_side_width(css_language *c, + const parserutils_vector *vector, int *ctx, + uint16_t side, css_style **result); +static inline css_error parse_margin_side(css_language *c, + const parserutils_vector *vector, int *ctx, + uint16_t side, css_style **result); +static inline css_error parse_padding_side(css_language *c, + const parserutils_vector *vector, int *ctx, + uint16_t side, css_style **result); + +/** + * Type of property handler function + */ +typedef css_error (*css_prop_handler)(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); + +/** + * Dispatch table of property handlers, indexed by property enum + */ +static const css_prop_handler property_handlers[LAST_PROP + 1 - FIRST_PROP] = +{ + parse_azimuth, + parse_background_attachment, + parse_background_color, + parse_background_image, + parse_background_position, + parse_background_repeat, + parse_border_bottom_color, + parse_border_bottom_style, + parse_border_bottom_width, + parse_border_collapse, + parse_border_left_color, + parse_border_left_style, + parse_border_left_width, + parse_border_right_color, + parse_border_right_style, + parse_border_right_width, + parse_border_spacing, + parse_border_top_color, + parse_border_top_style, + parse_border_top_width, + parse_bottom, + parse_caption_side, + parse_clear, + parse_clip, + parse_color, + parse_content, + parse_counter_increment, + parse_counter_reset, + parse_cue_after, + parse_cue_before, + parse_cursor, + parse_direction, + parse_display, + parse_elevation, + parse_empty_cells, + parse_float, + parse_font_family, + parse_font_size, + parse_font_style, + parse_font_variant, + parse_font_weight, + parse_height, + parse_left, + parse_letter_spacing, + parse_line_height, + parse_list_style_image, + parse_list_style_position, + parse_list_style_type, + parse_margin_bottom, + parse_margin_left, + parse_margin_right, + parse_margin_top, + parse_max_height, + parse_max_width, + parse_min_height, + parse_min_width, + parse_orphans, + parse_outline_color, + parse_outline_style, + parse_outline_width, + parse_overflow, + parse_padding_bottom, + parse_padding_left, + parse_padding_right, + parse_padding_top, + parse_page_break_after, + parse_page_break_before, + parse_page_break_inside, + parse_pause_after, + parse_pause_before, + parse_pitch_range, + parse_pitch, + parse_play_during, + parse_position, + parse_quotes, + parse_richness, + parse_right, + parse_speak_header, + parse_speak_numeral, + parse_speak_punctuation, + parse_speak, + parse_speech_rate, + parse_stress, + parse_table_layout, + parse_text_align, + parse_text_decoration, + parse_text_indent, + parse_text_transform, + parse_top, + parse_unicode_bidi, + parse_vertical_align, + parse_visibility, + parse_voice_family, + parse_volume, + parse_white_space, + parse_widows, + parse_width, + parse_word_spacing, + parse_z_index, +}; + +css_error parse_azimuth(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + /** \todo azimuth */ + UNUSED(c); + UNUSED(vector); + UNUSED(ctx); + UNUSED(result); + + return CSS_OK; +} + +css_error parse_background_attachment(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *ident; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + + /* IDENT (fixed, scroll, inherit) */ + ident = parserutils_vector_iterate(vector, ctx); + if (ident == NULL || ident->type != CSS_TOKEN_IDENT) + return CSS_INVALID; + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + if (ident->lower.data == c->strings[INHERIT]) { + flags |= FLAG_INHERIT; + } else if (ident->lower.data == c->strings[FIXED]) { + value = BACKGROUND_ATTACHMENT_FIXED; + } else if (ident->lower.data == c->strings[SCROLL]) { + value = BACKGROUND_ATTACHMENT_SCROLL; + } else + return CSS_INVALID; + + opv = buildOPV(OP_BACKGROUND_ATTACHMENT, flags, value); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + + return CSS_OK; +} + +css_error parse_background_color(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *token; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + uint32_t colour = 0; + uint32_t required_size; + + /* colour | IDENT (transparent, inherit) */ + token= parserutils_vector_peek(vector, *ctx); + if (token == NULL) + return CSS_INVALID; + + if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[INHERIT]) { + parserutils_vector_iterate(vector, ctx); + flags |= FLAG_INHERIT; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[TRANSPARENT]) { + parserutils_vector_iterate(vector, ctx); + value = BACKGROUND_COLOR_TRANSPARENT; + } else { + error = parse_colour_specifier(c, vector, ctx, &colour); + if (error != CSS_OK) + return error; + + value = BACKGROUND_COLOR_SET; + } + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + opv = buildOPV(OP_BACKGROUND_COLOR, flags, value); + + required_size = sizeof(opv); + if ((flags & FLAG_INHERIT) == false && value == BACKGROUND_COLOR_SET) + required_size += sizeof(colour); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, required_size, result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + if ((flags & FLAG_INHERIT) == false && value == BACKGROUND_COLOR_SET) { + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), + &colour, sizeof(colour)); + } + + return CSS_OK; +} + +css_error parse_background_image(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *token; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + uint32_t required_size; + + /* URI | IDENT (none, inherit) */ + token = parserutils_vector_iterate(vector, ctx); + if (token == NULL || (token->type != CSS_TOKEN_IDENT && + token->type != CSS_TOKEN_URI)) + return CSS_INVALID; + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[INHERIT]) { + flags |= FLAG_INHERIT; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[NONE]) { + value = BACKGROUND_IMAGE_NONE; + } else if (token->type == CSS_TOKEN_URI) { + value = BACKGROUND_IMAGE_URI; + } else + return CSS_INVALID; + + opv = buildOPV(OP_BACKGROUND_IMAGE, flags, value); + + required_size = sizeof(opv); + if ((flags & FLAG_INHERIT) == false && value == BACKGROUND_IMAGE_URI) + required_size += sizeof(uint8_t *) + sizeof(size_t); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, required_size, result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + if ((flags & FLAG_INHERIT) == false && value == BACKGROUND_IMAGE_URI) { + memcpy((uint8_t *) (*result)->bytecode + sizeof(opv), + &token->data.data, sizeof(uint8_t *)); + memcpy((uint8_t *) (*result)->bytecode + sizeof(opv) + + sizeof(uint8_t *), + &token->data.len, sizeof(size_t)); + } + + return CSS_OK; +} + +css_error parse_background_position(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + /** \todo background-position */ + UNUSED(c); + UNUSED(vector); + UNUSED(ctx); + UNUSED(result); + + return CSS_OK; +} + +css_error parse_background_repeat(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *ident; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + + /* IDENT (no-repeat, repeat-x, repeat-y, repeat, inherit) */ + ident = parserutils_vector_iterate(vector, ctx); + if (ident == NULL || ident->type != CSS_TOKEN_IDENT) + return CSS_INVALID; + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + if (ident->lower.data == c->strings[INHERIT]) { + flags |= FLAG_INHERIT; + } else if (ident->lower.data == c->strings[NO_REPEAT]) { + value = BACKGROUND_REPEAT_NO_REPEAT; + } else if (ident->lower.data == c->strings[REPEAT_X]) { + value = BACKGROUND_REPEAT_REPEAT_X; + } else if (ident->lower.data == c->strings[REPEAT_Y]) { + value = BACKGROUND_REPEAT_REPEAT_Y; + } else if (ident->lower.data == c->strings[REPEAT]) { + value = BACKGROUND_REPEAT_REPEAT; + } else + return CSS_INVALID; + + opv = buildOPV(OP_BACKGROUND_REPEAT, flags, value); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + + return CSS_OK; +} + +css_error parse_border_bottom_color(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + return parse_border_side_color(c, vector, ctx, SIDE_BOTTOM, result); +} + +css_error parse_border_bottom_style(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + return parse_border_side_style(c, vector, ctx, SIDE_BOTTOM, result); +} + +css_error parse_border_bottom_width(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + return parse_border_side_width(c, vector, ctx, SIDE_BOTTOM, result); +} + +css_error parse_border_collapse(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *ident; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + + /* IDENT (collapse, separate, inherit) */ + ident = parserutils_vector_iterate(vector, ctx); + if (ident == NULL || ident->type != CSS_TOKEN_IDENT) + return CSS_INVALID; + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + if (ident->lower.data == c->strings[INHERIT]) { + flags |= FLAG_INHERIT; + } else if (ident->lower.data == c->strings[COLLAPSE]) { + value = BORDER_COLLAPSE_COLLAPSE; + } else if (ident->lower.data == c->strings[SEPARATE]) { + value = BORDER_COLLAPSE_SEPARATE; + } else + return CSS_INVALID; + + opv = buildOPV(OP_BORDER_COLLAPSE, flags, value); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + + return CSS_OK; +} + +css_error parse_border_left_color(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + return parse_border_side_color(c, vector, ctx, SIDE_LEFT, result); +} + +css_error parse_border_left_style(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + return parse_border_side_style(c, vector, ctx, SIDE_LEFT, result); +} + +css_error parse_border_left_width(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + return parse_border_side_width(c, vector, ctx, SIDE_LEFT, result); +} + +css_error parse_border_right_color(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + return parse_border_side_color(c, vector, ctx, SIDE_RIGHT, result); +} + +css_error parse_border_right_style(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + return parse_border_side_style(c, vector, ctx, SIDE_RIGHT, result); +} + +css_error parse_border_right_width(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + return parse_border_side_width(c, vector, ctx, SIDE_RIGHT, result); +} + +css_error parse_border_spacing(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + /** \todo border-spacing */ + UNUSED(c); + UNUSED(vector); + UNUSED(ctx); + UNUSED(result); + + return CSS_OK; +} + +css_error parse_border_top_color(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + return parse_border_side_color(c, vector, ctx, SIDE_TOP, result); +} + +css_error parse_border_top_style(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + return parse_border_side_style(c, vector, ctx, SIDE_TOP, result); +} + +css_error parse_border_top_width(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + return parse_border_side_width(c, vector, ctx, SIDE_TOP, result); +} + +css_error parse_bottom(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *token; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + fixed length = 0; + uint32_t unit = 0; + uint32_t required_size; + + /* length | percentage | IDENT(auto, inherit) */ + token = parserutils_vector_peek(vector, *ctx); + if (token == NULL) + return CSS_INVALID; + + if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[INHERIT]) { + parserutils_vector_iterate(vector, ctx); + flags = FLAG_INHERIT; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[AUTO]) { + parserutils_vector_iterate(vector, ctx); + value = BOTTOM_AUTO; + } else { + error = parse_unit_specifier(c, vector, ctx, &length, &unit); + if (error != CSS_OK) + return error; + + if (unit & UNIT_ANGLE || unit & UNIT_TIME || unit & UNIT_FREQ) + return CSS_INVALID; + + value = BOTTOM_SET; + } + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + opv = buildOPV(OP_BOTTOM, flags, value); + + required_size = sizeof(opv); + if ((flags & FLAG_INHERIT) == false && value == BOTTOM_SET) + required_size += sizeof(length) + sizeof(unit); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, required_size, result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + if ((flags & FLAG_INHERIT) == false && value == BOTTOM_SET) { + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), + &length, sizeof(length)); + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + + sizeof(length), &unit, sizeof(unit)); + } + + return CSS_OK; +} + +css_error parse_caption_side(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *ident; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + + /* IDENT (top, bottom, inherit) */ + ident = parserutils_vector_iterate(vector, ctx); + if (ident == NULL || ident->type != CSS_TOKEN_IDENT) + return CSS_INVALID; + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + if (ident->lower.data == c->strings[INHERIT]) { + flags |= FLAG_INHERIT; + } else if (ident->lower.data == c->strings[TOP]) { + value = CAPTION_SIDE_TOP; + } else if (ident->lower.data == c->strings[BOTTOM]) { + value = CAPTION_SIDE_BOTTOM; + } else + return CSS_INVALID; + + opv = buildOPV(OP_CAPTION_SIDE, flags, value); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + + return CSS_OK; +} + +css_error parse_clear(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *ident; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + + /* IDENT (left, right, both, none, inherit) */ + ident = parserutils_vector_iterate(vector, ctx); + if (ident == NULL || ident->type != CSS_TOKEN_IDENT) + return CSS_INVALID; + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + if (ident->lower.data == c->strings[INHERIT]) { + flags |= FLAG_INHERIT; + } else if (ident->lower.data == c->strings[RIGHT]) { + value = CLEAR_RIGHT; + } else if (ident->lower.data == c->strings[LEFT]) { + value = CLEAR_LEFT; + } else if (ident->lower.data == c->strings[BOTH]) { + value = CLEAR_BOTH; + } else if (ident->lower.data == c->strings[NONE]) { + value = CLEAR_NONE; + } else + return CSS_INVALID; + + opv = buildOPV(OP_CLEAR, flags, value); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + + return CSS_OK; +} + +css_error parse_clip(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + /** \todo clip */ + UNUSED(c); + UNUSED(vector); + UNUSED(ctx); + UNUSED(result); + + return CSS_OK; +} + +css_error parse_color(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *token; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + uint32_t colour = 0; + uint32_t required_size; + + /* colour | IDENT (inherit) */ + token= parserutils_vector_peek(vector, *ctx); + if (token == NULL) + return CSS_INVALID; + + if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[INHERIT]) { + parserutils_vector_iterate(vector, ctx); + flags |= FLAG_INHERIT; + } else { + error = parse_colour_specifier(c, vector, ctx, &colour); + if (error != CSS_OK) + return error; + + value = COLOR_SET; + } + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + opv = buildOPV(OP_COLOR, flags, value); + + required_size = sizeof(opv); + if ((flags & FLAG_INHERIT) == false && value == COLOR_SET) + required_size += sizeof(colour); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, required_size, result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + if ((flags & FLAG_INHERIT) == false && value == COLOR_SET) { + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), + &colour, sizeof(colour)); + } + + return CSS_OK; +} + +css_error parse_content(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + /** \todo content */ + UNUSED(c); + UNUSED(vector); + UNUSED(ctx); + UNUSED(result); + + return CSS_OK; +} + +css_error parse_counter_increment(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + /** \todo counter-increment */ + UNUSED(c); + UNUSED(vector); + UNUSED(ctx); + UNUSED(result); + + return CSS_OK; +} + +css_error parse_counter_reset(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + /** \todo counter-reset */ + UNUSED(c); + UNUSED(vector); + UNUSED(ctx); + UNUSED(result); + + return CSS_OK; +} + +css_error parse_cue_after(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *token; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + uint32_t required_size; + + /* URI | IDENT (none, inherit) */ + token = parserutils_vector_iterate(vector, ctx); + if (token == NULL || (token->type != CSS_TOKEN_IDENT && + token->type != CSS_TOKEN_URI)) + return CSS_INVALID; + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[INHERIT]) { + flags |= FLAG_INHERIT; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[NONE]) { + value = CUE_AFTER_NONE; + } else if (token->type == CSS_TOKEN_URI) { + value = CUE_AFTER_URI; + } else + return CSS_INVALID; + + opv = buildOPV(OP_CUE_AFTER, flags, value); + + required_size = sizeof(opv); + if ((flags & FLAG_INHERIT) == false && value == CUE_AFTER_URI) + required_size += sizeof(uint8_t *) + sizeof(size_t); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, required_size, result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + if ((flags & FLAG_INHERIT) == false && value == CUE_AFTER_URI) { + memcpy((uint8_t *) (*result)->bytecode + sizeof(opv), + &token->data.data, sizeof(uint8_t *)); + memcpy((uint8_t *) (*result)->bytecode + sizeof(opv) + + sizeof(uint8_t *), + &token->data.len, sizeof(size_t)); + } + + return CSS_OK; +} + +css_error parse_cue_before(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *token; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + uint32_t required_size; + + /* URI | IDENT (none, inherit) */ + token = parserutils_vector_iterate(vector, ctx); + if (token == NULL || (token->type != CSS_TOKEN_IDENT && + token->type != CSS_TOKEN_URI)) + return CSS_INVALID; + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[INHERIT]) { + flags |= FLAG_INHERIT; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[NONE]) { + value = CUE_BEFORE_NONE; + } else if (token->type == CSS_TOKEN_URI) { + value = CUE_BEFORE_URI; + } else + return CSS_INVALID; + + opv = buildOPV(OP_CUE_BEFORE, flags, value); + + required_size = sizeof(opv); + if ((flags & FLAG_INHERIT) == false && value == CUE_BEFORE_URI) + required_size += sizeof(uint8_t *) + sizeof(size_t); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, required_size, result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + if ((flags & FLAG_INHERIT) == false && value == CUE_BEFORE_URI) { + memcpy((uint8_t *) (*result)->bytecode + sizeof(opv), + &token->data.data, sizeof(uint8_t *)); + memcpy((uint8_t *) (*result)->bytecode + sizeof(opv) + + sizeof(uint8_t *), + &token->data.len, sizeof(size_t)); + } + + return CSS_OK; +} + +css_error parse_cursor(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + /** \todo cursor */ + UNUSED(c); + UNUSED(vector); + UNUSED(ctx); + UNUSED(result); + + return CSS_OK; +} + +css_error parse_direction(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *ident; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + + /* IDENT (ltr, rtl, inherit) */ + ident = parserutils_vector_iterate(vector, ctx); + if (ident == NULL || ident->type != CSS_TOKEN_IDENT) + return CSS_INVALID; + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + if (ident->lower.data == c->strings[INHERIT]) { + flags |= FLAG_INHERIT; + } else if (ident->lower.data == c->strings[LTR]) { + value = DIRECTION_LTR; + } else if (ident->lower.data == c->strings[RTL]) { + value = DIRECTION_RTL; + } else + return CSS_INVALID; + + opv = buildOPV(OP_DIRECTION, flags, value); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + + return CSS_OK; +} + +css_error parse_display(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *ident; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + + /* IDENT (inline, block, list-item, run-in, inline-block, table, + * inline-table, table-row-group, table-header-group, + * table-footer-group, table-row, table-column-group, table-column, + * table-cell, table-caption, none, inherit) */ + ident = parserutils_vector_iterate(vector, ctx); + if (ident == NULL || ident->type != CSS_TOKEN_IDENT) + return CSS_INVALID; + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + if (ident->lower.data == c->strings[INHERIT]) { + flags |= FLAG_INHERIT; + } else if (ident->lower.data == c->strings[INLINE]) { + value = DISPLAY_INLINE; + } else if (ident->lower.data == c->strings[BLOCK]) { + value = DISPLAY_BLOCK; + } else if (ident->lower.data == c->strings[LIST_ITEM]) { + value = DISPLAY_LIST_ITEM; + } else if (ident->lower.data == c->strings[RUN_IN]) { + value = DISPLAY_RUN_IN; + } else if (ident->lower.data == c->strings[INLINE_BLOCK]) { + value = DISPLAY_INLINE_BLOCK; + } else if (ident->lower.data == c->strings[TABLE]) { + value = DISPLAY_TABLE; + } else if (ident->lower.data == c->strings[INLINE_TABLE]) { + value = DISPLAY_INLINE_TABLE; + } else if (ident->lower.data == c->strings[TABLE_ROW_GROUP]) { + value = DISPLAY_TABLE_ROW_GROUP; + } else if (ident->lower.data == c->strings[TABLE_HEADER_GROUP]) { + value = DISPLAY_TABLE_HEADER_GROUP; + } else if (ident->lower.data == c->strings[TABLE_FOOTER_GROUP]) { + value = DISPLAY_TABLE_FOOTER_GROUP; + } else if (ident->lower.data == c->strings[TABLE_ROW]) { + value = DISPLAY_TABLE_ROW; + } else if (ident->lower.data == c->strings[TABLE_COLUMN_GROUP]) { + value = DISPLAY_TABLE_COLUMN_GROUP; + } else if (ident->lower.data == c->strings[TABLE_COLUMN]) { + value = DISPLAY_TABLE_COLUMN; + } else if (ident->lower.data == c->strings[TABLE_CELL]) { + value = DISPLAY_TABLE_CELL; + } else if (ident->lower.data == c->strings[TABLE_CAPTION]) { + value = DISPLAY_TABLE_CAPTION; + } else if (ident->lower.data == c->strings[NONE]) { + value = DISPLAY_NONE; + } else + return CSS_INVALID; + + opv = buildOPV(OP_DISPLAY, flags, value); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + + return CSS_OK; +} + +css_error parse_elevation(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *token; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + fixed length = 0; + uint32_t unit = 0; + uint32_t required_size; + + /* angle | IDENT(below, level, above, higher, lower, inherit) */ + token = parserutils_vector_peek(vector, *ctx); + if (token == NULL) + return CSS_INVALID; + + if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[INHERIT]) { + parserutils_vector_iterate(vector, ctx); + flags = FLAG_INHERIT; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[BELOW]) { + parserutils_vector_iterate(vector, ctx); + value = ELEVATION_BELOW; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[LEVEL]) { + parserutils_vector_iterate(vector, ctx); + value = ELEVATION_LEVEL; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[ABOVE]) { + parserutils_vector_iterate(vector, ctx); + value = ELEVATION_ABOVE; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[HIGHER]) { + parserutils_vector_iterate(vector, ctx); + value = ELEVATION_HIGHER; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[LOWER]) { + parserutils_vector_iterate(vector, ctx); + value = ELEVATION_LOWER; + } else { + error = parse_unit_specifier(c, vector, ctx, &length, &unit); + if (error != CSS_OK) + return error; + + if ((unit & UNIT_ANGLE) == false) + return CSS_INVALID; + + value = ELEVATION_ANGLE; + } + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + opv = buildOPV(OP_ELEVATION, flags, value); + + required_size = sizeof(opv); + if ((flags & FLAG_INHERIT) == false && value == ELEVATION_ANGLE) + required_size += sizeof(length) + sizeof(unit); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, required_size, result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + if ((flags & FLAG_INHERIT) == false && value == ELEVATION_ANGLE) { + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), + &length, sizeof(length)); + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + + sizeof(length), &unit, sizeof(unit)); + } + + return CSS_OK; +} + +css_error parse_empty_cells(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *ident; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + + /* IDENT (show, hide, inherit) */ + ident = parserutils_vector_iterate(vector, ctx); + if (ident == NULL || ident->type != CSS_TOKEN_IDENT) + return CSS_INVALID; + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + if (ident->lower.data == c->strings[INHERIT]) { + flags |= FLAG_INHERIT; + } else if (ident->lower.data == c->strings[SHOW]) { + value = EMPTY_CELLS_SHOW; + } else if (ident->lower.data == c->strings[HIDE]) { + value = EMPTY_CELLS_HIDE; + } else + return CSS_INVALID; + + opv = buildOPV(OP_EMPTY_CELLS, flags, value); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + + return CSS_OK; +} + +css_error parse_float(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *ident; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + + /* IDENT (left, right, none, inherit) */ + ident = parserutils_vector_iterate(vector, ctx); + if (ident == NULL || ident->type != CSS_TOKEN_IDENT) + return CSS_INVALID; + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + if (ident->lower.data == c->strings[INHERIT]) { + flags |= FLAG_INHERIT; + } else if (ident->lower.data == c->strings[LEFT]) { + value = FLOAT_LEFT; + } else if (ident->lower.data == c->strings[RIGHT]) { + value = FLOAT_RIGHT; + } else if (ident->lower.data == c->strings[NONE]) { + value = FLOAT_NONE; + } else + return CSS_INVALID; + + opv = buildOPV(OP_FLOAT, flags, value); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + + return CSS_OK; +} + +css_error parse_font_family(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + /** \todo font-family */ + + UNUSED(c); + UNUSED(vector); + UNUSED(ctx); + UNUSED(result); + + return CSS_OK; +} + +css_error parse_font_size(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *token; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + fixed length = 0; + uint32_t unit = 0; + uint32_t required_size; + + /* length | percentage | IDENT(xx-small, x-small, small, medium, + * large, x-large, xx-large, larger, smaller, inherit) */ + token = parserutils_vector_peek(vector, *ctx); + if (token == NULL) + return CSS_INVALID; + + if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[INHERIT]) { + parserutils_vector_iterate(vector, ctx); + flags = FLAG_INHERIT; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[XX_SMALL]) { + parserutils_vector_iterate(vector, ctx); + value = FONT_SIZE_XX_SMALL; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[X_SMALL]) { + parserutils_vector_iterate(vector, ctx); + value = FONT_SIZE_X_SMALL; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[SMALL]) { + parserutils_vector_iterate(vector, ctx); + value = FONT_SIZE_SMALL; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[MEDIUM]) { + parserutils_vector_iterate(vector, ctx); + value = FONT_SIZE_MEDIUM; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[LARGE]) { + parserutils_vector_iterate(vector, ctx); + value = FONT_SIZE_LARGE; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[X_LARGE]) { + parserutils_vector_iterate(vector, ctx); + value = FONT_SIZE_X_LARGE; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[XX_LARGE]) { + parserutils_vector_iterate(vector, ctx); + value = FONT_SIZE_XX_LARGE; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[LARGER]) { + parserutils_vector_iterate(vector, ctx); + value = FONT_SIZE_LARGER; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[SMALLER]) { + parserutils_vector_iterate(vector, ctx); + value = FONT_SIZE_SMALLER; + } else { + error = parse_unit_specifier(c, vector, ctx, &length, &unit); + if (error != CSS_OK) + return error; + + if (unit & UNIT_ANGLE || unit & UNIT_TIME || unit & UNIT_FREQ) + return CSS_INVALID; + + value = FONT_SIZE_DIMENSION; + } + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + opv = buildOPV(OP_FONT_SIZE, flags, value); + + required_size = sizeof(opv); + if ((flags & FLAG_INHERIT) == false && value == FONT_SIZE_DIMENSION) + required_size += sizeof(length) + sizeof(unit); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, required_size, result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + if ((flags & FLAG_INHERIT) == false && value == FONT_SIZE_DIMENSION) { + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), + &length, sizeof(length)); + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + + sizeof(length), &unit, sizeof(unit)); + } + + return CSS_OK; +} + +css_error parse_font_style(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *ident; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + + /* IDENT (normal, italic, oblique, inherit) */ + ident = parserutils_vector_iterate(vector, ctx); + if (ident == NULL || ident->type != CSS_TOKEN_IDENT) + return CSS_INVALID; + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + if (ident->lower.data == c->strings[INHERIT]) { + flags |= FLAG_INHERIT; + } else if (ident->lower.data == c->strings[NORMAL]) { + value = FONT_STYLE_NORMAL; + } else if (ident->lower.data == c->strings[ITALIC]) { + value = FONT_STYLE_ITALIC; + } else if (ident->lower.data == c->strings[OBLIQUE]) { + value = FONT_STYLE_OBLIQUE; + } else + return CSS_INVALID; + + opv = buildOPV(OP_FONT_STYLE, flags, value); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + + return CSS_OK; +} + +css_error parse_font_variant(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *ident; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + + /* IDENT (normal, small-caps, inherit) */ + ident = parserutils_vector_iterate(vector, ctx); + if (ident == NULL || ident->type != CSS_TOKEN_IDENT) + return CSS_INVALID; + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + if (ident->lower.data == c->strings[INHERIT]) { + flags |= FLAG_INHERIT; + } else if (ident->lower.data == c->strings[NORMAL]) { + value = FONT_VARIANT_NORMAL; + } else if (ident->lower.data == c->strings[SMALL_CAPS]) { + value = FONT_VARIANT_SMALL_CAPS; + } else + return CSS_INVALID; + + opv = buildOPV(OP_FONT_VARIANT, flags, value); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + + return CSS_OK; +} + +css_error parse_font_weight(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *token; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + + /* NUMBER (100, 200, 300, 400, 500, 600, 700, 800, 900) | + * IDENT (normal, bold, bolder, lighter, inherit) */ + token = parserutils_vector_iterate(vector, ctx); + if (token == NULL || (token->type != CSS_TOKEN_IDENT && + token->type != CSS_TOKEN_NUMBER)) + return CSS_INVALID; + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + if (token->lower.data == c->strings[INHERIT]) { + flags |= FLAG_INHERIT; + } else if (token->type == CSS_TOKEN_NUMBER) { + size_t consumed = 0; + fixed num = number_from_css_string(&token->lower, &consumed); + int32_t intpart = FIXTOINT(num); + /* Invalid if there are trailing characters or it was a float */ + if (consumed != token->lower.len || num != intpart) + return CSS_INVALID; + switch (intpart) { + case 100: value = FONT_WEIGHT_100; break; + case 200: value = FONT_WEIGHT_200; break; + case 300: value = FONT_WEIGHT_300; break; + case 400: value = FONT_WEIGHT_400; break; + case 500: value = FONT_WEIGHT_500; break; + case 600: value = FONT_WEIGHT_600; break; + case 700: value = FONT_WEIGHT_700; break; + case 800: value = FONT_WEIGHT_800; break; + case 900: value = FONT_WEIGHT_900; break; + default: return CSS_INVALID; + } + } else if (token->lower.data == c->strings[NORMAL]) { + value = FONT_WEIGHT_NORMAL; + } else if (token->lower.data == c->strings[BOLD]) { + value = FONT_WEIGHT_BOLD; + } else if (token->lower.data == c->strings[BOLDER]) { + value = FONT_WEIGHT_BOLDER; + } else if (token->lower.data == c->strings[LIGHTER]) { + value = FONT_WEIGHT_LIGHTER; + } else + return CSS_INVALID; + + opv = buildOPV(OP_FONT_WEIGHT, flags, value); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + + return CSS_OK; +} + +css_error parse_height(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *token; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + fixed length = 0; + uint32_t unit = 0; + uint32_t required_size; + + /* length | percentage | IDENT(auto, inherit) */ + token = parserutils_vector_peek(vector, *ctx); + if (token == NULL) + return CSS_INVALID; + + if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[INHERIT]) { + parserutils_vector_iterate(vector, ctx); + flags = FLAG_INHERIT; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[AUTO]) { + parserutils_vector_iterate(vector, ctx); + value = HEIGHT_AUTO; + } else { + error = parse_unit_specifier(c, vector, ctx, &length, &unit); + if (error != CSS_OK) + return error; + + if (unit & UNIT_ANGLE || unit & UNIT_TIME || unit & UNIT_FREQ) + return CSS_INVALID; + + value = HEIGHT_SET; + } + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + opv = buildOPV(OP_HEIGHT, flags, value); + + required_size = sizeof(opv); + if ((flags & FLAG_INHERIT) == false && value == HEIGHT_SET) + required_size += sizeof(length) + sizeof(unit); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, required_size, result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + if ((flags & FLAG_INHERIT) == false && value == HEIGHT_SET) { + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), + &length, sizeof(length)); + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + + sizeof(length), &unit, sizeof(unit)); + } + + return CSS_OK; +} + +css_error parse_left(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *token; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + fixed length = 0; + uint32_t unit = 0; + uint32_t required_size; + + /* length | percentage | IDENT(auto, inherit) */ + token = parserutils_vector_peek(vector, *ctx); + if (token == NULL) + return CSS_INVALID; + + if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[INHERIT]) { + parserutils_vector_iterate(vector, ctx); + flags = FLAG_INHERIT; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[AUTO]) { + parserutils_vector_iterate(vector, ctx); + value = LEFT_AUTO; + } else { + error = parse_unit_specifier(c, vector, ctx, &length, &unit); + if (error != CSS_OK) + return error; + + if (unit & UNIT_ANGLE || unit & UNIT_TIME || unit & UNIT_FREQ) + return CSS_INVALID; + + value = LEFT_SET; + } + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + opv = buildOPV(OP_LEFT, flags, value); + + required_size = sizeof(opv); + if ((flags & FLAG_INHERIT) == false && value == LEFT_SET) + required_size += sizeof(length) + sizeof(unit); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, required_size, result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + if ((flags & FLAG_INHERIT) == false && value == LEFT_SET) { + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), + &length, sizeof(length)); + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + + sizeof(length), &unit, sizeof(unit)); + } + + return CSS_OK; +} + +css_error parse_letter_spacing(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *token; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + fixed length = 0; + uint32_t unit = 0; + uint32_t required_size; + + /* length | IDENT(normal, inherit) */ + token = parserutils_vector_peek(vector, *ctx); + if (token == NULL) + return CSS_INVALID; + + if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[INHERIT]) { + parserutils_vector_iterate(vector, ctx); + flags = FLAG_INHERIT; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[NORMAL]) { + parserutils_vector_iterate(vector, ctx); + value = LETTER_SPACING_NORMAL; + } else { + error = parse_unit_specifier(c, vector, ctx, &length, &unit); + if (error != CSS_OK) + return error; + + if (unit & UNIT_ANGLE || unit & UNIT_TIME || unit & UNIT_FREQ || + unit & UNIT_PCT) + return CSS_INVALID; + + value = LETTER_SPACING_SET; + } + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + opv = buildOPV(OP_LETTER_SPACING, flags, value); + + required_size = sizeof(opv); + if ((flags & FLAG_INHERIT) == false && value == LETTER_SPACING_SET) + required_size += sizeof(length) + sizeof(unit); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, required_size, result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + if ((flags & FLAG_INHERIT) == false && value == LETTER_SPACING_SET) { + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), + &length, sizeof(length)); + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + + sizeof(length), &unit, sizeof(unit)); + } + + return CSS_OK; +} + +css_error parse_line_height(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *token; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + fixed length = 0; + uint32_t unit = 0; + uint32_t required_size; + + /* number | length | percentage | IDENT(normal, inherit) */ + token = parserutils_vector_peek(vector, *ctx); + if (token == NULL) + return CSS_INVALID; + + if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[INHERIT]) { + parserutils_vector_iterate(vector, ctx); + flags = FLAG_INHERIT; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[NORMAL]) { + parserutils_vector_iterate(vector, ctx); + value = LINE_HEIGHT_NORMAL; + } else if (token->type == CSS_TOKEN_NUMBER) { + size_t consumed = 0; + length = number_from_css_string(&token->lower, &consumed); + if (consumed != token->lower.len) + return CSS_INVALID; + + value = LINE_HEIGHT_NUMBER; + } else { + error = parse_unit_specifier(c, vector, ctx, &length, &unit); + if (error != CSS_OK) + return error; + + if (unit & UNIT_ANGLE || unit & UNIT_TIME || unit & UNIT_FREQ) + return CSS_INVALID; + + value = LINE_HEIGHT_DIMENSION; + } + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + opv = buildOPV(OP_LINE_HEIGHT, flags, value); + + required_size = sizeof(opv); + if ((flags & FLAG_INHERIT) == false && value == LINE_HEIGHT_NUMBER) + required_size += sizeof(length); + else if ((flags & FLAG_INHERIT) == false && + value == LINE_HEIGHT_DIMENSION) + required_size += sizeof(length) + sizeof(unit); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, required_size, result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + if ((flags & FLAG_INHERIT) == false && (value == LINE_HEIGHT_NUMBER || + value == LINE_HEIGHT_DIMENSION)) + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), + &length, sizeof(length)); + if ((flags & FLAG_INHERIT) == false && value == LINE_HEIGHT_DIMENSION) + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + + sizeof(length), &unit, sizeof(unit)); + + return CSS_OK; +} + +css_error parse_list_style_image(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *token; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + uint32_t required_size; + + /* URI | IDENT (none, inherit) */ + token = parserutils_vector_iterate(vector, ctx); + if (token == NULL || (token->type != CSS_TOKEN_IDENT && + token->type != CSS_TOKEN_URI)) + return CSS_INVALID; + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[INHERIT]) { + flags |= FLAG_INHERIT; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[NONE]) { + value = LIST_STYLE_IMAGE_NONE; + } else if (token->type == CSS_TOKEN_URI) { + value = LIST_STYLE_IMAGE_URI; + } else + return CSS_INVALID; + + opv = buildOPV(OP_LIST_STYLE_IMAGE, flags, value); + + required_size = sizeof(opv); + if ((flags & FLAG_INHERIT) == false && value == LIST_STYLE_IMAGE_URI) + required_size += sizeof(uint8_t *) + sizeof(size_t); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, required_size, result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + if ((flags & FLAG_INHERIT) == false && value == LIST_STYLE_IMAGE_URI) { + memcpy((uint8_t *) (*result)->bytecode + sizeof(opv), + &token->data.data, sizeof(uint8_t *)); + memcpy((uint8_t *) (*result)->bytecode + sizeof(opv) + + sizeof(uint8_t *), + &token->data.len, sizeof(size_t)); + } + + return CSS_OK; +} + +css_error parse_list_style_position(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *ident; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + + /* IDENT (inside, outside, inherit) */ + ident = parserutils_vector_iterate(vector, ctx); + if (ident == NULL || ident->type != CSS_TOKEN_IDENT) + return CSS_INVALID; + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + if (ident->lower.data == c->strings[INHERIT]) { + flags |= FLAG_INHERIT; + } else if (ident->lower.data == c->strings[INSIDE]) { + value = LIST_STYLE_POSITION_INSIDE; + } else if (ident->lower.data == c->strings[OUTSIDE]) { + value = LIST_STYLE_POSITION_OUTSIDE; + } else + return CSS_INVALID; + + opv = buildOPV(OP_LIST_STYLE_POSITION, flags, value); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + + return CSS_OK; +} + +css_error parse_list_style_type(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *ident; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + + /* IDENT (disc, circle, square, decimal, decimal-leading-zero, + * lower-roman, upper-roman, lower-greek, lower-latin, + * upper-latin, armenian, georgian, lower-alpha, upper-alpha, + * none, inherit) + */ + ident = parserutils_vector_iterate(vector, ctx); + if (ident == NULL || ident->type != CSS_TOKEN_IDENT) + return CSS_INVALID; + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + if (ident->lower.data == c->strings[INHERIT]) { + flags |= FLAG_INHERIT; + } else if (ident->lower.data == c->strings[DISC]) { + value = LIST_STYLE_TYPE_DISC; + } else if (ident->lower.data == c->strings[CIRCLE]) { + value = LIST_STYLE_TYPE_CIRCLE; + } else if (ident->lower.data == c->strings[SQUARE]) { + value = LIST_STYLE_TYPE_SQUARE; + } else if (ident->lower.data == c->strings[DECIMAL]) { + value = LIST_STYLE_TYPE_DECIMAL; + } else if (ident->lower.data == c->strings[DECIMAL_LEADING_ZERO]) { + value = LIST_STYLE_TYPE_DECIMAL_LEADING_ZERO; + } else if (ident->lower.data == c->strings[LOWER_ROMAN]) { + value = LIST_STYLE_TYPE_LOWER_ROMAN; + } else if (ident->lower.data == c->strings[UPPER_ROMAN]) { + value = LIST_STYLE_TYPE_UPPER_ROMAN; + } else if (ident->lower.data == c->strings[LOWER_GREEK]) { + value = LIST_STYLE_TYPE_LOWER_GREEK; + } else if (ident->lower.data == c->strings[LOWER_LATIN]) { + value = LIST_STYLE_TYPE_LOWER_LATIN; + } else if (ident->lower.data == c->strings[UPPER_LATIN]) { + value = LIST_STYLE_TYPE_UPPER_LATIN; + } else if (ident->lower.data == c->strings[ARMENIAN]) { + value = LIST_STYLE_TYPE_ARMENIAN; + } else if (ident->lower.data == c->strings[GEORGIAN]) { + value = LIST_STYLE_TYPE_GEORGIAN; + } else if (ident->lower.data == c->strings[LOWER_ALPHA]) { + value = LIST_STYLE_TYPE_LOWER_ALPHA; + } else if (ident->lower.data == c->strings[UPPER_ALPHA]) { + value = LIST_STYLE_TYPE_UPPER_ALPHA; + } else if (ident->lower.data == c->strings[NONE]) { + value = LIST_STYLE_TYPE_NONE; + } else + return CSS_INVALID; + + opv = buildOPV(OP_LIST_STYLE_TYPE, flags, value); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + + return CSS_OK; +} + +css_error parse_margin_bottom(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + return parse_margin_side(c, vector, ctx, SIDE_BOTTOM, result); +} + +css_error parse_margin_left(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + return parse_margin_side(c, vector, ctx, SIDE_LEFT, result); +} + +css_error parse_margin_right(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + return parse_margin_side(c, vector, ctx, SIDE_RIGHT, result); +} + +css_error parse_margin_top(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + return parse_margin_side(c, vector, ctx, SIDE_TOP, result); +} + +css_error parse_max_height(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *token; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + fixed length = 0; + uint32_t unit = 0; + uint32_t required_size; + + /* length | percentage | IDENT(none, inherit) */ + token = parserutils_vector_peek(vector, *ctx); + if (token == NULL) + return CSS_INVALID; + + if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[INHERIT]) { + parserutils_vector_iterate(vector, ctx); + flags = FLAG_INHERIT; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[NONE]) { + parserutils_vector_iterate(vector, ctx); + value = MAX_HEIGHT_NONE; + } else { + error = parse_unit_specifier(c, vector, ctx, &length, &unit); + if (error != CSS_OK) + return error; + + if (unit & UNIT_ANGLE || unit & UNIT_TIME || unit & UNIT_FREQ) + return CSS_INVALID; + + value = MAX_HEIGHT_SET; + } + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + opv = buildOPV(OP_MAX_HEIGHT, flags, value); + + required_size = sizeof(opv); + if ((flags & FLAG_INHERIT) == false && value == MAX_HEIGHT_SET) + required_size += sizeof(length) + sizeof(unit); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, required_size, result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + if ((flags & FLAG_INHERIT) == false && value == MAX_HEIGHT_SET) { + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), + &length, sizeof(length)); + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + + sizeof(length), &unit, sizeof(unit)); + } + + return CSS_OK; +} + +css_error parse_max_width(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *token; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + fixed length = 0; + uint32_t unit = 0; + uint32_t required_size; + + /* length | percentage | IDENT(none, inherit) */ + token = parserutils_vector_peek(vector, *ctx); + if (token == NULL) + return CSS_INVALID; + + if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[INHERIT]) { + parserutils_vector_iterate(vector, ctx); + flags = FLAG_INHERIT; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[NONE]) { + parserutils_vector_iterate(vector, ctx); + value = MAX_WIDTH_NONE; + } else { + error = parse_unit_specifier(c, vector, ctx, &length, &unit); + if (error != CSS_OK) + return error; + + if (unit & UNIT_ANGLE || unit & UNIT_TIME || unit & UNIT_FREQ) + return CSS_INVALID; + + value = MAX_WIDTH_SET; + } + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + opv = buildOPV(OP_MAX_WIDTH, flags, value); + + required_size = sizeof(opv); + if ((flags & FLAG_INHERIT) == false && value == MAX_WIDTH_SET) + required_size += sizeof(length) + sizeof(unit); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, required_size, result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + if ((flags && FLAG_INHERIT) == false && value == MAX_WIDTH_SET) { + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), + &length, sizeof(length)); + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + + sizeof(length), &unit, sizeof(unit)); + } + + return CSS_OK; +} + +css_error parse_min_height(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *token; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + fixed length = 0; + uint32_t unit = 0; + uint32_t required_size; + + /* length | percentage | IDENT(inherit) */ + token = parserutils_vector_peek(vector, *ctx); + if (token == NULL) + return CSS_INVALID; + + if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[INHERIT]) { + parserutils_vector_iterate(vector, ctx); + flags = FLAG_INHERIT; + } else { + error = parse_unit_specifier(c, vector, ctx, &length, &unit); + if (error != CSS_OK) + return error; + + if (unit & UNIT_ANGLE || unit & UNIT_TIME || unit & UNIT_FREQ) + return CSS_INVALID; + + value = MIN_HEIGHT_SET; + } + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + opv = buildOPV(OP_MIN_HEIGHT, flags, value); + + required_size = sizeof(opv); + if ((flags & FLAG_INHERIT) == false && value == MIN_HEIGHT_SET) + required_size += sizeof(length) + sizeof(unit); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, required_size, result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + if ((flags & FLAG_INHERIT) == false && value == MIN_HEIGHT_SET) { + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), + &length, sizeof(length)); + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + + sizeof(length), &unit, sizeof(unit)); + } + + return CSS_OK; +} + +css_error parse_min_width(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *token; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + fixed length = 0; + uint32_t unit = 0; + uint32_t required_size; + + /* length | percentage | IDENT(inherit) */ + token = parserutils_vector_peek(vector, *ctx); + if (token == NULL) + return CSS_INVALID; + + if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[INHERIT]) { + parserutils_vector_iterate(vector, ctx); + flags = FLAG_INHERIT; + } else { + error = parse_unit_specifier(c, vector, ctx, &length, &unit); + if (error != CSS_OK) + return error; + + if (unit & UNIT_ANGLE || unit & UNIT_TIME || unit & UNIT_FREQ) + return CSS_INVALID; + + value = MIN_WIDTH_SET; + } + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + opv = buildOPV(OP_MIN_WIDTH, flags, value); + + required_size = sizeof(opv); + if ((flags & FLAG_INHERIT) == false && value == MIN_WIDTH_SET) + required_size += sizeof(length) + sizeof(unit); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, required_size, result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + if ((flags & FLAG_INHERIT) == false && value == MIN_WIDTH_SET) { + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), + &length, sizeof(length)); + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + + sizeof(length), &unit, sizeof(unit)); + } + + return CSS_OK; +} + +css_error parse_orphans(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *token; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + fixed num = 0; + uint32_t required_size; + + /* | IDENT (inherit) */ + token = parserutils_vector_iterate(vector, ctx); + if (token == NULL || (token->type != CSS_TOKEN_IDENT && + token->type != CSS_TOKEN_NUMBER)) + return CSS_INVALID; + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + if (token->lower.data == c->strings[INHERIT]) { + flags |= FLAG_INHERIT; + } else if (token->type == CSS_TOKEN_NUMBER) { + size_t consumed = 0; + num = number_from_css_string(&token->lower, &consumed); + int32_t intpart = FIXTOINT(num); + /* Invalid if there are trailing characters or it was a float */ + if (consumed != token->lower.len || num != intpart) + return CSS_INVALID; + + value = ORPHANS_SET; + } else + return CSS_INVALID; + + opv = buildOPV(OP_ORPHANS, flags, value); + + required_size = sizeof(opv); + if ((flags & FLAG_INHERIT) == false && value == ORPHANS_SET) + required_size += sizeof(num); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, required_size, result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + if ((flags & FLAG_INHERIT) == false && value == ORPHANS_SET) { + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), + &num, sizeof(num)); + } + + return CSS_OK; +} + +css_error parse_outline_color(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *token; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + uint32_t colour = 0; + uint32_t required_size; + + /* colour | IDENT (invert, inherit) */ + token= parserutils_vector_peek(vector, *ctx); + if (token == NULL) + return CSS_INVALID; + + if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[INHERIT]) { + parserutils_vector_iterate(vector, ctx); + flags |= FLAG_INHERIT; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[INVERT]) { + parserutils_vector_iterate(vector, ctx); + value = OUTLINE_COLOR_INVERT; + } else { + error = parse_colour_specifier(c, vector, ctx, &colour); + if (error != CSS_OK) + return error; + + value = OUTLINE_COLOR_SET; + } + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + opv = buildOPV(OP_OUTLINE_COLOR, flags, value); + + required_size = sizeof(opv); + if ((flags & FLAG_INHERIT) == false && value == OUTLINE_COLOR_SET) + required_size += sizeof(colour); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, required_size, result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + if ((flags & FLAG_INHERIT) == false && value == OUTLINE_COLOR_SET) { + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), + &colour, sizeof(colour)); + } + + return CSS_OK; +} + +css_error parse_outline_style(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + uint32_t opv; + uint8_t flags; + uint16_t value; + + /* Fake as border-left-style */ + error = parse_border_side_style(c, vector, ctx, SIDE_LEFT, result); + if (error != CSS_OK) + return error; + + /* Then change the opcode to outline-style, and clear the side bits */ + opv = *((uint32_t *) (*result)->bytecode); + + flags = getFlags(opv); + value = getValue(opv) & ~SIDE_LEFT; + + opv = buildOPV(OP_OUTLINE_STYLE, flags, value); + + *((uint32_t *) (*result)->bytecode) = opv; + + return CSS_OK; +} + +css_error parse_outline_width(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + uint32_t opv; + uint8_t flags; + uint16_t value; + + /* Fake as border-left-width */ + error = parse_border_side_width(c, vector, ctx, SIDE_LEFT, result); + if (error != CSS_OK) + return error; + + /* Then change the opcode to outline-width, and clear the side bits */ + opv = *((uint32_t *) (*result)->bytecode); + + flags = getFlags(opv); + value = getValue(opv) & ~SIDE_LEFT; + + opv = buildOPV(OP_OUTLINE_WIDTH, flags, value); + + *((uint32_t *) (*result)->bytecode) = opv; + + return CSS_OK; +} + +css_error parse_overflow(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *ident; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + + /* IDENT (visible, hidden, scroll, auto, inherit) */ + ident = parserutils_vector_iterate(vector, ctx); + if (ident == NULL || ident->type != CSS_TOKEN_IDENT) + return CSS_INVALID; + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + if (ident->lower.data == c->strings[INHERIT]) { + flags |= FLAG_INHERIT; + } else if (ident->lower.data == c->strings[VISIBLE]) { + value = OVERFLOW_VISIBLE; + } else if (ident->lower.data == c->strings[HIDDEN]) { + value = OVERFLOW_HIDDEN; + } else if (ident->lower.data == c->strings[SCROLL]) { + value = OVERFLOW_SCROLL; + } else if (ident->lower.data == c->strings[AUTO]) { + value = OVERFLOW_AUTO; + } else + return CSS_INVALID; + + opv = buildOPV(OP_OVERFLOW, flags, value); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + + return CSS_OK; +} + +css_error parse_padding_bottom(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + return parse_padding_side(c, vector, ctx, SIDE_BOTTOM, result); +} + +css_error parse_padding_left(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + return parse_padding_side(c, vector, ctx, SIDE_LEFT, result); +} + +css_error parse_padding_right(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + return parse_padding_side(c, vector, ctx, SIDE_RIGHT, result); +} + +css_error parse_padding_top(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + return parse_padding_side(c, vector, ctx, SIDE_TOP, result); +} + +css_error parse_page_break_after(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *ident; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + + /* IDENT (auto, always, avoid, left, right, inherit) */ + ident = parserutils_vector_iterate(vector, ctx); + if (ident == NULL || ident->type != CSS_TOKEN_IDENT) + return CSS_INVALID; + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + if (ident->lower.data == c->strings[INHERIT]) { + flags |= FLAG_INHERIT; + } else if (ident->lower.data == c->strings[AUTO]) { + value = PAGE_BREAK_AFTER_AUTO; + } else if (ident->lower.data == c->strings[ALWAYS]) { + value = PAGE_BREAK_AFTER_ALWAYS; + } else if (ident->lower.data == c->strings[AVOID]) { + value = PAGE_BREAK_AFTER_AVOID; + } else if (ident->lower.data == c->strings[LEFT]) { + value = PAGE_BREAK_AFTER_LEFT; + } else if (ident->lower.data == c->strings[RIGHT]) { + value = PAGE_BREAK_AFTER_RIGHT; + } else + return CSS_INVALID; + + opv = buildOPV(OP_PAGE_BREAK_AFTER, flags, value); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + + return CSS_OK; +} + +css_error parse_page_break_before(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *ident; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + + /* IDENT (auto, always, avoid, left, right, inherit) */ + ident = parserutils_vector_iterate(vector, ctx); + if (ident == NULL || ident->type != CSS_TOKEN_IDENT) + return CSS_INVALID; + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + if (ident->lower.data == c->strings[INHERIT]) { + flags |= FLAG_INHERIT; + } else if (ident->lower.data == c->strings[AUTO]) { + value = PAGE_BREAK_BEFORE_AUTO; + } else if (ident->lower.data == c->strings[ALWAYS]) { + value = PAGE_BREAK_BEFORE_ALWAYS; + } else if (ident->lower.data == c->strings[AVOID]) { + value = PAGE_BREAK_BEFORE_AVOID; + } else if (ident->lower.data == c->strings[LEFT]) { + value = PAGE_BREAK_BEFORE_LEFT; + } else if (ident->lower.data == c->strings[RIGHT]) { + value = PAGE_BREAK_BEFORE_RIGHT; + } else + return CSS_INVALID; + + opv = buildOPV(OP_PAGE_BREAK_BEFORE, flags, value); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + + return CSS_OK; +} + +css_error parse_page_break_inside(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *ident; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + + /* IDENT (auto, avoid, inherit) */ + ident = parserutils_vector_iterate(vector, ctx); + if (ident == NULL || ident->type != CSS_TOKEN_IDENT) + return CSS_INVALID; + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + if (ident->lower.data == c->strings[INHERIT]) { + flags |= FLAG_INHERIT; + } else if (ident->lower.data == c->strings[AUTO]) { + value = PAGE_BREAK_INSIDE_AUTO; + } else if (ident->lower.data == c->strings[AVOID]) { + value = PAGE_BREAK_INSIDE_AVOID; + } else + return CSS_INVALID; + + opv = buildOPV(OP_PAGE_BREAK_INSIDE, flags, value); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + + return CSS_OK; +} + +css_error parse_pause_after(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *token; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + fixed length = 0; + uint32_t unit = 0; + uint32_t required_size; + + /* time | percentage | IDENT(inherit) */ + token = parserutils_vector_peek(vector, *ctx); + if (token == NULL) + return CSS_INVALID; + + if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[INHERIT]) { + parserutils_vector_iterate(vector, ctx); + flags = FLAG_INHERIT; + } else { + error = parse_unit_specifier(c, vector, ctx, &length, &unit); + if (error != CSS_OK) + return error; + + if ((unit & UNIT_TIME) == false && (unit & UNIT_PCT) == false) + return CSS_INVALID; + + value = PAUSE_AFTER_SET; + } + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + opv = buildOPV(OP_PAUSE_AFTER, flags, value); + + required_size = sizeof(opv); + if ((flags & FLAG_INHERIT) == false && value == PAUSE_AFTER_SET) + required_size += sizeof(length) + sizeof(unit); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, required_size, result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + if ((flags & FLAG_INHERIT) == false && value == PAUSE_AFTER_SET) { + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), + &length, sizeof(length)); + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + + sizeof(length), &unit, sizeof(unit)); + } + + return CSS_OK; +} + +css_error parse_pause_before(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *token; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + fixed length = 0; + uint32_t unit = 0; + uint32_t required_size; + + /* time | percentage | IDENT(inherit) */ + token = parserutils_vector_peek(vector, *ctx); + if (token == NULL) + return CSS_INVALID; + + if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[INHERIT]) { + parserutils_vector_iterate(vector, ctx); + flags = FLAG_INHERIT; + } else { + error = parse_unit_specifier(c, vector, ctx, &length, &unit); + if (error != CSS_OK) + return error; + + if ((unit & UNIT_TIME) == false && (unit & UNIT_PCT) == false) + return CSS_INVALID; + + value = PAUSE_BEFORE_SET; + } + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + opv = buildOPV(OP_PAUSE_BEFORE, flags, value); + + required_size = sizeof(opv); + if ((flags & FLAG_INHERIT) == false && value == PAUSE_BEFORE_SET) + required_size += sizeof(length) + sizeof(unit); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, required_size, result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + if ((flags & FLAG_INHERIT) == false && value == PAUSE_BEFORE_SET) { + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), + &length, sizeof(length)); + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + + sizeof(length), &unit, sizeof(unit)); + } + + return CSS_OK; +} + +css_error parse_pitch_range(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *token; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + fixed num = 0; + uint32_t required_size; + + /* number | IDENT (inherit) */ + token = parserutils_vector_iterate(vector, ctx); + if (token == NULL || (token->type != CSS_TOKEN_IDENT && + token->type != CSS_TOKEN_NUMBER)) + return CSS_INVALID; + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + if (token->lower.data == c->strings[INHERIT]) { + flags |= FLAG_INHERIT; + } else if (token->type == CSS_TOKEN_NUMBER) { + size_t consumed = 0; + num = number_from_css_string(&token->lower, &consumed); + /* Invalid if there are trailing characters */ + if (consumed != token->lower.len) + return CSS_INVALID; + + value = PITCH_RANGE_SET; + } else + return CSS_INVALID; + + opv = buildOPV(OP_PITCH_RANGE, flags, value); + + required_size = sizeof(opv); + if ((flags & FLAG_INHERIT) == false && value == PITCH_RANGE_SET) + required_size += sizeof(num); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, required_size, result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + if ((flags & FLAG_INHERIT) == false && value == PITCH_RANGE_SET) { + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), + &num, sizeof(num)); + } + + return CSS_OK; +} + +css_error parse_pitch(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *token; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + fixed length = 0; + uint32_t unit = 0; + uint32_t required_size; + + /* frequency | IDENT(x-low, low, medium, high, x-high, inherit) */ + token = parserutils_vector_peek(vector, *ctx); + if (token == NULL) + return CSS_INVALID; + + if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[INHERIT]) { + parserutils_vector_iterate(vector, ctx); + flags = FLAG_INHERIT; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[X_LOW]) { + value = PITCH_X_LOW; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[LOW]) { + value = PITCH_LOW; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[MEDIUM]) { + value = PITCH_MEDIUM; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[HIGH]) { + value = PITCH_HIGH; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[X_HIGH]) { + value = PITCH_X_HIGH; + } else { + error = parse_unit_specifier(c, vector, ctx, &length, &unit); + if (error != CSS_OK) + return error; + + if ((unit & UNIT_FREQ) == false) + return CSS_INVALID; + + value = PITCH_FREQUENCY; + } + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + opv = buildOPV(OP_PITCH, flags, value); + + required_size = sizeof(opv); + if ((flags & FLAG_INHERIT) == false && value == PITCH_FREQUENCY) + required_size += sizeof(length) + sizeof(unit); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, required_size, result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + if ((flags & FLAG_INHERIT) == false && value == PITCH_FREQUENCY) { + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), + &length, sizeof(length)); + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + + sizeof(length), &unit, sizeof(unit)); + } + + return CSS_OK; +} + +css_error parse_play_during(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + /** \todo play-during */ + + UNUSED(c); + UNUSED(vector); + UNUSED(ctx); + UNUSED(result); + + return CSS_OK; +} + +css_error parse_position(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *ident; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + + /* IDENT (static, relative, absolute, fixed, inherit) */ + ident = parserutils_vector_iterate(vector, ctx); + if (ident == NULL || ident->type != CSS_TOKEN_IDENT) + return CSS_INVALID; + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + if (ident->lower.data == c->strings[INHERIT]) { + flags |= FLAG_INHERIT; + } else if (ident->lower.data == c->strings[STATIC]) { + value = POSITION_STATIC; + } else if (ident->lower.data == c->strings[RELATIVE]) { + value = POSITION_RELATIVE; + } else if (ident->lower.data == c->strings[ABSOLUTE]) { + value = POSITION_ABSOLUTE; + } else if (ident->lower.data == c->strings[FIXED]) { + value = POSITION_FIXED; + } else + return CSS_INVALID; + + opv = buildOPV(OP_POSITION, flags, value); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + + return CSS_OK; +} + +css_error parse_quotes(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + /** \todo quotes */ + + UNUSED(c); + UNUSED(vector); + UNUSED(ctx); + UNUSED(result); + + return CSS_OK; +} + +css_error parse_richness(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *token; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + fixed num = 0; + uint32_t required_size; + + /* number | IDENT (inherit) */ + token = parserutils_vector_iterate(vector, ctx); + if (token == NULL || (token->type != CSS_TOKEN_IDENT && + token->type != CSS_TOKEN_NUMBER)) + return CSS_INVALID; + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + if (token->lower.data == c->strings[INHERIT]) { + flags |= FLAG_INHERIT; + } else if (token->type == CSS_TOKEN_NUMBER) { + size_t consumed = 0; + num = number_from_css_string(&token->lower, &consumed); + /* Invalid if there are trailing characters */ + if (consumed != token->lower.len) + return CSS_INVALID; + + value = RICHNESS_SET; + } else + return CSS_INVALID; + + opv = buildOPV(OP_RICHNESS, flags, value); + + required_size = sizeof(opv); + if ((flags & FLAG_INHERIT) == false && value == RICHNESS_SET) + required_size += sizeof(num); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, required_size, result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + if ((flags & FLAG_INHERIT) == false && value == RICHNESS_SET) { + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), + &num, sizeof(num)); + } + + return CSS_OK; +} + +css_error parse_right(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *token; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + fixed length = 0; + uint32_t unit = 0; + uint32_t required_size; + + /* length | percentage | IDENT(auto, inherit) */ + token = parserutils_vector_peek(vector, *ctx); + if (token == NULL) + return CSS_INVALID; + + if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[INHERIT]) { + parserutils_vector_iterate(vector, ctx); + flags = FLAG_INHERIT; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[AUTO]) { + parserutils_vector_iterate(vector, ctx); + value = RIGHT_AUTO; + } else { + error = parse_unit_specifier(c, vector, ctx, &length, &unit); + if (error != CSS_OK) + return error; + + if (unit & UNIT_ANGLE || unit & UNIT_TIME || unit & UNIT_FREQ) + return CSS_INVALID; + + value = RIGHT_SET; + } + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + opv = buildOPV(OP_RIGHT, flags, value); + + required_size = sizeof(opv); + if ((flags & FLAG_INHERIT) == false && value == RIGHT_SET) + required_size += sizeof(length) + sizeof(unit); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, required_size, result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + if ((flags & FLAG_INHERIT) == false && value == RIGHT_SET) { + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), + &length, sizeof(length)); + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + + sizeof(length), &unit, sizeof(unit)); + } + + return CSS_OK; +} + +css_error parse_speak_header(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *ident; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + + /* IDENT (once, always, inherit) */ + ident = parserutils_vector_iterate(vector, ctx); + if (ident == NULL || ident->type != CSS_TOKEN_IDENT) + return CSS_INVALID; + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + if (ident->lower.data == c->strings[INHERIT]) { + flags |= FLAG_INHERIT; + } else if (ident->lower.data == c->strings[ONCE]) { + value = SPEAK_HEADER_ONCE; + } else if (ident->lower.data == c->strings[ALWAYS]) { + value = SPEAK_HEADER_ALWAYS; + } else + return CSS_INVALID; + + opv = buildOPV(OP_SPEAK_HEADER, flags, value); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + + return CSS_OK; +} + +css_error parse_speak_numeral(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *ident; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + + /* IDENT (digits, continuous, inherit) */ + ident = parserutils_vector_iterate(vector, ctx); + if (ident == NULL || ident->type != CSS_TOKEN_IDENT) + return CSS_INVALID; + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + if (ident->lower.data == c->strings[INHERIT]) { + flags |= FLAG_INHERIT; + } else if (ident->lower.data == c->strings[DIGITS]) { + value = SPEAK_NUMERAL_DIGITS; + } else if (ident->lower.data == c->strings[CONTINUOUS]) { + value = SPEAK_NUMERAL_CONTINUOUS; + } else + return CSS_INVALID; + + opv = buildOPV(OP_SPEAK_NUMERAL, flags, value); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + + return CSS_OK; +} + +css_error parse_speak_punctuation(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *ident; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + + /* IDENT (code, none, inherit) */ + ident = parserutils_vector_iterate(vector, ctx); + if (ident == NULL || ident->type != CSS_TOKEN_IDENT) + return CSS_INVALID; + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + if (ident->lower.data == c->strings[INHERIT]) { + flags |= FLAG_INHERIT; + } else if (ident->lower.data == c->strings[CODE]) { + value = SPEAK_PUNCTUATION_CODE; + } else if (ident->lower.data == c->strings[NONE]) { + value = SPEAK_PUNCTUATION_NONE; + } else + return CSS_INVALID; + + opv = buildOPV(OP_SPEAK_PUNCTUATION, flags, value); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + + return CSS_OK; +} + +css_error parse_speak(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *ident; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + + /* IDENT (normal, none, spell-out, inherit) */ + ident = parserutils_vector_iterate(vector, ctx); + if (ident == NULL || ident->type != CSS_TOKEN_IDENT) + return CSS_INVALID; + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + if (ident->lower.data == c->strings[INHERIT]) { + flags |= FLAG_INHERIT; + } else if (ident->lower.data == c->strings[NORMAL]) { + value = SPEAK_NORMAL; + } else if (ident->lower.data == c->strings[NONE]) { + value = SPEAK_NONE; + } else if (ident->lower.data == c->strings[SPELL_OUT]) { + value = SPEAK_SPELL_OUT; + } else + return CSS_INVALID; + + opv = buildOPV(OP_SPEAK, flags, value); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + + return CSS_OK; +} + +css_error parse_speech_rate(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *token; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + fixed num = 0; + uint32_t required_size; + + /* number | IDENT (x-slow, slow, medium, fast, x-fast, faster, slower, + * inherit) + */ + token = parserutils_vector_iterate(vector, ctx); + if (token == NULL || (token->type != CSS_TOKEN_IDENT && + token->type != CSS_TOKEN_NUMBER)) + return CSS_INVALID; + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[INHERIT]) { + flags |= FLAG_INHERIT; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[X_SLOW]) { + value = SPEECH_RATE_X_SLOW; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[SLOW]) { + value = SPEECH_RATE_SLOW; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[MEDIUM]) { + value = SPEECH_RATE_MEDIUM; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[FAST]) { + value = SPEECH_RATE_FAST; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[X_FAST]) { + value = SPEECH_RATE_X_FAST; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[FASTER]) { + value = SPEECH_RATE_FASTER; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[SLOWER]) { + value = SPEECH_RATE_SLOWER; + } else if (token->type == CSS_TOKEN_NUMBER) { + size_t consumed = 0; + num = number_from_css_string(&token->lower, &consumed); + /* Invalid if there are trailing characters */ + if (consumed != token->lower.len) + return CSS_INVALID; + + value = SPEECH_RATE_SET; + } else + return CSS_INVALID; + + opv = buildOPV(OP_SPEECH_RATE, flags, value); + + required_size = sizeof(opv); + if ((flags & FLAG_INHERIT) == false && value == SPEECH_RATE_SET) + required_size += sizeof(num); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, required_size, result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + if ((flags & FLAG_INHERIT) == false && value == SPEECH_RATE_SET) { + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), + &num, sizeof(num)); + } + + return CSS_OK; +} + +css_error parse_stress(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *token; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + fixed num = 0; + uint32_t required_size; + + /* number | IDENT (inherit) */ + token = parserutils_vector_iterate(vector, ctx); + if (token == NULL || (token->type != CSS_TOKEN_IDENT && + token->type != CSS_TOKEN_NUMBER)) + return CSS_INVALID; + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + if (token->lower.data == c->strings[INHERIT]) { + flags |= FLAG_INHERIT; + } else if (token->type == CSS_TOKEN_NUMBER) { + size_t consumed = 0; + num = number_from_css_string(&token->lower, &consumed); + /* Invalid if there are trailing characters */ + if (consumed != token->lower.len) + return CSS_INVALID; + + value = STRESS_SET; + } else + return CSS_INVALID; + + opv = buildOPV(OP_STRESS, flags, value); + + required_size = sizeof(opv); + if ((flags & FLAG_INHERIT) == false && value == STRESS_SET) + required_size += sizeof(num); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, required_size, result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + if ((flags & FLAG_INHERIT) == false && value == STRESS_SET) { + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), + &num, sizeof(num)); + } + + return CSS_OK; +} + +css_error parse_table_layout(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *ident; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + + /* IDENT (auto, fixed, inherit) */ + ident = parserutils_vector_iterate(vector, ctx); + if (ident == NULL || ident->type != CSS_TOKEN_IDENT) + return CSS_INVALID; + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + if (ident->lower.data == c->strings[INHERIT]) { + flags |= FLAG_INHERIT; + } else if (ident->lower.data == c->strings[AUTO]) { + value = TABLE_LAYOUT_AUTO; + } else if (ident->lower.data == c->strings[FIXED]) { + value = TABLE_LAYOUT_FIXED; + } else + return CSS_INVALID; + + opv = buildOPV(OP_TABLE_LAYOUT, flags, value); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + + return CSS_OK; +} + +css_error parse_text_align(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *ident; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + + /* IDENT (left, right, center, justify, inherit) */ + ident = parserutils_vector_iterate(vector, ctx); + if (ident == NULL || ident->type != CSS_TOKEN_IDENT) + return CSS_INVALID; + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + if (ident->lower.data == c->strings[INHERIT]) { + flags |= FLAG_INHERIT; + } else if (ident->lower.data == c->strings[LEFT]) { + value = TEXT_ALIGN_LEFT; + } else if (ident->lower.data == c->strings[RIGHT]) { + value = TEXT_ALIGN_RIGHT; + } else if (ident->lower.data == c->strings[CENTER]) { + value = TEXT_ALIGN_CENTER; + } else if (ident->lower.data == c->strings[JUSTIFY]) { + value = TEXT_ALIGN_JUSTIFY; + } else + return CSS_INVALID; + + opv = buildOPV(OP_TEXT_ALIGN, flags, value); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + + return CSS_OK; +} + +css_error parse_text_decoration(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + /** \todo text-decoration */ + + UNUSED(c); + UNUSED(vector); + UNUSED(ctx); + UNUSED(result); + + return CSS_OK; +} + +css_error parse_text_indent(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *token; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + fixed length = 0; + uint32_t unit = 0; + uint32_t required_size; + + /* length | percentage | IDENT(inherit) */ + token = parserutils_vector_peek(vector, *ctx); + if (token == NULL) + return CSS_INVALID; + + if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[INHERIT]) { + parserutils_vector_iterate(vector, ctx); + flags = FLAG_INHERIT; + } else { + error = parse_unit_specifier(c, vector, ctx, &length, &unit); + if (error != CSS_OK) + return error; + + if (unit & UNIT_ANGLE || unit & UNIT_TIME || unit & UNIT_FREQ) + return CSS_INVALID; + + value = TEXT_INDENT_SET; + } + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + opv = buildOPV(OP_TEXT_INDENT, flags, value); + + required_size = sizeof(opv); + if ((flags & FLAG_INHERIT) == false && value == TEXT_INDENT_SET) + required_size += sizeof(length) + sizeof(unit); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, required_size, result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + if ((flags & FLAG_INHERIT) == false && value == TEXT_INDENT_SET) { + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), + &length, sizeof(length)); + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + + sizeof(length), &unit, sizeof(unit)); + } + + return CSS_OK; +} + +css_error parse_text_transform(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *ident; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + + /* IDENT (capitalize, uppercase, lowercase, none, inherit) */ + ident = parserutils_vector_iterate(vector, ctx); + if (ident == NULL || ident->type != CSS_TOKEN_IDENT) + return CSS_INVALID; + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + if (ident->lower.data == c->strings[INHERIT]) { + flags |= FLAG_INHERIT; + } else if (ident->lower.data == c->strings[CAPITALIZE]) { + value = TEXT_TRANSFORM_CAPITALIZE; + } else if (ident->lower.data == c->strings[UPPERCASE]) { + value = TEXT_TRANSFORM_UPPERCASE; + } else if (ident->lower.data == c->strings[LOWERCASE]) { + value = TEXT_TRANSFORM_LOWERCASE; + } else if (ident->lower.data == c->strings[NONE]) { + value = TEXT_TRANSFORM_NONE; + } else + return CSS_INVALID; + + opv = buildOPV(OP_TEXT_TRANSFORM, flags, value); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + + return CSS_OK; +} + +css_error parse_top(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *token; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + fixed length = 0; + uint32_t unit = 0; + uint32_t required_size; + + /* length | percentage | IDENT(auto, inherit) */ + token = parserutils_vector_peek(vector, *ctx); + if (token == NULL) + return CSS_INVALID; + + if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[INHERIT]) { + parserutils_vector_iterate(vector, ctx); + flags = FLAG_INHERIT; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[AUTO]) { + parserutils_vector_iterate(vector, ctx); + value = TOP_AUTO; + } else { + error = parse_unit_specifier(c, vector, ctx, &length, &unit); + if (error != CSS_OK) + return error; + + if (unit & UNIT_ANGLE || unit & UNIT_TIME || unit & UNIT_FREQ) + return CSS_INVALID; + + value = TOP_SET; + } + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + opv = buildOPV(OP_TOP, flags, value); + + required_size = sizeof(opv); + if ((flags & FLAG_INHERIT) == false && value == TOP_SET) + required_size += sizeof(length) + sizeof(unit); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, required_size, result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + if ((flags & FLAG_INHERIT) == false && value == TOP_SET) { + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), + &length, sizeof(length)); + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + + sizeof(length), &unit, sizeof(unit)); + } + + return CSS_OK; +} + +css_error parse_unicode_bidi(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *ident; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + + /* IDENT (normal, embed, bidi-override, inherit) */ + ident = parserutils_vector_iterate(vector, ctx); + if (ident == NULL || ident->type != CSS_TOKEN_IDENT) + return CSS_INVALID; + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + if (ident->lower.data == c->strings[INHERIT]) { + flags |= FLAG_INHERIT; + } else if (ident->lower.data == c->strings[NORMAL]) { + value = UNICODE_BIDI_NORMAL; + } else if (ident->lower.data == c->strings[EMBED]) { + value = UNICODE_BIDI_EMBED; + } else if (ident->lower.data == c->strings[BIDI_OVERRIDE]) { + value = UNICODE_BIDI_BIDI_OVERRIDE; + } else + return CSS_INVALID; + + opv = buildOPV(OP_UNICODE_BIDI, flags, value); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + + return CSS_OK; +} + +css_error parse_vertical_align(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *token; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + fixed length = 0; + uint32_t unit = 0; + uint32_t required_size; + + /* length | percentage | IDENT(baseline, sub, super, top, text-top, + * middle, bottom, text-bottom, inherit) + */ + token = parserutils_vector_peek(vector, *ctx); + if (token == NULL) + return CSS_INVALID; + + if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[INHERIT]) { + parserutils_vector_iterate(vector, ctx); + flags = FLAG_INHERIT; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[BASELINE]) { + parserutils_vector_iterate(vector, ctx); + value = VERTICAL_ALIGN_BASELINE; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[SUB]) { + parserutils_vector_iterate(vector, ctx); + value = VERTICAL_ALIGN_SUB; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[SUPER]) { + parserutils_vector_iterate(vector, ctx); + value = VERTICAL_ALIGN_SUPER; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[TOP]) { + parserutils_vector_iterate(vector, ctx); + value = VERTICAL_ALIGN_TOP; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[TEXT_TOP]) { + parserutils_vector_iterate(vector, ctx); + value = VERTICAL_ALIGN_TEXT_TOP; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[MIDDLE]) { + parserutils_vector_iterate(vector, ctx); + value = VERTICAL_ALIGN_MIDDLE; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[BOTTOM]) { + parserutils_vector_iterate(vector, ctx); + value = VERTICAL_ALIGN_BOTTOM; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[TEXT_BOTTOM]) { + parserutils_vector_iterate(vector, ctx); + value = VERTICAL_ALIGN_TEXT_BOTTOM; + } else { + error = parse_unit_specifier(c, vector, ctx, &length, &unit); + if (error != CSS_OK) + return error; + + if (unit & UNIT_ANGLE || unit & UNIT_TIME || unit & UNIT_FREQ) + return CSS_INVALID; + + value = VERTICAL_ALIGN_SET; + } + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + opv = buildOPV(OP_VERTICAL_ALIGN, flags, value); + + required_size = sizeof(opv); + if ((flags & FLAG_INHERIT) == false && value == VERTICAL_ALIGN_SET) + required_size += sizeof(length) + sizeof(unit); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, required_size, result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + if ((flags & FLAG_INHERIT) == false && value == VERTICAL_ALIGN_SET) { + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), + &length, sizeof(length)); + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + + sizeof(length), &unit, sizeof(unit)); + } + + return CSS_OK; +} + +css_error parse_visibility(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *ident; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + + /* IDENT (visible, hidden, collapse, inherit) */ + ident = parserutils_vector_iterate(vector, ctx); + if (ident == NULL || ident->type != CSS_TOKEN_IDENT) + return CSS_INVALID; + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + if (ident->lower.data == c->strings[INHERIT]) { + flags |= FLAG_INHERIT; + } else if (ident->lower.data == c->strings[VISIBLE]) { + value = VISIBILITY_VISIBLE; + } else if (ident->lower.data == c->strings[HIDDEN]) { + value = VISIBILITY_HIDDEN; + } else if (ident->lower.data == c->strings[COLLAPSE]) { + value = VISIBILITY_COLLAPSE; + } else + return CSS_INVALID; + + opv = buildOPV(OP_VISIBILITY, flags, value); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + + return CSS_OK; +} + +css_error parse_voice_family(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + /** \todo voice-family */ + + UNUSED(c); + UNUSED(vector); + UNUSED(ctx); + UNUSED(result); + + return CSS_OK; +} + +css_error parse_volume(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *token; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + fixed length = 0; + uint32_t unit = 0; + uint32_t required_size; + + /* number | percentage | IDENT(silent, x-soft, soft, medium, loud, + * x-loud, inherit) + */ + token = parserutils_vector_peek(vector, *ctx); + if (token == NULL) + return CSS_INVALID; + + if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[INHERIT]) { + parserutils_vector_iterate(vector, ctx); + flags = FLAG_INHERIT; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[SILENT]) { + parserutils_vector_iterate(vector, ctx); + value = VOLUME_SILENT; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[X_SOFT]) { + parserutils_vector_iterate(vector, ctx); + value = VOLUME_X_SOFT; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[SOFT]) { + parserutils_vector_iterate(vector, ctx); + value = VOLUME_SOFT; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[MEDIUM]) { + parserutils_vector_iterate(vector, ctx); + value = VOLUME_MEDIUM; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[LOUD]) { + parserutils_vector_iterate(vector, ctx); + value = VOLUME_LOUD; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[X_LOUD]) { + parserutils_vector_iterate(vector, ctx); + value = VOLUME_X_LOUD; + } else if (token->type == CSS_TOKEN_NUMBER) { + size_t consumed = 0; + length = number_from_css_string(&token->lower, &consumed); + if (consumed != token->lower.len) + return CSS_INVALID; + + value = VOLUME_NUMBER; + } else { + error = parse_unit_specifier(c, vector, ctx, &length, &unit); + if (error != CSS_OK) + return error; + + if ((unit & UNIT_PCT) == false) + return CSS_INVALID; + + value = VOLUME_DIMENSION; + } + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + opv = buildOPV(OP_VOLUME, flags, value); + + required_size = sizeof(opv); + if ((flags & FLAG_INHERIT) == false && value == VOLUME_NUMBER) + required_size += sizeof(length); + else if ((flags & FLAG_INHERIT) == false && value == VOLUME_DIMENSION) + required_size += sizeof(length) + sizeof(unit); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, required_size, result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + if ((flags & FLAG_INHERIT) == false && (value == VOLUME_NUMBER || + value == VOLUME_DIMENSION)) + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), + &length, sizeof(length)); + if ((flags & FLAG_INHERIT) == false && value == VOLUME_DIMENSION) + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + + sizeof(length), &unit, sizeof(unit)); + + return CSS_OK; +} + +css_error parse_white_space(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *ident; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + + /* IDENT (normal, pre, nowrap, pre-wrap, pre-line, inherit) */ + ident = parserutils_vector_iterate(vector, ctx); + if (ident == NULL || ident->type != CSS_TOKEN_IDENT) + return CSS_INVALID; + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + if (ident->lower.data == c->strings[INHERIT]) { + flags |= FLAG_INHERIT; + } else if (ident->lower.data == c->strings[NORMAL]) { + value = WHITE_SPACE_NORMAL; + } else if (ident->lower.data == c->strings[PRE]) { + value = WHITE_SPACE_PRE; + } else if (ident->lower.data == c->strings[NOWRAP]) { + value = WHITE_SPACE_NOWRAP; + } else if (ident->lower.data == c->strings[PRE_WRAP]) { + value = WHITE_SPACE_PRE_WRAP; + } else if (ident->lower.data == c->strings[PRE_LINE]) { + value = WHITE_SPACE_PRE_LINE; + } else + return CSS_INVALID; + + opv = buildOPV(OP_WHITE_SPACE, flags, value); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + + return CSS_OK; +} + +css_error parse_widows(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *token; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + fixed num = 0; + uint32_t required_size; + + /* | IDENT (inherit) */ + token = parserutils_vector_iterate(vector, ctx); + if (token == NULL || (token->type != CSS_TOKEN_IDENT && + token->type != CSS_TOKEN_NUMBER)) + return CSS_INVALID; + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + if (token->lower.data == c->strings[INHERIT]) { + flags |= FLAG_INHERIT; + } else if (token->type == CSS_TOKEN_NUMBER) { + size_t consumed = 0; + num = number_from_css_string(&token->lower, &consumed); + int32_t intpart = FIXTOINT(num); + /* Invalid if there are trailing characters or it was a float */ + if (consumed != token->lower.len || num != intpart) + return CSS_INVALID; + + value = WIDOWS_SET; + } else + return CSS_INVALID; + + opv = buildOPV(OP_WIDOWS, flags, value); + + required_size = sizeof(opv); + if ((flags & FLAG_INHERIT) == false && value == WIDOWS_SET) + required_size += sizeof(num); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, required_size, result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + if ((flags & FLAG_INHERIT) == false && value == WIDOWS_SET) { + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), + &num, sizeof(num)); + } + + return CSS_OK; +} + +css_error parse_width(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *token; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + fixed length = 0; + uint32_t unit = 0; + uint32_t required_size; + + /* length | percentage | IDENT(auto, inherit) */ + token = parserutils_vector_peek(vector, *ctx); + if (token == NULL) + return CSS_INVALID; + + if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[INHERIT]) { + parserutils_vector_iterate(vector, ctx); + flags = FLAG_INHERIT; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[AUTO]) { + parserutils_vector_iterate(vector, ctx); + value = WIDTH_AUTO; + } else { + error = parse_unit_specifier(c, vector, ctx, &length, &unit); + if (error != CSS_OK) + return error; + + if (unit & UNIT_ANGLE || unit & UNIT_TIME || unit & UNIT_FREQ) + return CSS_INVALID; + + value = WIDTH_SET; + } + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + opv = buildOPV(OP_WIDTH, flags, value); + + required_size = sizeof(opv); + if ((flags & FLAG_INHERIT) == false && value == WIDTH_SET) + required_size += sizeof(length) + sizeof(unit); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, required_size, result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + if ((flags & FLAG_INHERIT) == false && value == WIDTH_SET) { + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), + &length, sizeof(length)); + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + + sizeof(length), &unit, sizeof(unit)); + } + + return CSS_OK; +} + +css_error parse_word_spacing(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *token; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + fixed length = 0; + uint32_t unit = 0; + uint32_t required_size; + + /* length | IDENT(normal, inherit) */ + token = parserutils_vector_peek(vector, *ctx); + if (token == NULL) + return CSS_INVALID; + + if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[INHERIT]) { + parserutils_vector_iterate(vector, ctx); + flags = FLAG_INHERIT; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[NORMAL]) { + parserutils_vector_iterate(vector, ctx); + value = WORD_SPACING_NORMAL; + } else { + error = parse_unit_specifier(c, vector, ctx, &length, &unit); + if (error != CSS_OK) + return error; + + if (unit & UNIT_ANGLE || unit & UNIT_TIME || unit & UNIT_FREQ || + unit & UNIT_PCT) + return CSS_INVALID; + + value = WORD_SPACING_SET; + } + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + opv = buildOPV(OP_WORD_SPACING, flags, value); + + required_size = sizeof(opv); + if ((flags & FLAG_INHERIT) == false && value == WORD_SPACING_SET) + required_size += sizeof(length) + sizeof(unit); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, required_size, result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + if ((flags & FLAG_INHERIT) == false && value == WORD_SPACING_SET) { + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), + &length, sizeof(length)); + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + + sizeof(length), &unit, sizeof(unit)); + } + + return CSS_OK; +} + +css_error parse_z_index(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + css_error error; + const css_token *token; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + fixed num = 0; + uint32_t required_size; + + /* | IDENT (auto, inherit) */ + token = parserutils_vector_iterate(vector, ctx); + if (token == NULL || (token->type != CSS_TOKEN_IDENT && + token->type != CSS_TOKEN_NUMBER)) + return CSS_INVALID; + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[INHERIT]) { + flags |= FLAG_INHERIT; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[AUTO]) { + value = Z_INDEX_AUTO; + } else if (token->type == CSS_TOKEN_NUMBER) { + size_t consumed = 0; + num = number_from_css_string(&token->lower, &consumed); + int32_t intpart = FIXTOINT(num); + /* Invalid if there are trailing characters or it was a float */ + if (consumed != token->lower.len || num != intpart) + return CSS_INVALID; + + value = Z_INDEX_SET; + } else + return CSS_INVALID; + + opv = buildOPV(OP_Z_INDEX, flags, value); + + required_size = sizeof(opv); + if ((flags & FLAG_INHERIT) == false && value == Z_INDEX_SET) + required_size += sizeof(num); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, required_size, result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + if ((flags & FLAG_INHERIT) == false && value == Z_INDEX_SET) { + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), + &num, sizeof(num)); + } + + return CSS_OK; +} + +css_error parse_important(css_language *c, + const parserutils_vector *vector, int *ctx, + uint8_t *result) +{ + const css_token *token; + + consumeWhitespace(vector, ctx); + + token = parserutils_vector_iterate(vector, ctx); + if (token != NULL && tokenIsChar(token, '!')) { + consumeWhitespace(vector, ctx); + + token = parserutils_vector_iterate(vector, ctx); + if (token == NULL || token->type != CSS_TOKEN_IDENT) + return CSS_INVALID; + + if (token->lower.data == c->strings[IMPORTANT]) + *result |= FLAG_IMPORTANT; + } else if (token != NULL) + return CSS_INVALID; + + return CSS_OK; +} + +css_error parse_colour_specifier(css_language *c, + const parserutils_vector *vector, int *ctx, + uint32_t *result) +{ + const css_token *token; + + UNUSED(c); + UNUSED(result); + + /** \todo Parse colours */ + + /* For now, consume everything up to the end of the declaration or !, + * whichever comes first */ + while ((token = parserutils_vector_peek(vector, *ctx)) != NULL && + tokenIsChar(token, '!') == false) + parserutils_vector_iterate(vector, ctx); + + return CSS_OK; +} + +css_error parse_unit_specifier(css_language *c, + const parserutils_vector *vector, int *ctx, + fixed *length, uint32_t *unit) +{ + const css_token *token; + + UNUSED(c); + UNUSED(length); + UNUSED(unit); + + /** \todo Parse units */ + + /* For now, consume everything up to the end of the declaration or !, + * whichever comes first */ + while ((token = parserutils_vector_peek(vector, *ctx)) != NULL && + tokenIsChar(token, '!') == false) + parserutils_vector_iterate(vector, ctx); + + return CSS_OK; +} + +css_error parse_border_side_color(css_language *c, + const parserutils_vector *vector, int *ctx, + uint16_t side, css_style **result) +{ + css_error error; + const css_token *token; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + uint32_t colour = 0; + uint32_t required_size; + + /* colour | IDENT (transparent, inherit) */ + token= parserutils_vector_peek(vector, *ctx); + if (token == NULL) + return CSS_INVALID; + + if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[INHERIT]) { + parserutils_vector_iterate(vector, ctx); + flags |= FLAG_INHERIT; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[TRANSPARENT]) { + parserutils_vector_iterate(vector, ctx); + value = BORDER_COLOR_TRANSPARENT; + } else { + error = parse_colour_specifier(c, vector, ctx, &colour); + if (error != CSS_OK) + return error; + + value = BORDER_COLOR_SET; + } + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + opv = buildOPV(OP_BORDER_TRBL_COLOR, flags, value | side); + + required_size = sizeof(opv); + if ((flags & FLAG_INHERIT) == false && value == BORDER_COLOR_SET) + required_size += sizeof(colour); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, required_size, result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + if ((flags & FLAG_INHERIT) == false && value == BORDER_COLOR_SET) { + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), + &colour, sizeof(colour)); + } + + return CSS_OK; +} + +css_error parse_border_side_style(css_language *c, + const parserutils_vector *vector, int *ctx, + uint16_t side, css_style **result) +{ + css_error error; + const css_token *ident; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + + /* IDENT (none, hidden, dotted, dashed, solid, double, groove, + * ridge, inset, outset, inherit) */ + ident = parserutils_vector_iterate(vector, ctx); + if (ident == NULL || ident->type != CSS_TOKEN_IDENT) + return CSS_INVALID; + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + if (ident->lower.data == c->strings[INHERIT]) { + flags |= FLAG_INHERIT; + } else if (ident->lower.data == c->strings[NONE]) { + value = BORDER_STYLE_NONE; + } else if (ident->lower.data == c->strings[HIDDEN]) { + value = BORDER_STYLE_HIDDEN; + } else if (ident->lower.data == c->strings[DOTTED]) { + value = BORDER_STYLE_DOTTED; + } else if (ident->lower.data == c->strings[DASHED]) { + value = BORDER_STYLE_DASHED; + } else if (ident->lower.data == c->strings[SOLID]) { + value = BORDER_STYLE_SOLID; + } else if (ident->lower.data == c->strings[DOUBLE]) { + value = BORDER_STYLE_DOUBLE; + } else if (ident->lower.data == c->strings[GROOVE]) { + value = BORDER_STYLE_GROOVE; + } else if (ident->lower.data == c->strings[RIDGE]) { + value = BORDER_STYLE_RIDGE; + } else if (ident->lower.data == c->strings[INSET]) { + value = BORDER_STYLE_INSET; + } else if (ident->lower.data == c->strings[OUTSET]) { + value = BORDER_STYLE_OUTSET; + } else + return CSS_INVALID; + + opv = buildOPV(OP_BORDER_TRBL_STYLE, flags, value | side); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, sizeof(opv), result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + + return CSS_OK; +} + +css_error parse_border_side_width(css_language *c, + const parserutils_vector *vector, int *ctx, + uint16_t side, css_style **result) +{ + css_error error; + const css_token *token; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + fixed length = 0; + uint32_t unit = 0; + uint32_t required_size; + + /* length | IDENT(thin, medium, thick, inherit) */ + token= parserutils_vector_peek(vector, *ctx); + if (token == NULL) + return CSS_INVALID; + + if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[INHERIT]) { + parserutils_vector_iterate(vector, ctx); + flags |= FLAG_INHERIT; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[THIN]) { + parserutils_vector_iterate(vector, ctx); + value = BORDER_WIDTH_THIN; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[MEDIUM]) { + parserutils_vector_iterate(vector, ctx); + value = BORDER_WIDTH_MEDIUM; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[THICK]) { + parserutils_vector_iterate(vector, ctx); + value = BORDER_WIDTH_THICK; + } else { + error = parse_unit_specifier(c, vector, ctx, &length, &unit); + if (error != CSS_OK) + return error; + + if (unit == UNIT_PCT || unit & UNIT_ANGLE || + unit & UNIT_TIME || unit & UNIT_FREQ) + return CSS_INVALID; + + value = BORDER_WIDTH_SET; + } + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + opv = buildOPV(OP_BORDER_TRBL_WIDTH, flags, value | side); + + required_size = sizeof(opv); + if ((flags & FLAG_INHERIT) == false && value == BORDER_WIDTH_SET) + required_size += sizeof(length) + sizeof(unit); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, required_size, result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + if ((flags & FLAG_INHERIT) == false && value == BORDER_WIDTH_SET) { + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), + &length, sizeof(length)); + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + + sizeof(length), &unit, sizeof(unit)); + } + + return CSS_OK; +} + +css_error parse_margin_side(css_language *c, + const parserutils_vector *vector, int *ctx, + uint16_t side, css_style **result) +{ + css_error error; + const css_token *token; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + fixed length = 0; + uint32_t unit = 0; + uint32_t required_size; + + /* length | percentage | IDENT(auto, inherit) */ + token = parserutils_vector_peek(vector, *ctx); + if (token == NULL) + return CSS_INVALID; + + if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[INHERIT]) { + parserutils_vector_iterate(vector, ctx); + flags = FLAG_INHERIT; + } else if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[AUTO]) { + parserutils_vector_iterate(vector, ctx); + value = MARGIN_AUTO; + } else { + error = parse_unit_specifier(c, vector, ctx, &length, &unit); + if (error != CSS_OK) + return error; + + if (unit & UNIT_ANGLE || unit & UNIT_TIME || unit & UNIT_FREQ) + return CSS_INVALID; + + value = MARGIN_SET; + } + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + opv = buildOPV(OP_MARGIN_TRBL, flags, value | side); + + required_size = sizeof(opv); + if ((flags & FLAG_INHERIT) == false && value == MARGIN_SET) + required_size += sizeof(length) + sizeof(unit); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, required_size, result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + if ((flags & FLAG_INHERIT) == false && value == MARGIN_SET) { + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), + &length, sizeof(length)); + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + + sizeof(length), &unit, sizeof(unit)); + } + + return CSS_OK; +} + +css_error parse_padding_side(css_language *c, + const parserutils_vector *vector, int *ctx, + uint16_t side, css_style **result) +{ + css_error error; + const css_token *token; + uint8_t flags = 0; + uint16_t value = 0; + uint32_t opv; + fixed length = 0; + uint32_t unit = 0; + uint32_t required_size; + + /* length | percentage | IDENT(inherit) */ + token = parserutils_vector_peek(vector, *ctx); + if (token == NULL) + return CSS_INVALID; + + if (token->type == CSS_TOKEN_IDENT && + token->lower.data == c->strings[INHERIT]) { + parserutils_vector_iterate(vector, ctx); + flags = FLAG_INHERIT; + } else { + error = parse_unit_specifier(c, vector, ctx, &length, &unit); + if (error != CSS_OK) + return error; + + if (unit & UNIT_ANGLE || unit & UNIT_TIME || unit & UNIT_FREQ) + return CSS_INVALID; + + value = PADDING_SET; + } + + error = parse_important(c, vector, ctx, &flags); + if (error != CSS_OK) + return error; + + opv = buildOPV(OP_PADDING_TRBL, flags, value | side); + + required_size = sizeof(opv); + if ((flags & FLAG_INHERIT) == false && value == PADDING_SET) + required_size += sizeof(length) + sizeof(unit); + + /* Allocate result */ + error = css_stylesheet_style_create(c->sheet, required_size, result); + if (error != CSS_OK) + return error; + + /* Copy the bytecode to it */ + memcpy((*result)->bytecode, &opv, sizeof(opv)); + if ((flags & FLAG_INHERIT) == false && value == PADDING_SET) { + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv), + &length, sizeof(length)); + memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv) + + sizeof(length), &unit, sizeof(unit)); + } + + return CSS_OK; +} + + +#endif diff --git a/src/parse/propstrings.h b/src/parse/propstrings.h new file mode 100644 index 0000000..4050840 --- /dev/null +++ b/src/parse/propstrings.h @@ -0,0 +1,305 @@ +/* + * This file is part of LibCSS. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2008 John-Mark Bell + */ + +#ifndef css_parse_propstrings_h_ +#define css_parse_propstrings_h_ + +#include "utils/utils.h" + +enum { + /* At-rules */ + CHARSET, IMPORT, MEDIA, PAGE, + + /* Properties */ + FIRST_PROP, + + AZIMUTH = FIRST_PROP, BACKGROUND_ATTACHMENT, BACKGROUND_COLOR, + BACKGROUND_IMAGE, BACKGROUND_POSITION, BACKGROUND_REPEAT, + BORDER_BOTTOM_COLOR, BORDER_BOTTOM_STYLE, BORDER_BOTTOM_WIDTH, + BORDER_COLLAPSE, BORDER_LEFT_COLOR, BORDER_LEFT_STYLE, + BORDER_LEFT_WIDTH, BORDER_RIGHT_COLOR, BORDER_RIGHT_STYLE, + BORDER_RIGHT_WIDTH, BORDER_SPACING, BORDER_TOP_COLOR, BORDER_TOP_STYLE, + BORDER_TOP_WIDTH, BOTTOM, CAPTION_SIDE, CLEAR, CLIP, COLOR, CONTENT, + COUNTER_INCREMENT, COUNTER_RESET, CUE_AFTER, CUE_BEFORE, CURSOR, + DIRECTION, DISPLAY, ELEVATION, EMPTY_CELLS, FLOAT, FONT_FAMILY, + FONT_SIZE, FONT_STYLE, FONT_VARIANT, FONT_WEIGHT, HEIGHT, LEFT, + LETTER_SPACING, LINE_HEIGHT, LIST_STYLE_IMAGE, LIST_STYLE_POSITION, + LIST_STYLE_TYPE, MARGIN_BOTTOM, MARGIN_LEFT, MARGIN_RIGHT, MARGIN_TOP, + MAX_HEIGHT, MAX_WIDTH, MIN_HEIGHT, MIN_WIDTH, ORPHANS, OUTLINE_COLOR, + OUTLINE_STYLE, OUTLINE_WIDTH, OVERFLOW, PADDING_BOTTOM, PADDING_LEFT, + PADDING_RIGHT, PADDING_TOP, PAGE_BREAK_AFTER, PAGE_BREAK_BEFORE, + PAGE_BREAK_INSIDE, PAUSE_AFTER, PAUSE_BEFORE, PITCH_RANGE, PITCH, + PLAY_DURING, POSITION, QUOTES, RICHNESS, RIGHT, SPEAK_HEADER, + SPEAK_NUMERAL, SPEAK_PUNCTUATION, SPEAK, SPEECH_RATE, STRESS, + TABLE_LAYOUT, TEXT_ALIGN, TEXT_DECORATION, TEXT_INDENT, TEXT_TRANSFORM, + TOP, UNICODE_BIDI, VERTICAL_ALIGN, VISIBILITY, VOICE_FAMILY, VOLUME, + WHITE_SPACE, WIDOWS, WIDTH, WORD_SPACING, Z_INDEX, + + LAST_PROP = Z_INDEX, + + /* Other keywords */ + INHERIT, IMPORTANT, NONE, BOTH, FIXED, SCROLL, TRANSPARENT, + NO_REPEAT, REPEAT_X, REPEAT_Y, REPEAT, HIDDEN, DOTTED, DASHED, + SOLID, DOUBLE, GROOVE, RIDGE, INSET, OUTSET, THIN, MEDIUM, THICK, + COLLAPSE, SEPARATE, AUTO, LTR, RTL, INLINE, BLOCK, LIST_ITEM, RUN_IN, + INLINE_BLOCK, TABLE, INLINE_TABLE, TABLE_ROW_GROUP, TABLE_HEADER_GROUP, + TABLE_FOOTER_GROUP, TABLE_ROW, TABLE_COLUMN_GROUP, TABLE_COLUMN, + TABLE_CELL, TABLE_CAPTION, BELOW, LEVEL, ABOVE, HIGHER, LOWER, + SHOW, HIDE, XX_SMALL, X_SMALL, SMALL, LARGE, X_LARGE, XX_LARGE, + LARGER, SMALLER, NORMAL, ITALIC, OBLIQUE, SMALL_CAPS, BOLD, BOLDER, + LIGHTER, INSIDE, OUTSIDE, DISC, CIRCLE, SQUARE, DECIMAL, + DECIMAL_LEADING_ZERO, LOWER_ROMAN, UPPER_ROMAN, LOWER_GREEK, + LOWER_LATIN, UPPER_LATIN, ARMENIAN, GEORGIAN, LOWER_ALPHA, UPPER_ALPHA, + INVERT, VISIBLE, ALWAYS, AVOID, X_LOW, LOW, HIGH, X_HIGH, STATIC, + RELATIVE, ABSOLUTE, ONCE, DIGITS, CONTINUOUS, CODE, SPELL_OUT, X_SLOW, + SLOW, FAST, X_FAST, FASTER, SLOWER, CENTER, JUSTIFY, CAPITALIZE, + UPPERCASE, LOWERCASE, EMBED, BIDI_OVERRIDE, BASELINE, SUB, SUPER, + TEXT_TOP, MIDDLE, TEXT_BOTTOM, SILENT, X_SOFT, SOFT, LOUD, X_LOUD, + PRE, NOWRAP, PRE_WRAP, PRE_LINE, + + LAST_KNOWN +}; + +/* Must be synchronised with above enum */ +static struct { + const char *data; + size_t len; +} stringmap[LAST_KNOWN] = { + { "charset", SLEN("charset") }, + { "import", SLEN("import") }, + { "media", SLEN("media") }, + { "page", SLEN("page") }, + + { "azimuth", SLEN("azimuth") }, + { "background-attachment", SLEN("background-attachment") }, + { "background-color", SLEN("background-color") }, + { "background-image", SLEN("background-image") }, + { "background-position", SLEN("background-position") }, + { "background-repeat", SLEN("background-repeat") }, + { "border-bottom-color", SLEN("border-bottom-color") }, + { "border-bottom-style", SLEN("border-bottom-style") }, + { "border-bottom-width", SLEN("border-bottom-width") }, + { "border-collapse", SLEN("border-collapse") }, + { "border-left-color", SLEN("border-left-color") }, + { "border-left-style", SLEN("border-left-style") }, + { "border-left-width", SLEN("border-left-width") }, + { "border-right-color", SLEN("border-right-color") }, + { "border-right-style", SLEN("border-right-style") }, + { "border-right-width", SLEN("border-right-width") }, + { "border-spacing", SLEN("border-spacing") }, + { "border-top-color", SLEN("border-top-color") }, + { "border-top-style", SLEN("border-top-style") }, + { "border-top-width", SLEN("border-top-width") }, + { "bottom", SLEN("bottom") }, + { "caption-side", SLEN("caption-side") }, + { "clear", SLEN("clear") }, + { "clip", SLEN("clip") }, + { "color", SLEN("color") }, + { "content", SLEN("content") }, + { "counter-increment", SLEN("counter-increment") }, + { "counter-reset", SLEN("counter-reset") }, + { "cue-after", SLEN("cue-after") }, + { "cue-before", SLEN("cue-before") }, + { "cursor", SLEN("cursor") }, + { "direction", SLEN("direction") }, + { "display", SLEN("display") }, + { "elevation", SLEN("elevation") }, + { "empty-cells", SLEN("empty-cells") }, + { "float", SLEN("float") }, + { "font-family", SLEN("font-family") }, + { "font-size", SLEN("font-size") }, + { "font-style", SLEN("font-style") }, + { "font-variant", SLEN("font-variant") }, + { "font-weight", SLEN("font-weight") }, + { "height", SLEN("height") }, + { "left", SLEN("left") }, + { "letter-spacing", SLEN("letter-spacing") }, + { "line-height", SLEN("line-height") }, + { "list-style-image", SLEN("list-style-image") }, + { "list-style-position", SLEN("list-style-position") }, + { "list-style-type", SLEN("list-style-type") }, + { "margin-bottom", SLEN("margin-bottom") }, + { "margin-left", SLEN("margin-left") }, + { "margin-right", SLEN("margin-right") }, + { "margin-top", SLEN("margin-top") }, + { "max-height", SLEN("max-height") }, + { "max-width", SLEN("max-width") }, + { "min-height", SLEN("min-height") }, + { "min-width", SLEN("min-width") }, + { "orphans", SLEN("orphans") }, + { "outline-color", SLEN("outline-color") }, + { "outline-style", SLEN("outline-style") }, + { "outline-width", SLEN("outline-width") }, + { "overflow", SLEN("overflow") }, + { "padding-bottom", SLEN("padding-bottom") }, + { "padding-left", SLEN("padding-left") }, + { "padding-right", SLEN("padding-right") }, + { "padding-top", SLEN("padding-top") }, + { "page-break-after", SLEN("page-break-after") }, + { "page-break-before", SLEN("page-break-before") }, + { "page-break-inside", SLEN("page-break-inside") }, + { "pause-after", SLEN("pause-after") }, + { "pause-before", SLEN("pause-before") }, + { "pitch-range", SLEN("pitch-range") }, + { "pitch", SLEN("pitch") }, + { "play-during", SLEN("play-during") }, + { "position", SLEN("position") }, + { "quotes", SLEN("quotes") }, + { "richness", SLEN("richness") }, + { "right", SLEN("right") }, + { "speak-header", SLEN("speak-header") }, + { "speak-numeral", SLEN("speak-numeral") }, + { "speak-punctuation", SLEN("speak-punctuation") }, + { "speak", SLEN("speak") }, + { "speech-rate", SLEN("speech-rate") }, + { "stress", SLEN("stress") }, + { "table-layout", SLEN("table-layout") }, + { "text-align", SLEN("text-align") }, + { "text-decoration", SLEN("text-decoration") }, + { "text-indent", SLEN("text-indent") }, + { "text-transform", SLEN("text-transform") }, + { "top", SLEN("top") }, + { "unicode-bidi", SLEN("unicode-bidi") }, + { "vertical-align", SLEN("vertical-align") }, + { "visibility", SLEN("visibility") }, + { "voice-family", SLEN("voice-family") }, + { "volume", SLEN("volume") }, + { "white-space", SLEN("white-space") }, + { "widows", SLEN("widows") }, + { "width", SLEN("width") }, + { "word-spacing", SLEN("word-spacing") }, + { "z-index", SLEN("z-index") }, + + { "inherit", SLEN("inherit") }, + { "important", SLEN("important") }, + { "none", SLEN("none") }, + { "both", SLEN("both") }, + { "fixed", SLEN("fixed") }, + { "scroll", SLEN("scroll") }, + { "transparent", SLEN("transparent") }, + { "no-repeat", SLEN("no-repeat") }, + { "repeat-x", SLEN("repeat-x") }, + { "repeat-y", SLEN("repeat-y") }, + { "repeat", SLEN("repeat") }, + { "hidden", SLEN("hidden") }, + { "dotted", SLEN("dotted") }, + { "dashed", SLEN("dashed") }, + { "solid", SLEN("solid") }, + { "double", SLEN("double") }, + { "groove", SLEN("groove") }, + { "ridge", SLEN("ridge") }, + { "inset", SLEN("inset") }, + { "outset", SLEN("outset") }, + { "thin", SLEN("thin") }, + { "medium", SLEN("medium") }, + { "thick", SLEN("thick") }, + { "collapse", SLEN("collapse") }, + { "separate", SLEN("separate") }, + { "auto", SLEN("auto") }, + { "ltr", SLEN("ltr") }, + { "rtl", SLEN("rtl") }, + { "inline", SLEN("inline") }, + { "block", SLEN("block") }, + { "list-item", SLEN("list-item") }, + { "run-in", SLEN("run-in") }, + { "inline-block", SLEN("inline-block") }, + { "table", SLEN("table") }, + { "inline-table", SLEN("inline-table") }, + { "table-row-group", SLEN("table-row-group") }, + { "table-header-group", SLEN("table-header-group") }, + { "table-footer-group", SLEN("table-footer-group") }, + { "table-row", SLEN("table-row") }, + { "table-column-group", SLEN("table-column-group") }, + { "table-column", SLEN("table-column") }, + { "table-cell", SLEN("table-cell") }, + { "table-caption", SLEN("table-caption") }, + { "below", SLEN("below") }, + { "level", SLEN("level") }, + { "above", SLEN("above") }, + { "higher", SLEN("higher") }, + { "lower", SLEN("lower") }, + { "show", SLEN("show") }, + { "hide", SLEN("hide") }, + { "xx-small", SLEN("xx-small") }, + { "x-small", SLEN("x-small") }, + { "small", SLEN("small") }, + { "large", SLEN("large") }, + { "x-large", SLEN("x-large") }, + { "xx-large", SLEN("xx-large") }, + { "larger", SLEN("larger") }, + { "smaller", SLEN("smaller") }, + { "normal", SLEN("normal") }, + { "italic", SLEN("italic") }, + { "oblique", SLEN("oblique") }, + { "small-caps", SLEN("small-caps") }, + { "bold", SLEN("bold") }, + { "bolder", SLEN("bolder") }, + { "lighter", SLEN("lighter") }, + { "inside", SLEN("inside") }, + { "outside", SLEN("outside") }, + { "disc", SLEN("disc") }, + { "circle", SLEN("circle") }, + { "square", SLEN("square") }, + { "decimal", SLEN("decimal") }, + { "decimal-leading-zero", SLEN("decimal-leading-zero") }, + { "lower-roman", SLEN("lower-roman") }, + { "upper-roman", SLEN("upper-roman") }, + { "lower-greek", SLEN("lower-greek") }, + { "lower-latin", SLEN("lower-latin") }, + { "upper-latin", SLEN("upper-latin") }, + { "armenian", SLEN("armenian") }, + { "georgian", SLEN("georgian") }, + { "lower-alpha", SLEN("lower-alpha") }, + { "upper-alpha", SLEN("upper-alpha") }, + { "invert", SLEN("invert") }, + { "visible", SLEN("visible") }, + { "always", SLEN("always") }, + { "avoid", SLEN("avoid") }, + { "x-low", SLEN("x-low") }, + { "low", SLEN("low") }, + { "high", SLEN("high") }, + { "x-high", SLEN("x-high") }, + { "static", SLEN("static") }, + { "relative", SLEN("relative") }, + { "absolute", SLEN("absolute") }, + { "once", SLEN("once") }, + { "digits", SLEN("digits") }, + { "continuous", SLEN("continuous") }, + { "code", SLEN("code") }, + { "spell-out", SLEN("spell-out") }, + { "x-slow", SLEN("x-slow") }, + { "slow", SLEN("slow") }, + { "fast", SLEN("fast") }, + { "x-fast", SLEN("x-fast") }, + { "faster", SLEN("faster") }, + { "slower", SLEN("slower") }, + { "center", SLEN("center") }, + { "justify", SLEN("justify") }, + { "capitalize", SLEN("capitalize") }, + { "uppercase", SLEN("uppercase") }, + { "lowercase", SLEN("lowercase") }, + { "embed", SLEN("embed") }, + { "bidi-override", SLEN("bidi-override") }, + { "baseline", SLEN("baseline") }, + { "sub", SLEN("sub") }, + { "super", SLEN("super") }, + { "text-top", SLEN("text-top") }, + { "middle", SLEN("middle") }, + { "text-bottom", SLEN("text-bottom") }, + { "silent", SLEN("silent") }, + { "x-soft", SLEN("x-soft") }, + { "soft", SLEN("soft") }, + { "loud", SLEN("loud") }, + { "x-loud", SLEN("x-loud") }, + { "pre", SLEN("pre") }, + { "nowrap", SLEN("nowrap") }, + { "pre-wrap", SLEN("pre-wrap") }, + { "pre-line", SLEN("pre-line") }, +}; + +#endif + diff --git a/src/stylesheet.c b/src/stylesheet.c index 0936243..5c6e68d 100644 --- a/src/stylesheet.c +++ b/src/stylesheet.c @@ -9,7 +9,7 @@ #include "stylesheet.h" #include "bytecode/bytecode.h" -#include "parse/css21.h" +#include "parse/language.h" #include "utils/parserutilserror.h" #include "utils/utils.h" @@ -67,16 +67,8 @@ css_error css_stylesheet_create(css_language_level level, return error; } - /* We only support CSS 2.1 */ - if (level != CSS_LEVEL_21) { - css_parser_destroy(sheet->parser); - parserutils_dict_destroy(sheet->dictionary); - alloc(sheet, 0, alloc_pw); - return CSS_INVALID; /** \todo better error */ - } - sheet->level = level; - error = css_css21_create(sheet, sheet->parser, alloc, alloc_pw, + error = css_language_create(sheet, sheet->parser, alloc, alloc_pw, &sheet->parser_frontend); if (error != CSS_OK) { css_parser_destroy(sheet->parser); @@ -90,7 +82,7 @@ css_error css_stylesheet_create(css_language_level level, len = strlen(url) + 1; sheet->url = alloc(NULL, len, alloc_pw); if (sheet->url == NULL) { - css_css21_destroy(sheet->parser_frontend); + css_language_destroy(sheet->parser_frontend); css_parser_destroy(sheet->parser); parserutils_dict_destroy(sheet->dictionary); alloc(sheet, 0, alloc_pw); @@ -103,7 +95,7 @@ css_error css_stylesheet_create(css_language_level level, sheet->title = alloc(NULL, len, alloc_pw); if (sheet->title == NULL) { alloc(sheet->url, 0, alloc_pw); - css_css21_destroy(sheet->parser_frontend); + css_language_destroy(sheet->parser_frontend); css_parser_destroy(sheet->parser); parserutils_dict_destroy(sheet->dictionary); alloc(sheet, 0, alloc_pw); @@ -146,7 +138,7 @@ css_error css_stylesheet_destroy(css_stylesheet *sheet) /** \todo destroy selector hash + other data */ - css_css21_destroy(sheet->parser_frontend); + css_language_destroy(sheet->parser_frontend); css_parser_destroy(sheet->parser); -- cgit v1.2.3