summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Silverstone <dsilvers@netsurf-browser.org>2020-10-03 20:19:47 +0100
committerMichael Drake <Michael Drake tlsa@netsurf-browser.org>2020-12-04 13:43:45 +0000
commitabe10f3dde30e9ef21dc036c70d57bc3f7c1cc95 (patch)
treee872fb0214cc86f6194d665d3b1084f6770579d4
parentcc9d55ba6e7916e2a7e439c7ba0239a1f736db72 (diff)
downloadlibcss-abe10f3dde30e9ef21dc036c70d57bc3f7c1cc95.tar.gz
libcss-abe10f3dde30e9ef21dc036c70d57bc3f7c1cc95.tar.bz2
parse: calc() test and fixup.
-rw-r--r--src/bytecode/bytecode.h14
-rw-r--r--src/parse/properties/css_property_parser_gen.c2
-rw-r--r--src/parse/properties/utils.c66
-rw-r--r--test/data/parse2/INDEX1
-rw-r--r--test/data/parse2/calc.dat7
-rw-r--r--test/dump.h45
6 files changed, 115 insertions, 20 deletions
diff --git a/src/bytecode/bytecode.h b/src/bytecode/bytecode.h
index c356f90..c48f6f8 100644
--- a/src/bytecode/bytecode.h
+++ b/src/bytecode/bytecode.h
@@ -23,6 +23,14 @@ enum flag {
FLAG_INHERIT = (1<<1)
};
+enum calc_opcodes {
+ CALC_PUSH_VALUE = 'V',
+ CALC_ADD = '+',
+ CALC_SUBTRACT = '-',
+ CALC_MULTIPLY = '*',
+ CALC_DIVIDE = '/',
+ CALC_FINISH = '=',
+};
typedef enum unit {
UNIT_LENGTH = (1u << 8),
@@ -110,6 +118,12 @@ static inline bool isInherit(css_code_t OPV)
return getFlags(OPV) & 0x2;
}
+static inline bool isCalc(css_code_t OPV)
+{
+ /* Note, this relies on all _CALC values being the same ultimately */
+ return getValue(OPV) == 0x7f;
+}
+
#endif
diff --git a/src/parse/properties/css_property_parser_gen.c b/src/parse/properties/css_property_parser_gen.c
index 1cdb27f..08f3f12 100644
--- a/src/parse/properties/css_property_parser_gen.c
+++ b/src/parse/properties/css_property_parser_gen.c
@@ -310,7 +310,7 @@ void output_calc(FILE *outputf, struct keyval *parseid, struct keyval_list *kvli
kind = ckv->key;
fprintf(outputf,
- "if ((token->type == CSS_TOKEN_IDENT) && "
+ "if ((token->type == CSS_TOKEN_FUNCTION) && "
"(lwc_string_caseless_isequal(token->idata, c->strings[CALC], &match) == lwc_error_ok && match))"
" {\n"
"\t\terror = css__parse_calc(c, vector, ctx, result, buildOPV(%s, 0, %s), %s);\n"
diff --git a/src/parse/properties/utils.c b/src/parse/properties/utils.c
index 11b7f72..a0fc786 100644
--- a/src/parse/properties/utils.c
+++ b/src/parse/properties/utils.c
@@ -1373,8 +1373,10 @@ css__parse_calc_value(css_language *c,
int orig_ctx = *ctx;
const css_token *token;
- token = parserutils_vector_iterate(vector, ctx);
+ /* On entry, we are already pointing at the value to parse, so peek it */
+ token = parserutils_vector_peek(vector, *ctx);
if (tokenIsChar(token, '(')) {
+ parserutils_vector_iterate(vector, ctx);
error = css__parse_calc_sum(c, vector, ctx, result);
if (error != CSS_OK) {
return error;
@@ -1384,7 +1386,8 @@ css__parse_calc_value(css_language *c,
if (!tokenIsChar(token, ')')) {
return CSS_INVALID;
}
-
+ /* Consume the close-paren to complete this value */
+ parserutils_vector_iterate(vector, ctx);
} else switch (token->type) {
case CSS_TOKEN_NUMBER: /* Fall through */
case CSS_TOKEN_DIMENSION: /* Fall through */
@@ -1400,7 +1403,7 @@ css__parse_calc_value(css_language *c,
return error;
}
- error = css__stylesheet_style_vappend(result, 3, (css_code_t) 'V', length, unit);
+ error = css__stylesheet_style_vappend(result, 3, (css_code_t) CALC_PUSH_VALUE, length, unit);
}
break;
@@ -1409,6 +1412,11 @@ css__parse_calc_value(css_language *c,
break;
}
+ token = parserutils_vector_peek(vector, *ctx);
+ while (token->type == CSS_TOKEN_S) {
+ parserutils_vector_iterate(vector, ctx);
+ token = parserutils_vector_peek(vector, *ctx);
+ }
return error;
}
@@ -1439,7 +1447,10 @@ css__parse_calc_product(css_language *c,
if (token == NULL) {
error = CSS_INVALID;
break;
- } else if (tokenIsChar(token, ')'))
+ } else if (
+ tokenIsChar(token, ')') ||
+ tokenIsChar(token, '+') ||
+ tokenIsChar(token, '-'))
break;
else if (tokenIsChar(token, '*'))
multiplication = true;
@@ -1450,15 +1461,21 @@ css__parse_calc_product(css_language *c,
break;
}
/* Consume that * or / now */
- token = parserutils_vector_iterate(vector, ctx);
+ parserutils_vector_iterate(vector, ctx);
+ token = parserutils_vector_peek(vector, *ctx);
+ while (token->type == CSS_TOKEN_S) {
+ parserutils_vector_iterate(vector, ctx);
+ token = parserutils_vector_peek(vector, *ctx);
+ }
/* parse another value */
error = css__parse_calc_value(c, vector, ctx, result);
if (error != CSS_OK)
break;
/* emit the multiplication/division operator */
- error = css__stylesheet_style_append(result, (css_code_t) (multiplication ? '*' : '/'));
+ error = css__stylesheet_style_append(result,
+ (css_code_t) (multiplication ? CALC_MULTIPLY : CALC_DIVIDE));
} while (1);
/* We've fallen off, either we had an error or we're left with ')' */
return error;
@@ -1498,7 +1515,13 @@ css__parse_calc_sum(css_language *c,
break;
}
/* Consume that + or - now */
- token = parserutils_vector_iterate(vector, ctx);
+ parserutils_vector_iterate(vector, ctx);
+ token = parserutils_vector_peek(vector, *ctx);
+
+ while (token->type == CSS_TOKEN_S) {
+ parserutils_vector_iterate(vector, ctx);
+ token = parserutils_vector_peek(vector, *ctx);
+ }
/* parse another product */
error = css__parse_calc_product(c, vector, ctx, result);
@@ -1506,7 +1529,7 @@ css__parse_calc_sum(css_language *c,
break;
/* emit the addition/subtraction operator */
- error = css__stylesheet_style_append(result, (css_code_t) (addition ? '+' : '-'));
+ error = css__stylesheet_style_append(result, (css_code_t) (addition ? CALC_ADD : CALC_SUBTRACT));
} while (1);
/* We've fallen off, either we had an error or we're left with ')' */
return error;
@@ -1524,16 +1547,15 @@ css_error css__parse_calc(css_language *c,
css_error error = CSS_OK;
css_style *calc_style = NULL;
- token = parserutils_vector_iterate(vector, ctx);
+ token = parserutils_vector_peek(vector, *ctx);
if (token == NULL) {
*ctx = orig_ctx;
return CSS_INVALID;
}
- if (!tokenIsChar(token, '(')) {
- /* If we don't get an open-paren, give up now */
- *ctx = orig_ctx;
- return CSS_INVALID;
+ while (token->type == CSS_TOKEN_S) {
+ parserutils_vector_iterate(vector, ctx);
+ token = parserutils_vector_peek(vector, *ctx);
}
error = css__stylesheet_style_create(c->sheet, &calc_style);
@@ -1545,27 +1567,33 @@ css_error css__parse_calc(css_language *c,
goto cleanup;
error = css__stylesheet_style_append(calc_style, (css_code_t) unit);
+ if (error != CSS_OK)
+ goto cleanup;
error = css__parse_calc_sum(c, vector, ctx, calc_style);
if (error != CSS_OK)
goto cleanup;
- token = parserutils_vector_iterate(vector, ctx);
+ token = parserutils_vector_peek(vector, *ctx);
+ while (token->type == CSS_TOKEN_S) {
+ parserutils_vector_iterate(vector, ctx);
+ token = parserutils_vector_peek(vector, *ctx);
+ }
if (!tokenIsChar(token, ')')) {
/* If we don't get a close-paren, give up now */
error = CSS_INVALID;
goto cleanup;
}
+ /* Swallow that close paren */
+ parserutils_vector_iterate(vector, ctx);
+
/* Append the indicator that the calc is finished */
- error = css__stylesheet_style_append(calc_style, (css_code_t) '=');
+ error = css__stylesheet_style_append(calc_style, (css_code_t) CALC_FINISH);
if (error != CSS_OK)
goto cleanup;
- /* TODO: Once we're OK to do so, merge the style */
- (void)result;
- /* error = css__stylesheet_style_merge_style(result, calc_style); */
-
+ error = css__stylesheet_merge_style(result, calc_style);
cleanup:
css__stylesheet_style_destroy(calc_style);
if (error != CSS_OK) {
diff --git a/test/data/parse2/INDEX b/test/data/parse2/INDEX
index 331cf5c..bb2a79b 100644
--- a/test/data/parse2/INDEX
+++ b/test/data/parse2/INDEX
@@ -23,3 +23,4 @@ multicol.dat Multi-column layout property tests
flexbox.dat Flexbox properties and shorthands tests
units.dat Length unit tests
dodgy-media-block.dat Media block with incomplete ruleset
+calc.dat calc() tests
diff --git a/test/data/parse2/calc.dat b/test/data/parse2/calc.dat
new file mode 100644
index 0000000..95abf6c
--- /dev/null
+++ b/test/data/parse2/calc.dat
@@ -0,0 +1,7 @@
+#data
+* { height: calc(50vh + 10px)}
+#errors
+#expected
+| *
+| height: /* -> 0px */ calc(50vh 10px + =)
+#reset \ No newline at end of file
diff --git a/test/dump.h b/test/dump.h
index d67bb2a..7ad84d9 100644
--- a/test/dump.h
+++ b/test/dump.h
@@ -647,6 +647,12 @@ static void dump_unit(css_fixed val, uint32_t unit, char **ptr)
case UNIT_KHZ:
*ptr += sprintf(*ptr, "kHz");
break;
+ case UNIT_CALC_ANY:
+ *ptr += sprintf(*ptr, "any");
+ break;
+ case UNIT_CALC_NUMBER:
+ *ptr += sprintf(*ptr, "number");
+ break;
}
}
@@ -797,6 +803,45 @@ void dump_bytecode(css_style *style, char **ptr, uint32_t depth)
if (isInherit(opv)) {
*ptr += sprintf(*ptr, "inherit");
+ } else if (isCalc(opv)) {
+ /* First entry is a unit */
+ uint32_t unit = *((uint32_t *)bytecode);
+ ADVANCE(sizeof(unit));
+ *ptr += sprintf(*ptr, "/* -> ");
+ dump_unit(0, unit, ptr);
+ *ptr += sprintf(*ptr, " */ calc(");
+ css_code_t calc_opcode;
+ while ((calc_opcode = *((css_code_t *)bytecode)) != CALC_FINISH) {
+ ADVANCE(sizeof(calc_opcode));
+ switch (calc_opcode) {
+ case CALC_ADD:
+ *ptr += sprintf(*ptr, "+ ");
+ break;
+ case CALC_SUBTRACT:
+ *ptr += sprintf(*ptr, "- ");
+ break;
+ case CALC_MULTIPLY:
+ *ptr += sprintf(*ptr, "* ");
+ break;
+ case CALC_DIVIDE:
+ *ptr += sprintf(*ptr, "/ ");
+ break;
+ case CALC_PUSH_VALUE: {
+ css_fixed num = *((css_fixed *)bytecode);
+ ADVANCE(sizeof(num));
+ uint32_t unit = *((uint32_t *)bytecode);
+ ADVANCE(sizeof(unit));
+ dump_unit(num, unit, ptr);
+ *ptr += sprintf(*ptr, " ");
+ break;
+ }
+ default:
+ *ptr += sprintf(*ptr, "??%d ", calc_opcode);
+ break;
+ }
+ }
+ ADVANCE(sizeof(calc_opcode));
+ *ptr += sprintf(*ptr, "=)");
} else {
value = getValue(opv);