summaryrefslogtreecommitdiff
path: root/src/parse/css21props.c
diff options
context:
space:
mode:
authorJohn Mark Bell <jmb@netsurf-browser.org>2008-10-25 01:24:03 +0000
committerJohn Mark Bell <jmb@netsurf-browser.org>2008-10-25 01:24:03 +0000
commit5caf9a56956f55b70d937cea7e135417bada7b25 (patch)
tree1fec329c7b8133c3ef4b76b18ae48fb161f94c71 /src/parse/css21props.c
parentc8e73871f9006987983fd1010d97b6168c13f6a3 (diff)
downloadlibcss-5caf9a56956f55b70d937cea7e135417bada7b25.tar.gz
libcss-5caf9a56956f55b70d937cea7e135417bada7b25.tar.bz2
A bunch of property parsers.
Split out !important parsing into a separate function. Support for dumping bytecode to a file handle in some kind of human-readable format. Strings can be represented in the bytecode as a pointer, length pair rather than embedding the string data into the bytecode -- all strings are interned by the core syntax parser. Add todo relating to early destruction of parser object (it shouldn't be needed once parsing is complete). Note documented issue surrounding interned string dictionary, however. In general, it seems wasteful to create a new dictionary containing string representations of keywords for every single parser instance. It would be better to have one central (statically allocated?) dictionary for this and then each parser instance can have a smaller dictionary containing any unknown strings contained within the stylesheet being parsed (e.g. string constants or URLs). svn path=/trunk/libcss/; revision=5627
Diffstat (limited to 'src/parse/css21props.c')
-rw-r--r--src/parse/css21props.c280
1 files changed, 232 insertions, 48 deletions
diff --git a/src/parse/css21props.c b/src/parse/css21props.c
index c47ef99..09eb889 100644
--- a/src/parse/css21props.c
+++ b/src/parse/css21props.c
@@ -309,6 +309,13 @@ 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);
+
/**
* Type of property handler function
*/
@@ -319,7 +326,7 @@ typedef css_error (*css_prop_handler)(css_css21 *c,
/**
* Dispatch table of property handlers, indexed by property enum
*/
-static const css_prop_handler property_handlers[LAST_KNOWN - FIRST_PROP] =
+static const css_prop_handler property_handlers[LAST_PROP + 1 - FIRST_PROP] =
{
parse_azimuth,
parse_background_attachment,
@@ -426,6 +433,7 @@ css_error parse_azimuth(css_css21 *c,
const parserutils_vector *vector, int *ctx,
css_style **result)
{
+ /** \todo azimuth */
UNUSED(c);
UNUSED(vector);
UNUSED(ctx);
@@ -438,10 +446,39 @@ css_error parse_background_attachment(css_css21 *c,
const parserutils_vector *vector, int *ctx,
css_style **result)
{
- UNUSED(c);
- UNUSED(vector);
- UNUSED(ctx);
- UNUSED(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.ptr == c->strings[INHERIT]) {
+ flags |= FLAG_INHERIT;
+ } else if (ident->lower.ptr == c->strings[FIXED]) {
+ value = BACKGROUND_ATTACHMENT_FIXED;
+ } else if (ident->lower.ptr == c->strings[SCROLL]) {
+ value = BACKGROUND_ATTACHMENT_SCROLL;
+ } else
+ return CSS_INVALID;
+
+ opv = buildOPV(OP_BACKGROUND_ATTACHMENT, flags, value);
+
+ /* Allocate result */
+ *result = css_stylesheet_style_create(c->sheet, sizeof(opv));
+ if (*result == NULL)
+ return CSS_NOMEM;
+
+ /* Copy the bytecode to it */
+ memcpy((*result)->bytecode, &opv, sizeof(opv));
return CSS_OK;
}
@@ -450,10 +487,56 @@ css_error parse_background_color(css_css21 *c,
const parserutils_vector *vector, int *ctx,
css_style **result)
{
- UNUSED(c);
- UNUSED(vector);
- UNUSED(ctx);
- UNUSED(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.ptr == c->strings[INHERIT]) {
+ parserutils_vector_iterate(vector, ctx);
+ flags |= FLAG_INHERIT;
+ } else if (token->type == CSS_TOKEN_IDENT &&
+ token->lower.ptr == 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 CSS_INVALID;
+
+ 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 (value == BACKGROUND_COLOR_SET)
+ required_size += sizeof(colour);
+
+ /* Allocate result */
+ *result = css_stylesheet_style_create(c->sheet, required_size);
+ if (*result == NULL)
+ return CSS_NOMEM;
+
+ /* Copy the bytecode to it */
+ memcpy((*result)->bytecode, &opv, sizeof(opv));
+ if (value == BACKGROUND_COLOR_SET) {
+ memcpy(((uint8_t *) (*result)->bytecode) + sizeof(opv),
+ &colour, sizeof(colour));
+ }
return CSS_OK;
}
@@ -462,10 +545,54 @@ css_error parse_background_image(css_css21 *c,
const parserutils_vector *vector, int *ctx,
css_style **result)
{
- UNUSED(c);
- UNUSED(vector);
- UNUSED(ctx);
- UNUSED(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.ptr == c->strings[INHERIT]) {
+ flags |= FLAG_INHERIT;
+ } else if (token->type == CSS_TOKEN_IDENT &&
+ token->lower.ptr == 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 (value == BACKGROUND_IMAGE_URI)
+ required_size += sizeof(uint8_t *) + sizeof(size_t);
+
+ /* Allocate result */
+ *result = css_stylesheet_style_create(c->sheet, required_size);
+ if (*result == NULL)
+ return CSS_NOMEM;
+
+ /* Copy the bytecode to it */
+ memcpy((*result)->bytecode, &opv, sizeof(opv));
+ if (value == BACKGROUND_IMAGE_URI) {
+ memcpy((uint8_t *) (*result)->bytecode + sizeof(opv),
+ &token->data.ptr, sizeof(uint8_t *));
+ memcpy((uint8_t *) (*result)->bytecode + sizeof(opv) +
+ sizeof(uint8_t *),
+ &token->data.len, sizeof(size_t));
+ }
return CSS_OK;
}
@@ -474,6 +601,7 @@ 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);
@@ -486,10 +614,43 @@ css_error parse_background_repeat(css_css21 *c,
const parserutils_vector *vector, int *ctx,
css_style **result)
{
- UNUSED(c);
- UNUSED(vector);
- UNUSED(ctx);
- UNUSED(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.ptr == c->strings[INHERIT]) {
+ flags |= FLAG_INHERIT;
+ } else if (ident->lower.ptr == c->strings[NO_REPEAT]) {
+ value = BACKGROUND_REPEAT_NO_REPEAT;
+ } else if (ident->lower.ptr == c->strings[REPEAT_X]) {
+ value = BACKGROUND_REPEAT_REPEAT_X;
+ } else if (ident->lower.ptr == c->strings[REPEAT_Y]) {
+ value = BACKGROUND_REPEAT_REPEAT_Y;
+ } else if (ident->lower.ptr == c->strings[REPEAT]) {
+ value = BACKGROUND_REPEAT_REPEAT;
+ } else
+ return CSS_INVALID;
+
+ opv = buildOPV(OP_BACKGROUND_REPEAT, flags, value);
+
+ /* Allocate result */
+ *result = css_stylesheet_style_create(c->sheet, sizeof(opv));
+ if (*result == NULL)
+ return CSS_NOMEM;
+
+ /* Copy the bytecode to it */
+ memcpy((*result)->bytecode, &opv, sizeof(opv));
return CSS_OK;
}
@@ -690,7 +851,8 @@ css_error parse_clear(css_css21 *c,
const parserutils_vector *vector, int *ctx,
css_style **result)
{
- const css_token *token, *ident;
+ css_error error;
+ const css_token *ident;
uint8_t flags = 0;
uint16_t value = 0;
uint32_t opv;
@@ -700,41 +862,19 @@ css_error parse_clear(css_css21 *c,
if (ident == NULL || ident->type != CSS_TOKEN_IDENT)
return CSS_INVALID;
- /** \todo break this !important stuff into a utility function */
- consumeWhitespace(vector, ctx);
-
- token = parserutils_vector_iterate(vector, ctx);
- if (token != NULL && tokenIsChar(token, '!')) {
- consumeWhitespace(vector, ctx);
+ error = parse_important(c, vector, ctx, &flags);
+ if (error != CSS_OK)
+ return error;
- token = parserutils_vector_iterate(vector, ctx);
- if (token == NULL || token->type != CSS_TOKEN_IDENT)
- return CSS_INVALID;
-
- /** \todo compare pointer to interned version. */
- if (token->lower.len == 9 &&
- strncmp((char *) token->lower.ptr,
- "important", 9) == 0)
- flags |= FLAG_IMPORTANT;
- } else if (token != NULL)
- return CSS_INVALID;
-
-
- /** \todo ugh. compare pointers to interned versions, already */
- if (ident->lower.len == 7 &&
- strncmp((char *) ident->lower.ptr, "inherit", 7) == 0) {
+ if (ident->lower.ptr == c->strings[INHERIT]) {
flags |= FLAG_INHERIT;
- } else if (ident->lower.len == 5 &&
- strncmp((char *) ident->lower.ptr, "right", 5) == 0) {
+ } else if (ident->lower.ptr == c->strings[RIGHT]) {
value = CLEAR_RIGHT;
- } else if (ident->lower.len == 4 &&
- strncmp((char *) ident->lower.ptr, "left", 4) == 0) {
+ } else if (ident->lower.ptr == c->strings[LEFT]) {
value = CLEAR_LEFT;
- } else if (ident->lower.len == 4 &&
- strncmp((char *) ident->lower.ptr, "both", 4) == 0) {
+ } else if (ident->lower.ptr == c->strings[BOTH]) {
value = CLEAR_BOTH;
- } else if (ident->lower.len == 4 &&
- strncmp((char *) ident->lower.ptr, "none", 4) == 0) {
+ } else if (ident->lower.ptr == c->strings[NONE]) {
value = CLEAR_NONE;
} else
return CSS_INVALID;
@@ -1664,4 +1804,48 @@ css_error parse_z_index(css_css21 *c,
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.ptr == 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;
+}
+
#endif