summaryrefslogtreecommitdiff
path: root/src/parse/properties/content.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/parse/properties/content.c')
-rw-r--r--src/parse/properties/content.c457
1 files changed, 374 insertions, 83 deletions
diff --git a/src/parse/properties/content.c b/src/parse/properties/content.c
index 7f37400..9a3a425 100644
--- a/src/parse/properties/content.c
+++ b/src/parse/properties/content.c
@@ -13,6 +13,7 @@
#include "parse/properties/properties.h"
#include "parse/properties/utils.h"
+
/**
* Parse content
*
@@ -27,108 +28,398 @@
* 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_content(css_language *c,
- const parserutils_vector *vector, int *ctx,
- css_style **result)
+css_error parse_content(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;
- uint16_t value = 0;
- uint32_t opv;
- uint32_t required_size = sizeof(opv);
- int temp_ctx = *ctx;
- uint8_t *ptr;
bool match;
- /* IDENT(normal, none, inherit) |
- * [
- * IDENT(open-quote, close-quote, no-open-quote, no-close-quote) |
- * STRING | URI |
- * FUNCTION(attr) IDENT ')' |
- * FUNCTION(counter) IDENT IDENT? ')' |
- * FUNCTION(counters) IDENT STRING IDENT? ')'
- * ]+
- */
-
- /* Pass 1: Calculate required size & validate input */
- token = parserutils_vector_peek(vector, temp_ctx);
+ /* IDENT(normal, none, inherit) | [ ... ]+ */
+ token = parserutils_vector_iterate(vector, ctx);
if (token == NULL) {
*ctx = orig_ctx;
return CSS_INVALID;
}
- if (token->type == CSS_TOKEN_IDENT &&
- (lwc_string_caseless_isequal(
- token->idata, c->strings[INHERIT],
- &match) == lwc_error_ok && match)) {
- flags = FLAG_INHERIT;
- parserutils_vector_iterate(vector, &temp_ctx);
- } else if (token->type == CSS_TOKEN_IDENT &&
- (lwc_string_caseless_isequal(
- token->idata, c->strings[NORMAL],
- &match) == lwc_error_ok && match)) {
- value = CONTENT_NORMAL;
- parserutils_vector_iterate(vector, &temp_ctx);
- } else if (token->type == CSS_TOKEN_IDENT &&
- (lwc_string_caseless_isequal(
- token->idata, c->strings[NONE],
- &match) == lwc_error_ok && match)) {
- value = CONTENT_NONE;
- parserutils_vector_iterate(vector, &temp_ctx);
+
+ if ((token->type == CSS_TOKEN_IDENT) &&
+ (lwc_string_caseless_isequal(token->idata,
+ c->strings[INHERIT],
+ &match) == lwc_error_ok && match)) {
+ error = css_stylesheet_style_inherit(result, CSS_PROP_CONTENT);
+ } else if ((token->type == CSS_TOKEN_IDENT) &&
+ (lwc_string_caseless_isequal(token->idata,
+ c->strings[NORMAL],
+ &match) == lwc_error_ok && match)) {
+ error = css_stylesheet_style_appendOPV(result, CSS_PROP_CONTENT, 0, CONTENT_NORMAL);
+ } else if ((token->type == CSS_TOKEN_IDENT) &&
+ (lwc_string_caseless_isequal(token->idata,
+ c->strings[NONE],
+ &match) == lwc_error_ok && match)) {
+ error = css_stylesheet_style_appendOPV(result, CSS_PROP_CONTENT, 0, CONTENT_NONE);
} else {
- uint32_t len;
- error = parse_content_list(c, vector, &temp_ctx, &value,
- NULL, &len);
- if (error != CSS_OK) {
- *ctx = orig_ctx;
- return error;
- }
+/* Macro to output the value marker, awkward because we need to check
+ * first to determine how the value is constructed.
+ */
+#define CSS_APPEND(CSSVAL) css_stylesheet_style_append(result, first?buildOPV(CSS_PROP_CONTENT, 0, CSSVAL):CSSVAL)
- required_size += len;
- }
+ bool first = true;
+ int prev_ctx = orig_ctx;
- opv = buildOPV(CSS_PROP_CONTENT, flags, value);
+ /* [
+ * IDENT(open-quote, close-quote, no-open-quote,
+ * no-close-quote) |
+ * STRING |
+ * URI |
+ * FUNCTION(attr) IDENT ')' |
+ * FUNCTION(counter) IDENT IDENT? ')' |
+ * FUNCTION(counters) IDENT STRING IDENT? ')'
+ * ]+
+ */
- /* Allocate result */
- error = css_stylesheet_style_create(c->sheet, required_size, result);
- if (error != CSS_OK) {
- *ctx = orig_ctx;
- return error;
- }
+ while (token != NULL) {
+ if ((token->type == CSS_TOKEN_IDENT) &&
+ (lwc_string_caseless_isequal(
+ token->idata, c->strings[OPEN_QUOTE],
+ &match) == lwc_error_ok && match)) {
- /* Copy OPV to bytecode */
- ptr = (*result)->bytecode;
- memcpy(ptr, &opv, sizeof(opv));
- ptr += sizeof(opv);
+ error = CSS_APPEND(CONTENT_OPEN_QUOTE);
- /* Pass 2: construct bytecode */
- token = parserutils_vector_peek(vector, *ctx);
- if (token == NULL) {
- *ctx = orig_ctx;
- return CSS_INVALID;
- }
+ } else if (token->type == CSS_TOKEN_IDENT &&
+ (lwc_string_caseless_isequal(
+ token->idata, c->strings[CLOSE_QUOTE],
+ &match) == lwc_error_ok && match)) {
- if (token->type == CSS_TOKEN_IDENT &&
- ((lwc_string_caseless_isequal(
- token->idata, c->strings[INHERIT],
- &match) == lwc_error_ok && match) ||
- (lwc_string_caseless_isequal(
- token->idata, c->strings[NORMAL],
- &match) == lwc_error_ok && match) ||
- (lwc_string_caseless_isequal(
- token->idata, c->strings[NONE],
- &match) == lwc_error_ok && match))) {
- parserutils_vector_iterate(vector, ctx);
- } else {
- error = parse_content_list(c, vector, ctx, NULL, ptr, NULL);
- if (error != CSS_OK) {
- *ctx = orig_ctx;
- return error;
- }
+ error = CSS_APPEND(CONTENT_CLOSE_QUOTE);
+ } else if (token->type == CSS_TOKEN_IDENT &&
+ (lwc_string_caseless_isequal(
+ token->idata, c->strings[NO_OPEN_QUOTE],
+ &match) == lwc_error_ok && match)) {
+ error = CSS_APPEND(CONTENT_NO_OPEN_QUOTE);
+ } else if (token->type == CSS_TOKEN_IDENT &&
+ (lwc_string_caseless_isequal(
+ token->idata, c->strings[NO_CLOSE_QUOTE],
+ &match) == lwc_error_ok && match)) {
+ error = CSS_APPEND(CONTENT_NO_CLOSE_QUOTE);
+ } else if (token->type == CSS_TOKEN_STRING) {
+ uint32_t snumber;
+
+ error = css_stylesheet_string_add(c->sheet, lwc_string_ref(token->idata), &snumber);
+ if (error != CSS_OK) {
+ *ctx = orig_ctx;
+ return error;
+ }
+
+ error = CSS_APPEND(CONTENT_STRING);
+ if (error != CSS_OK) {
+ *ctx = orig_ctx;
+ return error;
+ }
+
+ error = css_stylesheet_style_append(result, snumber);
+ } else if (token->type == CSS_TOKEN_URI) {
+ lwc_string *uri;
+ uint32_t uri_snumber;
+
+ error = c->sheet->resolve(c->sheet->resolve_pw,
+ c->sheet->url,
+ token->idata,
+ &uri);
+ if (error != CSS_OK) {
+ *ctx = orig_ctx;
+ return error;
+ }
+
+ error = css_stylesheet_string_add(c->sheet,
+ uri,
+ &uri_snumber);
+ if (error != CSS_OK) {
+ *ctx = orig_ctx;
+ return error;
+ }
+
+ error = CSS_APPEND(CONTENT_URI);
+ if (error != CSS_OK) {
+ *ctx = orig_ctx;
+ return error;
+ }
+
+ error = css_stylesheet_style_append(result, uri_snumber);
+ } else if (token->type == CSS_TOKEN_FUNCTION &&
+ (lwc_string_caseless_isequal(
+ token->idata, c->strings[ATTR],
+ &match) == lwc_error_ok && match)) {
+ uint32_t snumber;
+
+ consumeWhitespace(vector, ctx);
+
+ /* Expect IDENT */
+ token = parserutils_vector_iterate(vector, ctx);
+ if (token == NULL || token->type != CSS_TOKEN_IDENT) {
+ *ctx = orig_ctx;
+ return CSS_INVALID;
+ }
+
+ error = css_stylesheet_string_add(c->sheet, lwc_string_ref(token->idata), &snumber);
+ if (error != CSS_OK) {
+ *ctx = orig_ctx;
+ return error;
+ }
+
+ error = CSS_APPEND(CONTENT_ATTR);
+ if (error != CSS_OK) {
+ *ctx = orig_ctx;
+ return error;
+ }
+
+ error = css_stylesheet_style_append(result, snumber);
+
+ consumeWhitespace(vector, ctx);
+
+ /* Expect ')' */
+ token = parserutils_vector_iterate(vector, ctx);
+ if (token == NULL || tokenIsChar(token, ')') == false) {
+ *ctx = orig_ctx;
+ return CSS_INVALID;
+ }
+ } else if (token->type == CSS_TOKEN_FUNCTION &&
+ (lwc_string_caseless_isequal(
+ token->idata, c->strings[COUNTER],
+ &match) == lwc_error_ok && match)) {
+ lwc_string *name;
+ uint32_t snumber;
+ uint32_t opv;
+
+ opv = CONTENT_COUNTER;
+
+ consumeWhitespace(vector, ctx);
+
+ /* Expect IDENT */
+ token = parserutils_vector_iterate(vector, ctx);
+ if (token == NULL || token->type != CSS_TOKEN_IDENT) {
+ *ctx = orig_ctx;
+ return CSS_INVALID;
+ }
+
+ name = token->idata;
+
+ consumeWhitespace(vector, ctx);
+
+ /* Possible ',' */
+ token = parserutils_vector_peek(vector, *ctx);
+ if (token == NULL ||
+ (tokenIsChar(token, ',') == false &&
+ tokenIsChar(token, ')') == false)) {
+ *ctx = orig_ctx;
+ return CSS_INVALID;
+ }
+
+ if (tokenIsChar(token, ',')) {
+ uint16_t v;
+
+ parserutils_vector_iterate(vector, ctx);
+
+ consumeWhitespace(vector, ctx);
+
+ /* Expect IDENT */
+ token = parserutils_vector_peek(vector, *ctx);
+ if (token == NULL || token->type !=
+ CSS_TOKEN_IDENT) {
+ *ctx = orig_ctx;
+ return CSS_INVALID;
+ }
+
+ error = parse_list_style_type_value(c, token, &v);
+ if (error != CSS_OK) {
+ *ctx = orig_ctx;
+ return error;
+ }
+
+ opv |= v << CONTENT_COUNTER_STYLE_SHIFT;
+
+ parserutils_vector_iterate(vector, ctx);
+
+ consumeWhitespace(vector, ctx);
+ } else {
+ opv |= LIST_STYLE_TYPE_DECIMAL <<
+ CONTENT_COUNTER_STYLE_SHIFT;
+ }
+
+ /* Expect ')' */
+ token = parserutils_vector_iterate(vector, ctx);
+ if (token == NULL || tokenIsChar(token, ')') == false) {
+ *ctx = orig_ctx;
+ return CSS_INVALID;
+ }
+
+
+ error = css_stylesheet_string_add(c->sheet, lwc_string_ref(name), &snumber);
+ if (error != CSS_OK) {
+ *ctx = orig_ctx;
+ return error;
+ }
+
+ error = CSS_APPEND(opv);
+ if (error != CSS_OK) {
+ *ctx = orig_ctx;
+ return error;
+ }
+
+ error = css_stylesheet_style_append(result, snumber);
+ } else if (token->type == CSS_TOKEN_FUNCTION &&
+ (lwc_string_caseless_isequal(
+ token->idata, c->strings[COUNTERS],
+ &match) == lwc_error_ok && match)) {
+ lwc_string *name;
+ lwc_string *sep;
+ uint32_t name_snumber;
+ uint32_t sep_snumber;
+ uint32_t opv;
+
+ opv = CONTENT_COUNTERS;
+
+ consumeWhitespace(vector, ctx);
+
+ /* Expect IDENT */
+ token = parserutils_vector_iterate(vector, ctx);
+ if (token == NULL || token->type != CSS_TOKEN_IDENT) {
+ *ctx = orig_ctx;
+ return CSS_INVALID;
+ }
+
+ name = token->idata;
+
+ consumeWhitespace(vector, ctx);
+
+ /* Expect ',' */
+ token = parserutils_vector_iterate(vector, ctx);
+ if (token == NULL || tokenIsChar(token, ',') == false) {
+ *ctx = orig_ctx;
+ return CSS_INVALID;
+ }
+
+ consumeWhitespace(vector, ctx);
+
+ /* Expect STRING */
+ token = parserutils_vector_iterate(vector, ctx);
+ if (token == NULL || token->type != CSS_TOKEN_STRING) {
+ *ctx = orig_ctx;
+ return CSS_INVALID;
+ }
+
+ sep = token->idata;
+
+ consumeWhitespace(vector, ctx);
+
+ /* Possible ',' */
+ token = parserutils_vector_peek(vector, *ctx);
+ if (token == NULL ||
+ (tokenIsChar(token, ',') == false &&
+ tokenIsChar(token, ')') == false)) {
+ *ctx = orig_ctx;
+ return CSS_INVALID;
+ }
+
+ if (tokenIsChar(token, ',')) {
+ uint16_t v;
+
+ parserutils_vector_iterate(vector, ctx);
+
+ consumeWhitespace(vector, ctx);
+
+ /* Expect IDENT */
+ token = parserutils_vector_peek(vector, *ctx);
+ if (token == NULL || token->type !=
+ CSS_TOKEN_IDENT) {
+ *ctx = orig_ctx;
+ return CSS_INVALID;
+ }
+
+ error = parse_list_style_type_value(c,
+ token, &v);
+ if (error != CSS_OK) {
+ *ctx = orig_ctx;
+ return error;
+ }
+
+ opv |= v << CONTENT_COUNTERS_STYLE_SHIFT;
+
+ parserutils_vector_iterate(vector, ctx);
+
+ consumeWhitespace(vector, ctx);
+ } else {
+ opv |= LIST_STYLE_TYPE_DECIMAL <<
+ CONTENT_COUNTERS_STYLE_SHIFT;
+ }
+
+ /* Expect ')' */
+ token = parserutils_vector_iterate(vector, ctx);
+ if (token == NULL || tokenIsChar(token, ')') == false) {
+ *ctx = orig_ctx;
+ return CSS_INVALID;
+ }
+
+
+ error = css_stylesheet_string_add(c->sheet, lwc_string_ref(name), &name_snumber);
+ if (error != CSS_OK) {
+ *ctx = orig_ctx;
+ return error;
+ }
+
+ error = css_stylesheet_string_add(c->sheet, lwc_string_ref(sep), &sep_snumber);
+ if (error != CSS_OK) {
+ *ctx = orig_ctx;
+ return error;
+ }
+
+ error = CSS_APPEND(opv);
+ if (error != CSS_OK) {
+ *ctx = orig_ctx;
+ return error;
+ }
+
+ error = css_stylesheet_style_append(result, name_snumber);
+ if (error != CSS_OK) {
+ *ctx = orig_ctx;
+ return error;
+ }
+
+ error = css_stylesheet_style_append(result, sep_snumber);
+ } else if (first) {
+ /* Invalid if this is the first iteration */
+ error = CSS_INVALID;
+ } else {
+ /* Give up, ensuring current token is reprocessed */
+ *ctx = prev_ctx;
+ error = CSS_OK;
+ break;
+ }
+
+ /* if there was an error bail */
+ if (error != CSS_OK) {
+ *ctx = orig_ctx;
+ return error;
+ }
+
+ first = false;
+
+ consumeWhitespace(vector, ctx);
+
+ prev_ctx = *ctx;
+ token = parserutils_vector_iterate(vector, ctx);
+ } /* while */
+
+ /* Write list terminator */
+ css_stylesheet_style_append(result, CONTENT_NORMAL);
}
- return CSS_OK;
+ if (error != CSS_OK)
+ *ctx = orig_ctx;
+
+ return error;
}
+