summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/Bytecode22
-rw-r--r--src/bytecode/opcodes.h6
-rw-r--r--src/parse/properties.c259
-rw-r--r--src/parse/propstrings.h10
4 files changed, 285 insertions, 12 deletions
diff --git a/docs/Bytecode b/docs/Bytecode
index 37a1a27..dfa5712 100644
--- a/docs/Bytecode
+++ b/docs/Bytecode
@@ -314,13 +314,18 @@ Opcodes
10 - content
<value> (14bits) :
- bits 8-13: MBZ
+ bits 8-13: MBZ (except counter & counters, see below)
bits 0-7 :
bit 7 set => string follows
bits 0-6: 0000000 => string,
0000001 => uri,
0000010 => counter,
- 0000011 => attr,
+ bits 12-13: MBZ
+ bits 8-11 : list-style-type
+ 0000011 => counters,
+ bits 12-13: MBZ
+ bits 8-11 : list-style-type
+ 0000100 => attr,
other => rffe.
bit 7 clear => keywords:
bits 0-6: 0000000 => normal,
@@ -338,11 +343,18 @@ Opcodes
For example,
content: open-quote url('http://example.com/')
- " : " attr(name) close-quote;"
+ " : " attr(name) " " counter(x) "." counters(y, ".")
+ close-quote;"
would result in the following bytecode:
- <00080010> <00000081> <00000013> "http://example.com/" <00>
- <00000080> <00000003> " : " <00> <00000083> <00000004> "name"
+ <00080010>
+ <00000081> <ptr to "http://example.com">
+ <00000080> <ptr to " : ">
+ <00000084> <ptr to "name">
+ <00000080> <ptr to " ">
+ <00000382> <ptr to "x">
+ <00000080> <ptr to ".">
+ <00000383> <ptr to "y"> <ptr to ".">
<00000003> <00000000>
11 - counter-increment
diff --git a/src/bytecode/opcodes.h b/src/bytecode/opcodes.h
index 330489e..790b93b 100644
--- a/src/bytecode/opcodes.h
+++ b/src/bytecode/opcodes.h
@@ -140,7 +140,11 @@ enum op_content {
CONTENT_STRING = 0x0080,
CONTENT_URI = 0x0081,
CONTENT_COUNTER = 0x0082,
- CONTENT_ATTR = 0x0083,
+ CONTENT_COUNTERS = 0x0083,
+ CONTENT_ATTR = 0x0084,
+
+ CONTENT_COUNTER_STYLE_SHIFT = 8,
+ CONTENT_COUNTERS_STYLE_SHIFT = 8,
CONTENT_NORMAL = 0x0000,
CONTENT_NONE = 0x0001,
diff --git a/src/parse/properties.c b/src/parse/properties.c
index 9f6e69a..9b27408 100644
--- a/src/parse/properties.c
+++ b/src/parse/properties.c
@@ -1489,11 +1489,260 @@ 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);
+ 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;
+
+ /* 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);
+ if (token == NULL)
+ return CSS_INVALID;
+
+ if (token->type == CSS_TOKEN_IDENT &&
+ token->ilower == c->strings[INHERIT]) {
+ flags = FLAG_INHERIT;
+ } else if (token->type == CSS_TOKEN_IDENT &&
+ token->ilower == c->strings[NORMAL]) {
+ value = CONTENT_NORMAL;
+ } else if (token->type == CSS_TOKEN_IDENT &&
+ token->ilower == c->strings[NONE]) {
+ value = CONTENT_NONE;
+ } else {
+ bool done_value = false;
+
+ while (token != NULL && tokenIsChar(token, '!') == false) {
+ if (token->type == CSS_TOKEN_IDENT &&
+ token->ilower ==
+ c->strings[OPEN_QUOTE]) {
+ if (done_value == false) {
+ value = CONTENT_OPEN_QUOTE;
+ } else {
+ required_size += sizeof(opv);
+ }
+ } else if (token->type == CSS_TOKEN_IDENT &&
+ token->ilower ==
+ c->strings[CLOSE_QUOTE]) {
+ if (done_value == false) {
+ value = CONTENT_CLOSE_QUOTE;
+ } else {
+ required_size += sizeof(opv);
+ }
+ } else if (token->type == CSS_TOKEN_IDENT &&
+ token->ilower ==
+ c->strings[NO_OPEN_QUOTE]) {
+ if (done_value == false) {
+ value = CONTENT_NO_OPEN_QUOTE;
+ } else {
+ required_size += sizeof(opv);
+ }
+ } else if (token->type == CSS_TOKEN_IDENT &&
+ token->ilower ==
+ c->strings[NO_CLOSE_QUOTE]) {
+ if (done_value == false) {
+ value = CONTENT_NO_CLOSE_QUOTE;
+ } else {
+ required_size += sizeof(opv);
+ }
+ } else if (token->type == CSS_TOKEN_STRING) {
+ if (done_value == false) {
+ value = CONTENT_STRING;
+ } else {
+ required_size += sizeof(opv);
+ }
+
+ required_size +=
+ sizeof(parserutils_hash_entry *);
+ } else if (token->type == CSS_TOKEN_URI) {
+ if (done_value == false) {
+ value = CONTENT_URI;
+ } else {
+ required_size += sizeof(opv);
+ }
+
+ required_size +=
+ sizeof(parserutils_hash_entry *);
+ } else if (token->type == CSS_TOKEN_FUNCTION &&
+ token->ilower == c->strings[ATTR]) {
+ if (done_value == false) {
+ value = CONTENT_ATTR;
+ } else {
+ required_size += sizeof(opv);
+ }
+
+ parserutils_vector_iterate(vector, &temp_ctx);
+
+ consumeWhitespace(vector, &temp_ctx);
+
+ /* Expect IDENT */
+ token = parserutils_vector_iterate(vector,
+ &temp_ctx);
+ if (token == NULL ||
+ token->type != CSS_TOKEN_IDENT)
+ return CSS_INVALID;
+
+ consumeWhitespace(vector, &temp_ctx);
+
+ /* Expect ')' */
+ token = parserutils_vector_peek(vector,
+ temp_ctx);
+ if (token == NULL || tokenIsChar(token, ')') ==
+ false)
+ return CSS_INVALID;
+
+ required_size +=
+ sizeof(parserutils_hash_entry *);
+ } else if (token->type == CSS_TOKEN_FUNCTION &&
+ token->ilower == c->strings[COUNTER]) {
+ if (done_value == false) {
+ value = CONTENT_COUNTER;
+ } else {
+ required_size += sizeof(opv);
+ }
+
+ parserutils_vector_iterate(vector, &temp_ctx);
+
+ consumeWhitespace(vector, &temp_ctx);
+
+ /* Expect IDENT */
+ token = parserutils_vector_iterate(vector,
+ &temp_ctx);
+ if (token == NULL ||
+ token->type != CSS_TOKEN_IDENT)
+ return CSS_INVALID;
+
+ consumeWhitespace(vector, &temp_ctx);
+
+ /* Possible IDENT */
+ token = parserutils_vector_peek(vector,
+ temp_ctx);
+ if (token == NULL ||
+ (token->type != CSS_TOKEN_IDENT &&
+ tokenIsChar(token, ')') ==
+ false))
+ return CSS_INVALID;
+
+ if (token->type == CSS_TOKEN_IDENT) {
+ /** \todo validate list-style-type */
+ if (done_value == false) {
+ /** \todo or style into value */
+ }
+
+ parserutils_vector_iterate(vector,
+ &temp_ctx);
+
+ consumeWhitespace(vector, &temp_ctx);
+
+ token = parserutils_vector_peek(vector,
+ temp_ctx);
+ if (token == NULL || tokenIsChar(token,
+ ')') == false)
+ return CSS_INVALID;
+ }
+
+ required_size +=
+ sizeof(parserutils_hash_entry *);
+ } else if (token->type == CSS_TOKEN_FUNCTION &&
+ token->ilower == c->strings[COUNTERS]) {
+ if (done_value == false) {
+ value = CONTENT_COUNTERS;
+ } else {
+ required_size += sizeof(opv);
+ }
+
+ parserutils_vector_iterate(vector, &temp_ctx);
+
+ consumeWhitespace(vector, &temp_ctx);
+
+ /* Expect IDENT */
+ token = parserutils_vector_iterate(vector,
+ &temp_ctx);
+ if (token == NULL ||
+ token->type != CSS_TOKEN_IDENT)
+ return CSS_INVALID;
+
+ consumeWhitespace(vector, &temp_ctx);
+
+ /* Expect STRING */
+ token = parserutils_vector_iterate(vector,
+ &temp_ctx);
+ if (token == NULL ||
+ token->type != CSS_TOKEN_STRING)
+ return CSS_INVALID;
+
+ consumeWhitespace(vector, &temp_ctx);
+
+ /* Possible IDENT */
+ token = parserutils_vector_peek(vector,
+ temp_ctx);
+ if (token == NULL ||
+ (token->type != CSS_TOKEN_IDENT &&
+ tokenIsChar(token, ')') ==
+ false))
+ return CSS_INVALID;
+
+ if (token->type == CSS_TOKEN_IDENT) {
+ /** \todo validate list-style-type */
+ if (done_value == false) {
+ /** \todo or style into value */
+ }
+
+ parserutils_vector_iterate(vector,
+ &temp_ctx);
+
+ consumeWhitespace(vector, &temp_ctx);
+
+ token = parserutils_vector_peek(vector,
+ temp_ctx);
+ if (token == NULL || tokenIsChar(token,
+ ')') == false)
+ return CSS_INVALID;
+ }
+
+ required_size +=
+ 2 * sizeof(parserutils_hash_entry *);
+ } else {
+ return CSS_INVALID;
+ }
+
+ done_value = true;
+
+ parserutils_vector_iterate(vector, &temp_ctx);
+
+ consumeWhitespace(vector, &temp_ctx);
+
+ token = parserutils_vector_peek(vector, temp_ctx);
+ }
+
+ /* Add on extra space for list terminator */
+ required_size += sizeof(opv);
+ }
+
+ error = parse_important(c, vector, &temp_ctx, &flags);
+ if (error != CSS_OK)
+ return error;
+
+ opv = buildOPV(OP_CONTENT, flags, value);
+
+ /* Allocate result */
+ error = css_stylesheet_style_create(c->sheet, required_size, result);
+ if (error != CSS_OK)
+ return error;
+
+ /** \todo Pass 2: construct bytecode */
return CSS_OK;
}
diff --git a/src/parse/propstrings.h b/src/parse/propstrings.h
index 2942578..7d999c4 100644
--- a/src/parse/propstrings.h
+++ b/src/parse/propstrings.h
@@ -63,7 +63,8 @@ enum {
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, LEFTWARDS, RIGHTWARDS, LEFT_SIDE,
- FAR_LEFT, FAR_RIGHT, RIGHT_SIDE, BEHIND, RECT,
+ FAR_LEFT, FAR_RIGHT, RIGHT_SIDE, BEHIND, RECT, OPEN_QUOTE, CLOSE_QUOTE,
+ NO_OPEN_QUOTE, NO_CLOSE_QUOTE, ATTR, COUNTER, COUNTERS,
LAST_KNOWN
};
@@ -313,6 +314,13 @@ static struct {
{ "right-side", SLEN("right-side") },
{ "behind", SLEN("behind") },
{ "rect", SLEN("rect") },
+ { "open-quote", SLEN("open-quote") },
+ { "close-quote", SLEN("close-quote") },
+ { "no-open-quote", SLEN("no-open-quote") },
+ { "no-close-quote", SLEN("no-close-quote") },
+ { "attr", SLEN("attr") },
+ { "counter", SLEN("counter") },
+ { "counters", SLEN("counters") },
};
#endif