summaryrefslogtreecommitdiff
path: root/src/parse
diff options
context:
space:
mode:
authorJohn Mark Bell <jmb@netsurf-browser.org>2009-06-25 18:24:26 +0000
committerJohn Mark Bell <jmb@netsurf-browser.org>2009-06-25 18:24:26 +0000
commitfc09dd686bd7b131f7ee743a392900bf3f741498 (patch)
tree34a285126260f7cf4ba3f5547485a4bbf79621a9 /src/parse
parent7782c74a03f19797fd5af2b015b80710c869616b (diff)
downloadlibcss-fc09dd686bd7b131f7ee743a392900bf3f741498.tar.gz
libcss-fc09dd686bd7b131f7ee743a392900bf3f741498.tar.bz2
Documentation and context restoration on error.
Make font-family parser use generic comma-separated list parser svn path=/trunk/libcss/; revision=7985
Diffstat (limited to 'src/parse')
-rw-r--r--src/parse/properties/font.c496
1 files changed, 196 insertions, 300 deletions
diff --git a/src/parse/properties/font.c b/src/parse/properties/font.c
index 17cac76..e964cba 100644
--- a/src/parse/properties/font.c
+++ b/src/parse/properties/font.c
@@ -12,10 +12,72 @@
#include "parse/properties/properties.h"
#include "parse/properties/utils.h"
+/**
+ * Determine if a given font-family ident is reserved
+ *
+ * \param c Parsing context
+ * \param ident IDENT to consider
+ * \return True if IDENT is reserved, false otherwise
+ */
+static bool font_family_reserved(css_language *c, const css_token *ident)
+{
+ return ident->ilower == c->strings[SERIF] ||
+ ident->ilower == c->strings[SANS_SERIF] ||
+ ident->ilower == c->strings[CURSIVE] ||
+ ident->ilower == c->strings[FANTASY] ||
+ ident->ilower == c->strings[MONOSPACE];
+}
+
+/**
+ * Convert a font-family token into a bytecode value
+ *
+ * \param c Parsing context
+ * \param token Token to consider
+ * \return Bytecode value
+ */
+static uint16_t font_family_value(css_language *c, const css_token *token)
+{
+ uint16_t value;
+
+ if (token->type == CSS_TOKEN_IDENT) {
+ if (token->ilower == c->strings[SERIF])
+ value = FONT_FAMILY_SERIF;
+ else if (token->ilower == c->strings[SANS_SERIF])
+ value = FONT_FAMILY_SANS_SERIF;
+ else if (token->ilower == c->strings[CURSIVE])
+ value = FONT_FAMILY_CURSIVE;
+ else if (token->ilower == c->strings[FANTASY])
+ value = FONT_FAMILY_FANTASY;
+ else if (token->ilower == c->strings[MONOSPACE])
+ value = FONT_FAMILY_MONOSPACE;
+ else
+ value = FONT_FAMILY_IDENT_LIST;
+ } else {
+ value = FONT_FAMILY_STRING;
+ }
+
+ return value;
+}
+
+/**
+ * Parse font-family
+ *
+ * \param c Parsing context
+ * \param vector Vector of tokens to process
+ * \param ctx Pointer to vector iteration context
+ * \param result Pointer to location to receive resulting style
+ * \return CSS_OK on success,
+ * CSS_NOMEM on memory exhaustion,
+ * CSS_INVALID if the input is not valid
+ *
+ * Post condition: \a *ctx is updated with the next token to process
+ * If the input is invalid, then \a *ctx remains unchanged.
+ */
css_error parse_font_family(css_language *c,
const parserutils_vector *vector, int *ctx,
css_style **result)
{
+ int orig_ctx = *ctx;
css_error error;
const css_token *token;
uint8_t flags = 0;
@@ -37,129 +99,37 @@ css_error parse_font_family(css_language *c,
/* Pass 1: validate input and calculate space */
token = parserutils_vector_iterate(vector, &temp_ctx);
if (token == NULL || (token->type != CSS_TOKEN_IDENT &&
- token->type != CSS_TOKEN_STRING))
+ token->type != CSS_TOKEN_STRING)) {
+ *ctx = orig_ctx;
return CSS_INVALID;
+ }
if (token->type == CSS_TOKEN_IDENT &&
token->ilower == c->strings[INHERIT]) {
flags = FLAG_INHERIT;
} else {
- bool first = true;
-
- while (token != NULL) {
- if (token->type == CSS_TOKEN_IDENT) {
- if (first == false) {
- required_size += sizeof(opv);
- }
-
- if (token->ilower == c->strings[SERIF]) {
- if (first) {
- value = FONT_FAMILY_SERIF;
- }
- } else if (token->ilower ==
- c->strings[SANS_SERIF]) {
- if (first) {
- value = FONT_FAMILY_SANS_SERIF;
- }
- } else if (token->ilower ==
- c->strings[CURSIVE]) {
- if (first) {
- value = FONT_FAMILY_CURSIVE;
- }
- } else if (token->ilower ==
- c->strings[FANTASY]) {
- if (first) {
- value = FONT_FAMILY_FANTASY;
- }
- } else if (token->ilower ==
- c->strings[MONOSPACE]) {
- if (first) {
- value = FONT_FAMILY_MONOSPACE;
- }
- } else {
- if (first) {
- value = FONT_FAMILY_IDENT_LIST;
- }
-
- required_size +=
- sizeof(lwc_string *);
-
- /* Skip past [ IDENT* S* ]* */
- while (token != NULL) {
- token = parserutils_vector_peek(
- vector,
- temp_ctx);
- if (token == NULL ||
- (token->type !=
- CSS_TOKEN_IDENT &&
- token->type !=
- CSS_TOKEN_S)) {
- break;
- }
-
- /* idents must not match
- * generic families */
- if (token->type == CSS_TOKEN_IDENT &&
- (token->ilower == c->strings[SERIF] ||
- token->ilower == c->strings[SANS_SERIF] ||
- token->ilower == c->strings[CURSIVE] ||
- token->ilower == c->strings[FANTASY] ||
- token->ilower == c->strings[MONOSPACE]))
- return CSS_INVALID;
- token = parserutils_vector_iterate(
- vector, &temp_ctx);
- }
- }
- } else if (token->type == CSS_TOKEN_STRING) {
- if (first == false) {
- required_size += sizeof(opv);
- } else {
- value = FONT_FAMILY_STRING;
- }
-
- required_size +=
- sizeof(lwc_string *);
- } else {
- return CSS_INVALID;
- }
-
- consumeWhitespace(vector, &temp_ctx);
-
- token = parserutils_vector_peek(vector, temp_ctx);
- if (token != NULL && tokenIsChar(token, ',') == false &&
- tokenIsChar(token, '!') == false) {
- return CSS_INVALID;
- }
-
- if (token != NULL && tokenIsChar(token, ',')) {
- parserutils_vector_iterate(vector, &temp_ctx);
-
- consumeWhitespace(vector, &temp_ctx);
-
- token = parserutils_vector_peek(vector,
- temp_ctx);
- if (token == NULL || tokenIsChar(token, '!'))
- return CSS_INVALID;
- }
-
- first = false;
-
- token = parserutils_vector_peek(vector, temp_ctx);
- if (token != NULL && tokenIsChar(token, '!'))
- break;
-
- token = parserutils_vector_iterate(vector, &temp_ctx);
+ uint32_t list_size;
+
+ value = font_family_value(c, token);
+
+ error = comma_list_length(c, vector, &temp_ctx,
+ token, font_family_reserved, &list_size);
+ if (error != CSS_OK) {
+ *ctx = orig_ctx;
+ return error;
}
- required_size += sizeof(opv);
+ required_size += list_size;
}
opv = buildOPV(CSS_PROP_FONT_FAMILY, flags, value);
/* Allocate result */
error = css_stylesheet_style_create(c->sheet, required_size, result);
- if (error != CSS_OK)
+ if (error != CSS_OK) {
+ *ctx = orig_ctx;
return error;
+ }
/* Copy OPV to bytecode */
ptr = (*result)->bytecode;
@@ -172,6 +142,7 @@ css_error parse_font_family(css_language *c,
token->type != CSS_TOKEN_STRING)) {
css_stylesheet_style_destroy(c->sheet, *result);
*result = NULL;
+ *ctx = orig_ctx;
return CSS_INVALID;
}
@@ -179,181 +150,14 @@ css_error parse_font_family(css_language *c,
token->ilower == c->strings[INHERIT]) {
/* Nothing to do */
} else {
- bool first = true;
-
- while (token != NULL) {
- if (token->type == CSS_TOKEN_IDENT) {
- lwc_string *tok_idata = token->idata;
- lwc_string *name = tok_idata;
- lwc_string *newname;
-
- if (token->ilower == c->strings[SERIF]) {
- opv = FONT_FAMILY_SERIF;
- } else if (token->ilower ==
- c->strings[SANS_SERIF]) {
- opv = FONT_FAMILY_SANS_SERIF;
- } else if (token->ilower ==
- c->strings[CURSIVE]) {
- opv = FONT_FAMILY_CURSIVE;
- } else if (token->ilower ==
- c->strings[FANTASY]) {
- opv = FONT_FAMILY_FANTASY;
- } else if (token->ilower ==
- c->strings[MONOSPACE]) {
- opv = FONT_FAMILY_MONOSPACE;
- } else {
- uint16_t len = lwc_string_length(token->idata);
- const css_token *temp_token = token;
- lwc_error lerror;
- uint8_t *buf;
- uint8_t *p;
-
- temp_ctx = *ctx;
-
- opv = FONT_FAMILY_IDENT_LIST;
-
- /* Build string from idents */
- while (temp_token != NULL) {
- temp_token = parserutils_vector_peek(
- vector, temp_ctx);
- if (temp_token == NULL ||
- (temp_token->type !=
- CSS_TOKEN_IDENT &&
- temp_token->type !=
- CSS_TOKEN_S)) {
- break;
- }
-
- if (temp_token->type ==
- CSS_TOKEN_IDENT) {
- len += lwc_string_length(temp_token->idata);
- } else {
- len += 1;
- }
-
- temp_token = parserutils_vector_iterate(
- vector, &temp_ctx);
- }
-
- /** \todo Don't use alloca */
- buf = alloca(len);
- p = buf;
-
- memcpy(p, lwc_string_data(token->idata), lwc_string_length(token->idata));
- p += lwc_string_length(token->idata);
-
- while (token != NULL) {
- token = parserutils_vector_peek(
- vector, *ctx);
- if (token == NULL ||
- (token->type !=
- CSS_TOKEN_IDENT &&
- token->type !=
- CSS_TOKEN_S)) {
- break;
- }
-
- if (token->type ==
- CSS_TOKEN_IDENT) {
- memcpy(p,
- lwc_string_data(token->idata),
- lwc_string_length(token->idata));
- p += lwc_string_length(token->idata);
- } else {
- *p++ = ' ';
- }
-
- token = parserutils_vector_iterate(
- vector, ctx);
- }
-
- /* Strip trailing whitespace */
- while (p > buf && p[-1] == ' ')
- p--;
-
- /* Insert into hash, if it's different
- * from the name we already have */
-
- lerror = lwc_context_intern(c->sheet->dictionary,
- (char *)buf, len, &newname);
- if (lerror != lwc_error_ok) {
- css_stylesheet_style_destroy(c->sheet, *result);
- *result = NULL;
- return css_error_from_lwc_error(lerror);
- }
-
- if (newname == name)
- lwc_context_string_unref(c->sheet->dictionary,
- newname);
-
- name = newname;
-
- }
-
- if (first == false) {
- memcpy(ptr, &opv, sizeof(opv));
- ptr += sizeof(opv);
- }
-
- if (opv == FONT_FAMILY_IDENT_LIST) {
- /* Only ref 'name' again if the token owns it,
- * otherwise we already own the only ref to the
- * new name generated above.
- */
- if (name == tok_idata)
- lwc_context_string_ref(c->sheet->dictionary, name);
- memcpy(ptr, &name, sizeof(name));
- ptr += sizeof(name);
- }
- } else if (token->type == CSS_TOKEN_STRING) {
- opv = FONT_FAMILY_STRING;
-
- if (first == false) {
- memcpy(ptr, &opv, sizeof(opv));
- ptr += sizeof(opv);
- }
-
- lwc_context_string_ref(c->sheet->dictionary, token->idata);
- memcpy(ptr, &token->idata,
- sizeof(token->idata));
- ptr += sizeof(token->idata);
- } else {
- css_stylesheet_style_destroy(c->sheet, *result);
- *result = NULL;
- return CSS_INVALID;
- }
-
- consumeWhitespace(vector, ctx);
-
- token = parserutils_vector_peek(vector, *ctx);
- if (token != NULL && tokenIsChar(token, ',') == false &&
- tokenIsChar(token, '!') == false) {
- css_stylesheet_style_destroy(c->sheet, *result);
- *result = NULL;
- return CSS_INVALID;
- }
-
- if (token != NULL && tokenIsChar(token, ',')) {
- parserutils_vector_iterate(vector, ctx);
-
- consumeWhitespace(vector, ctx);
-
- token = parserutils_vector_peek(vector, *ctx);
- if (token == NULL || tokenIsChar(token, '!')) {
- css_stylesheet_style_destroy(c->sheet,
- *result);
- *result = NULL;
- return CSS_INVALID;
- }
- }
-
- first = false;
-
- token = parserutils_vector_peek(vector, *ctx);
- if (token != NULL && tokenIsChar(token, '!'))
- break;
-
- token = parserutils_vector_iterate(vector, ctx);
+ error = comma_list_to_bytecode(c, vector, ctx, token,
+ font_family_reserved, font_family_value,
+ &ptr);
+ if (error != CSS_OK) {
+ css_stylesheet_style_destroy(c->sheet, *result);
+ *result = NULL;
+ *ctx = orig_ctx;
+ return error;
}
/* Write terminator */
@@ -365,10 +169,25 @@ css_error parse_font_family(css_language *c,
return CSS_OK;
}
+/**
+ * Parse font-size
+ *
+ * \param c Parsing context
+ * \param vector Vector of tokens to process
+ * \param ctx Pointer to vector iteration context
+ * \param result Pointer to location to receive resulting style
+ * \return CSS_OK on success,
+ * CSS_NOMEM on memory exhaustion,
+ * CSS_INVALID if the input is not valid
+ *
+ * Post condition: \a *ctx is updated with the next token to process
+ * If the input is invalid, then \a *ctx remains unchanged.
+ */
css_error parse_font_size(css_language *c,
const parserutils_vector *vector, int *ctx,
css_style **result)
{
+ int orig_ctx = *ctx;
css_error error;
const css_token *token;
uint8_t flags = 0;
@@ -381,8 +200,10 @@ css_error parse_font_size(css_language *c,
/* 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)
+ if (token == NULL) {
+ *ctx = orig_ctx;
return CSS_INVALID;
+ }
if (token->type == CSS_TOKEN_IDENT &&
token->ilower == c->strings[INHERIT]) {
@@ -427,15 +248,21 @@ css_error parse_font_size(css_language *c,
} else {
error = parse_unit_specifier(c, vector, ctx, UNIT_PX,
&length, &unit);
- if (error != CSS_OK)
+ if (error != CSS_OK) {
+ *ctx = orig_ctx;
return error;
+ }
- if (unit & UNIT_ANGLE || unit & UNIT_TIME || unit & UNIT_FREQ)
+ if (unit & UNIT_ANGLE || unit & UNIT_TIME || unit & UNIT_FREQ) {
+ *ctx = orig_ctx;
return CSS_INVALID;
+ }
/* Negative values are not permitted */
- if (length < 0)
+ if (length < 0) {
+ *ctx = orig_ctx;
return CSS_INVALID;
+ }
value = FONT_SIZE_DIMENSION;
}
@@ -448,8 +275,10 @@ css_error parse_font_size(css_language *c,
/* Allocate result */
error = css_stylesheet_style_create(c->sheet, required_size, result);
- if (error != CSS_OK)
+ if (error != CSS_OK) {
+ *ctx = orig_ctx;
return error;
+ }
/* Copy the bytecode to it */
memcpy((*result)->bytecode, &opv, sizeof(opv));
@@ -463,10 +292,25 @@ css_error parse_font_size(css_language *c,
return CSS_OK;
}
+/**
+ * Parse font-style
+ *
+ * \param c Parsing context
+ * \param vector Vector of tokens to process
+ * \param ctx Pointer to vector iteration context
+ * \param result Pointer to location to receive resulting style
+ * \return CSS_OK on success,
+ * CSS_NOMEM on memory exhaustion,
+ * CSS_INVALID if the input is not valid
+ *
+ * Post condition: \a *ctx is updated with the next token to process
+ * If the input is invalid, then \a *ctx remains unchanged.
+ */
css_error parse_font_style(css_language *c,
const parserutils_vector *vector, int *ctx,
css_style **result)
{
+ int orig_ctx = *ctx;
css_error error;
const css_token *ident;
uint8_t flags = 0;
@@ -475,8 +319,10 @@ css_error parse_font_style(css_language *c,
/* IDENT (normal, italic, oblique, inherit) */
ident = parserutils_vector_iterate(vector, ctx);
- if (ident == NULL || ident->type != CSS_TOKEN_IDENT)
+ if (ident == NULL || ident->type != CSS_TOKEN_IDENT) {
+ *ctx = orig_ctx;
return CSS_INVALID;
+ }
if (ident->ilower == c->strings[INHERIT]) {
flags |= FLAG_INHERIT;
@@ -486,15 +332,19 @@ css_error parse_font_style(css_language *c,
value = FONT_STYLE_ITALIC;
} else if (ident->ilower == c->strings[OBLIQUE]) {
value = FONT_STYLE_OBLIQUE;
- } else
+ } else {
+ *ctx = orig_ctx;
return CSS_INVALID;
+ }
opv = buildOPV(CSS_PROP_FONT_STYLE, flags, value);
/* Allocate result */
error = css_stylesheet_style_create(c->sheet, sizeof(opv), result);
- if (error != CSS_OK)
+ if (error != CSS_OK) {
+ *ctx = orig_ctx;
return error;
+ }
/* Copy the bytecode to it */
memcpy((*result)->bytecode, &opv, sizeof(opv));
@@ -502,10 +352,25 @@ css_error parse_font_style(css_language *c,
return CSS_OK;
}
+/**
+ * Parse font-variant
+ *
+ * \param c Parsing context
+ * \param vector Vector of tokens to process
+ * \param ctx Pointer to vector iteration context
+ * \param result Pointer to location to receive resulting style
+ * \return CSS_OK on success,
+ * CSS_NOMEM on memory exhaustion,
+ * CSS_INVALID if the input is not valid
+ *
+ * Post condition: \a *ctx is updated with the next token to process
+ * If the input is invalid, then \a *ctx remains unchanged.
+ */
css_error parse_font_variant(css_language *c,
const parserutils_vector *vector, int *ctx,
css_style **result)
{
+ int orig_ctx = *ctx;
css_error error;
const css_token *ident;
uint8_t flags = 0;
@@ -514,8 +379,10 @@ css_error parse_font_variant(css_language *c,
/* IDENT (normal, small-caps, inherit) */
ident = parserutils_vector_iterate(vector, ctx);
- if (ident == NULL || ident->type != CSS_TOKEN_IDENT)
+ if (ident == NULL || ident->type != CSS_TOKEN_IDENT) {
+ *ctx = orig_ctx;
return CSS_INVALID;
+ }
if (ident->ilower == c->strings[INHERIT]) {
flags |= FLAG_INHERIT;
@@ -523,15 +390,19 @@ css_error parse_font_variant(css_language *c,
value = FONT_VARIANT_NORMAL;
} else if (ident->ilower == c->strings[SMALL_CAPS]) {
value = FONT_VARIANT_SMALL_CAPS;
- } else
+ } else {
+ *ctx = orig_ctx;
return CSS_INVALID;
+ }
opv = buildOPV(CSS_PROP_FONT_VARIANT, flags, value);
/* Allocate result */
error = css_stylesheet_style_create(c->sheet, sizeof(opv), result);
- if (error != CSS_OK)
+ if (error != CSS_OK) {
+ *ctx = orig_ctx;
return error;
+ }
/* Copy the bytecode to it */
memcpy((*result)->bytecode, &opv, sizeof(opv));
@@ -539,10 +410,25 @@ css_error parse_font_variant(css_language *c,
return CSS_OK;
}
+/**
+ * Parse font-weight
+ *
+ * \param c Parsing context
+ * \param vector Vector of tokens to process
+ * \param ctx Pointer to vector iteration context
+ * \param result Pointer to location to receive resulting style
+ * \return CSS_OK on success,
+ * CSS_NOMEM on memory exhaustion,
+ * CSS_INVALID if the input is not valid
+ *
+ * Post condition: \a *ctx is updated with the next token to process
+ * If the input is invalid, then \a *ctx remains unchanged.
+ */
css_error parse_font_weight(css_language *c,
const parserutils_vector *vector, int *ctx,
css_style **result)
{
+ int orig_ctx = *ctx;
css_error error;
const css_token *token;
uint8_t flags = 0;
@@ -553,17 +439,23 @@ css_error parse_font_weight(css_language *c,
* 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))
+ token->type != CSS_TOKEN_NUMBER)) {
+ *ctx = orig_ctx;
return CSS_INVALID;
+ }
if (token->ilower == c->strings[INHERIT]) {
flags |= FLAG_INHERIT;
} else if (token->type == CSS_TOKEN_NUMBER) {
size_t consumed = 0;
- css_fixed num = number_from_lwc_string(token->ilower, true, &consumed);
+ css_fixed num = number_from_lwc_string(token->ilower,
+ true, &consumed);
/* Invalid if there are trailing characters */
- if (consumed != lwc_string_length(token->ilower))
+ if (consumed != lwc_string_length(token->ilower)) {
+ *ctx = orig_ctx;
return CSS_INVALID;
+ }
+
switch (FIXTOINT(num)) {
case 100: value = FONT_WEIGHT_100; break;
case 200: value = FONT_WEIGHT_200; break;
@@ -574,7 +466,7 @@ css_error parse_font_weight(css_language *c,
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;
+ default: *ctx = orig_ctx; return CSS_INVALID;
}
} else if (token->ilower == c->strings[NORMAL]) {
value = FONT_WEIGHT_NORMAL;
@@ -584,15 +476,19 @@ css_error parse_font_weight(css_language *c,
value = FONT_WEIGHT_BOLDER;
} else if (token->ilower == c->strings[LIGHTER]) {
value = FONT_WEIGHT_LIGHTER;
- } else
+ } else {
+ *ctx = orig_ctx;
return CSS_INVALID;
+ }
opv = buildOPV(CSS_PROP_FONT_WEIGHT, flags, value);
/* Allocate result */
error = css_stylesheet_style_create(c->sheet, sizeof(opv), result);
- if (error != CSS_OK)
+ if (error != CSS_OK) {
+ *ctx = orig_ctx;
return error;
+ }
/* Copy the bytecode to it */
memcpy((*result)->bytecode, &opv, sizeof(opv));