summaryrefslogtreecommitdiff
path: root/src/parse/properties
diff options
context:
space:
mode:
Diffstat (limited to 'src/parse/properties')
-rw-r--r--src/parse/properties/content.c4
-rw-r--r--src/parse/properties/css_property_parser_gen.c54
-rw-r--r--src/parse/properties/font.c1
-rw-r--r--src/parse/properties/properties.gen78
-rw-r--r--src/parse/properties/text_decoration.c2
-rw-r--r--src/parse/properties/utils.c361
-rw-r--r--src/parse/properties/utils.h24
7 files changed, 481 insertions, 43 deletions
diff --git a/src/parse/properties/content.c b/src/parse/properties/content.c
index b32de22..7c03c6a 100644
--- a/src/parse/properties/content.c
+++ b/src/parse/properties/content.c
@@ -33,7 +33,7 @@ css_error css__parse_content(css_language *c,
css_style *result)
{
int32_t orig_ctx = *ctx;
- css_error error;
+ css_error error = CSS_INVALID;
const css_token *token;
enum flag_value flag_value;
bool match;
@@ -42,7 +42,7 @@ css_error css__parse_content(css_language *c,
token = parserutils_vector_iterate(vector, ctx);
if (token == NULL) {
*ctx = orig_ctx;
- return CSS_INVALID;
+ return error;
}
flag_value = get_css_flag_value(c, token);
diff --git a/src/parse/properties/css_property_parser_gen.c b/src/parse/properties/css_property_parser_gen.c
index 3e1d997..85d8122 100644
--- a/src/parse/properties/css_property_parser_gen.c
+++ b/src/parse/properties/css_property_parser_gen.c
@@ -19,6 +19,12 @@
* list_style_position:CSS_PROP_LIST_STYLE_POSITION IDENT:( INHERIT: INSIDE:0,LIST_STYLE_POSITION_INSIDE OUTSIDE:0,LIST_STYLE_POSITION_OUTSIDE IDENT:)
*/
+typedef enum {
+ CALC_ANY,
+ CALC_NUMBER,
+ CALC_UNIT,
+} calc_kind;
+
struct keyval {
char *key;
char *val;
@@ -44,7 +50,12 @@ struct keyval *get_keyval(char **pos)
} else {
kvlen = (endpos - *pos);
}
+
nkeyval = calloc(1, sizeof(struct keyval) + kvlen + 1);
+ if (nkeyval == NULL) {
+ /* allocation failed, cannot proceed */
+ return NULL;
+ }
memcpy(nkeyval + 1, *pos, kvlen);
@@ -311,12 +322,35 @@ void output_color(FILE *outputf, struct keyval *parseid, struct keyval_list *kvl
parseid->val);
}
+void output_calc(FILE *outputf, struct keyval *parseid, struct keyval_list *kvlist)
+{
+ struct keyval *ckv = kvlist->item[0];
+ const char *kind;
+
+ if (strcmp(ckv->key, "NUMBER") == 0)
+ kind = "UNIT_CALC_NUMBER";
+ else if (strcmp(ckv->key, "ANY") == 0)
+ kind = "UNIT_CALC_ANY";
+ else
+ kind = ckv->key;
+
+ fprintf(outputf,
+ "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"
+ "\t} else ",
+ parseid->val,
+ ckv->val,
+ kind
+ );
+}
+
void output_length_unit(FILE *outputf, struct keyval *parseid, struct keyval_list *kvlist)
{
struct keyval *ckv = kvlist->item[0];
int ident_count;
-
fprintf(outputf,
"{\n"
"\t\tcss_fixed length = 0;\n"
@@ -523,6 +557,7 @@ int main(int argc, char **argv)
struct keyval_list WRAP;
struct keyval_list NUMBER;
struct keyval_list COLOR;
+ struct keyval_list CALC;
if (argc < 2) {
@@ -555,6 +590,7 @@ int main(int argc, char **argv)
COLOR.count = 0;
LENGTH_UNIT.count = 0;
IDENT_LIST.count = 0;
+ CALC.count = 0;
curlist = &base;
@@ -570,7 +606,7 @@ int main(int argc, char **argv)
if (strcmp(rkv->key, "WRAP") == 0) {
WRAP.item[WRAP.count++] = rkv;
only_ident = false;
- } else if (strcmp(rkv->key, "NUMBER") == 0) {
+ } else if (curlist == &base && strcmp(rkv->key, "NUMBER") == 0) {
if (rkv->val[0] == '(') {
curlist = &NUMBER;
} else if (rkv->val[0] == ')') {
@@ -607,6 +643,14 @@ int main(int argc, char **argv)
}
only_ident = false;
do_token_check = false;
+ } else if (strcmp(rkv->key, "CALC") == 0) {
+ if (rkv->val[0] == '(') {
+ curlist = &CALC;
+ } else if (rkv->val[0] == ')') {
+ curlist = &base;
+ }
+ only_ident = false;
+ do_token_check = false;
} else if (strcmp(rkv->key, "COLOR") == 0) {
COLOR.item[COLOR.count++] = rkv;
do_token_check = false;
@@ -630,7 +674,7 @@ int main(int argc, char **argv)
/* header */
-output_header(outputf, descriptor, base.item[0], is_generic);
+ output_header(outputf, descriptor, base.item[0], is_generic);
if (WRAP.count > 0) {
output_wrap(outputf, base.item[0], &WRAP);
@@ -644,6 +688,10 @@ output_header(outputf, descriptor, base.item[0], is_generic);
if (URI.count > 0)
output_uri(outputf, base.item[0], &URI);
+ if (CALC.count > 0) {
+ output_calc(outputf, base.item[0], &CALC);
+ }
+
if (NUMBER.count > 0)
output_number(outputf, base.item[0], &NUMBER);
diff --git a/src/parse/properties/font.c b/src/parse/properties/font.c
index 16a6cc4..2d95cd8 100644
--- a/src/parse/properties/font.c
+++ b/src/parse/properties/font.c
@@ -45,6 +45,7 @@ static inline uint32_t css__to_parse_unit(css_unit u)
case CSS_UNIT_S: return UNIT_S;
case CSS_UNIT_HZ: return UNIT_HZ;
case CSS_UNIT_KHZ: return UNIT_KHZ;
+ case CSS_UNIT_CALC: assert(0);
}
return 0;
diff --git a/src/parse/properties/properties.gen b/src/parse/properties/properties.gen
index b0e797c..3452f81 100644
--- a/src/parse/properties/properties.gen
+++ b/src/parse/properties/properties.gen
@@ -6,6 +6,13 @@
#property:CSS_PROP_ENUM IDENT:( INHERIT: INITIAL: REVERT: UNSET: IDENT:) LENGTH_UNIT:( UNIT_HZ:PITCH_FREQUENCY ALLOW: DISALLOW: RANGE:<0 LENGTH_UNIT:)
#property:CSS_PROP_ENUM WRAP:
+# When a property takes a NUMBER and/or LENGTH_UNIT you may add calc() support:
+# In the below, PROPERTY_FOO_CALC is the opcode enum for the set-but-calculated value bytecode.
+# e.g. HEIGHT_SET (for a LENGTH_UNIT) would be HEIGHT_CALC here.
+# CALC:( UNIT_??:PROPERTY_FOO_CALC CALC:) <-- When a default unit must be considered
+# CALC:( NUMBER:PROPERTY_FOO_CALC CALC:) <-- When a number must be produced (not a dimension)
+# CALC:( ANY:PROPERTY_FOO_CALC CALC:) <-- When a number or dimension is valid (e.g. line-height)
+
background_repeat:CSS_PROP_BACKGROUND_REPEAT IDENT:( INHERIT: INITIAL: REVERT: UNSET: NO_REPEAT:0,BACKGROUND_REPEAT_NO_REPEAT REPEAT_X:0,BACKGROUND_REPEAT_REPEAT_X REPEAT_Y:0,BACKGROUND_REPEAT_REPEAT_Y REPEAT:0,BACKGROUND_REPEAT_REPEAT IDENT:)
border_collapse:CSS_PROP_BORDER_COLLAPSE IDENT:( INHERIT: INITIAL: REVERT: UNSET: COLLAPSE:0,BORDER_COLLAPSE_COLLAPSE SEPARATE:0,BORDER_COLLAPSE_SEPARATE IDENT:)
@@ -22,35 +29,35 @@ empty_cells:CSS_PROP_EMPTY_CELLS IDENT:( INHERIT: INITIAL: REVERT: UNSET: SHOW:0
float:CSS_PROP_FLOAT IDENT:( INHERIT: INITIAL: REVERT: UNSET: LEFT:0,FLOAT_LEFT RIGHT:0,FLOAT_RIGHT NONE:0,FLOAT_NONE IDENT:)
-font_size:CSS_PROP_FONT_SIZE IDENT:( INHERIT: INITIAL: REVERT: UNSET: XX_SMALL:0,FONT_SIZE_XX_SMALL X_SMALL:0,FONT_SIZE_X_SMALL SMALL:0,FONT_SIZE_SMALL MEDIUM:0,FONT_SIZE_MEDIUM LARGE:0,FONT_SIZE_LARGE X_LARGE:0,FONT_SIZE_X_LARGE XX_LARGE:0,FONT_SIZE_XX_LARGE LARGER:0,FONT_SIZE_LARGER SMALLER:0,FONT_SIZE_SMALLER IDENT:) LENGTH_UNIT:( UNIT_PX:FONT_SIZE_DIMENSION MASK:UNIT_MASK_FONT_SIZE RANGE:<0 LENGTH_UNIT:)
+font_size:CSS_PROP_FONT_SIZE IDENT:( INHERIT: INITIAL: REVERT: UNSET: XX_SMALL:0,FONT_SIZE_XX_SMALL X_SMALL:0,FONT_SIZE_X_SMALL SMALL:0,FONT_SIZE_SMALL MEDIUM:0,FONT_SIZE_MEDIUM LARGE:0,FONT_SIZE_LARGE X_LARGE:0,FONT_SIZE_X_LARGE XX_LARGE:0,FONT_SIZE_XX_LARGE LARGER:0,FONT_SIZE_LARGER SMALLER:0,FONT_SIZE_SMALLER IDENT:) LENGTH_UNIT:( UNIT_PX:FONT_SIZE_DIMENSION MASK:UNIT_MASK_FONT_SIZE RANGE:<0 LENGTH_UNIT:) CALC:( UNIT_PX:FONT_SIZE_CALC CALC:)
font_style:CSS_PROP_FONT_STYLE IDENT:( INHERIT: INITIAL: REVERT: UNSET: NORMAL:0,FONT_STYLE_NORMAL ITALIC:0,FONT_STYLE_ITALIC OBLIQUE:0,FONT_STYLE_OBLIQUE IDENT:)
font_variant:CSS_PROP_FONT_VARIANT IDENT:( INHERIT: INITIAL: REVERT: UNSET: NORMAL:0,FONT_VARIANT_NORMAL SMALL_CAPS:0,FONT_VARIANT_SMALL_CAPS IDENT:)
-height:CSS_PROP_HEIGHT IDENT:( INHERIT: INITIAL: REVERT: UNSET: AUTO:0,HEIGHT_AUTO IDENT:) LENGTH_UNIT:( UNIT_PX:HEIGHT_SET MASK:UNIT_MASK_HEIGHT RANGE:<0 LENGTH_UNIT:)
+height:CSS_PROP_HEIGHT IDENT:( INHERIT: INITIAL: REVERT: UNSET: AUTO:0,HEIGHT_AUTO IDENT:) LENGTH_UNIT:( UNIT_PX:HEIGHT_SET MASK:UNIT_MASK_HEIGHT RANGE:<0 LENGTH_UNIT:) CALC:( UNIT_PX:HEIGHT_CALC CALC:)
-letter_spacing:CSS_PROP_LETTER_SPACING IDENT:( INHERIT: INITIAL: REVERT: UNSET: NORMAL:0,LETTER_SPACING_NORMAL IDENT:) LENGTH_UNIT:( UNIT_PX:LETTER_SPACING_SET MASK:UNIT_MASK_LETTER_SPACING LENGTH_UNIT:)
+letter_spacing:CSS_PROP_LETTER_SPACING IDENT:( INHERIT: INITIAL: REVERT: UNSET: NORMAL:0,LETTER_SPACING_NORMAL IDENT:) LENGTH_UNIT:( UNIT_PX:LETTER_SPACING_SET MASK:UNIT_MASK_LETTER_SPACING LENGTH_UNIT:) CALC:( UNIT_PX:LETTER_SPACING_CALC CALC:)
-line_height:CSS_PROP_LINE_HEIGHT IDENT:( INHERIT: INITIAL: REVERT: UNSET: NORMAL:0,LINE_HEIGHT_NORMAL IDENT:) NUMBER:( false:LINE_HEIGHT_NUMBER RANGE:num<0 NUMBER:) LENGTH_UNIT:( UNIT_PX:LINE_HEIGHT_DIMENSION MASK:UNIT_MASK_LINE_HEIGHT RANGE:<0 LENGTH_UNIT:)
+line_height:CSS_PROP_LINE_HEIGHT IDENT:( INHERIT: INITIAL: REVERT: UNSET: NORMAL:0,LINE_HEIGHT_NORMAL IDENT:) NUMBER:( false:LINE_HEIGHT_NUMBER RANGE:num<0 NUMBER:) LENGTH_UNIT:( UNIT_PX:LINE_HEIGHT_DIMENSION MASK:UNIT_MASK_LINE_HEIGHT RANGE:<0 LENGTH_UNIT:) CALC:( ANY:LINE_HEIGHT_CALC CALC:)
border_top:BORDER_SIDE_TOP WRAP:css__parse_border_side
border_bottom:BORDER_SIDE_BOTTOM WRAP:css__parse_border_side
border_left:BORDER_SIDE_LEFT WRAP:css__parse_border_side
border_right:BORDER_SIDE_RIGHT WRAP:css__parse_border_side
-max_height:CSS_PROP_MAX_HEIGHT IDENT:( INHERIT: INITIAL: REVERT: UNSET: NONE:0,MAX_HEIGHT_NONE IDENT:) LENGTH_UNIT:( UNIT_PX:MAX_HEIGHT_SET MASK:UNIT_MASK_MAX_HEIGHT RANGE:<0 LENGTH_UNIT:)
+max_height:CSS_PROP_MAX_HEIGHT IDENT:( INHERIT: INITIAL: REVERT: UNSET: NONE:0,MAX_HEIGHT_NONE IDENT:) LENGTH_UNIT:( UNIT_PX:MAX_HEIGHT_SET MASK:UNIT_MASK_MAX_HEIGHT RANGE:<0 LENGTH_UNIT:) CALC:( UNIT_PX:MAX_HEIGHT_CALC CALC:)
-max_width:CSS_PROP_MAX_WIDTH IDENT:( INHERIT: INITIAL: REVERT: UNSET: NONE:0,MAX_WIDTH_NONE IDENT:) LENGTH_UNIT:( UNIT_PX:MAX_WIDTH_SET MASK:UNIT_MASK_MAX_WIDTH RANGE:<0 LENGTH_UNIT:)
+max_width:CSS_PROP_MAX_WIDTH IDENT:( INHERIT: INITIAL: REVERT: UNSET: NONE:0,MAX_WIDTH_NONE IDENT:) LENGTH_UNIT:( UNIT_PX:MAX_WIDTH_SET MASK:UNIT_MASK_MAX_WIDTH RANGE:<0 LENGTH_UNIT:) CALC:( UNIT_PX:MAX_WIDTH_CALC CALC:)
-min_height:CSS_PROP_MIN_HEIGHT IDENT:( INHERIT: INITIAL: REVERT: UNSET: AUTO:0,MIN_HEIGHT_AUTO IDENT:) LENGTH_UNIT:( UNIT_PX:MIN_HEIGHT_SET MASK:UNIT_MASK_MIN_HEIGHT RANGE:<0 LENGTH_UNIT:)
+min_height:CSS_PROP_MIN_HEIGHT IDENT:( INHERIT: INITIAL: REVERT: UNSET: AUTO:0,MIN_HEIGHT_AUTO IDENT:) LENGTH_UNIT:( UNIT_PX:MIN_HEIGHT_SET MASK:UNIT_MASK_MIN_HEIGHT RANGE:<0 LENGTH_UNIT:) CALC:( UNIT_PX:MIN_HEIGHT_CALC CALC:)
-min_width:CSS_PROP_MIN_WIDTH IDENT:( INHERIT: INITIAL: REVERT: UNSET: AUTO:0,MIN_WIDTH_AUTO IDENT:) LENGTH_UNIT:( UNIT_PX:MIN_WIDTH_SET MASK:UNIT_MASK_MIN_WIDTH RANGE:<0 LENGTH_UNIT:)
+min_width:CSS_PROP_MIN_WIDTH IDENT:( INHERIT: INITIAL: REVERT: UNSET: AUTO:0,MIN_WIDTH_AUTO IDENT:) LENGTH_UNIT:( UNIT_PX:MIN_WIDTH_SET MASK:UNIT_MASK_MIN_WIDTH RANGE:<0 LENGTH_UNIT:) CALC:( UNIT_PX:MIN_WIDTH_CALC CALC:)
color:CSS_PROP_COLOR IDENT:( INHERIT: INITIAL: REVERT: UNSET: IDENT:) COLOR:COLOR_SET
#generic for padding_{top, bottom, left, right}.c
-padding_side:op GENERIC: IDENT:( INHERIT: INITIAL: REVERT: UNSET: IDENT:) LENGTH_UNIT:( UNIT_PX:PADDING_SET MASK:UNIT_MASK_PADDING_SIDE RANGE:<0 LENGTH_UNIT:)
+padding_side:op GENERIC: IDENT:( INHERIT: INITIAL: REVERT: UNSET: IDENT:) LENGTH_UNIT:( UNIT_PX:PADDING_SET MASK:UNIT_MASK_PADDING_SIDE RANGE:<0 LENGTH_UNIT:) CALC:( UNIT_PX:PADDING_CALC CALC:)
padding_bottom:CSS_PROP_PADDING_BOTTOM WRAP:css__parse_padding_side
padding_left:CSS_PROP_PADDING_LEFT WRAP:css__parse_padding_side
@@ -59,7 +66,7 @@ padding_right:CSS_PROP_PADDING_RIGHT WRAP:css__parse_padding_side
#generic for margin_{top, bottom, left, right}.c
-margin_side:op GENERIC IDENT:( INHERIT: INITIAL: REVERT: UNSET: AUTO:0,MARGIN_AUTO IDENT:) LENGTH_UNIT:( UNIT_PX:MARGIN_SET MASK:UNIT_MASK_MARGIN_SIDE LENGTH_UNIT:)
+margin_side:op GENERIC IDENT:( INHERIT: INITIAL: REVERT: UNSET: AUTO:0,MARGIN_AUTO IDENT:) LENGTH_UNIT:( UNIT_PX:MARGIN_SET MASK:UNIT_MASK_MARGIN_SIDE LENGTH_UNIT:) CALC:( UNIT_PX:MARGIN_CALC CALC:)
margin_top:CSS_PROP_MARGIN_TOP WRAP:css__parse_margin_side
margin_bottom:CSS_PROP_MARGIN_BOTTOM WRAP:css__parse_margin_side
@@ -67,7 +74,7 @@ margin_left:CSS_PROP_MARGIN_LEFT WRAP:css__parse_margin_side
margin_right:CSS_PROP_MARGIN_RIGHT WRAP:css__parse_margin_side
#generic for {top, bottom, left, right}.c
-side:op GENERIC: IDENT:( INHERIT: INITIAL: REVERT: UNSET: AUTO:0,BOTTOM_AUTO IDENT:) LENGTH_UNIT:( UNIT_PX:BOTTOM_SET ALLOW:unit&(UNIT_LENGTH|UNIT_PCT) LENGTH_UNIT:)
+side:op GENERIC: IDENT:( INHERIT: INITIAL: REVERT: UNSET: AUTO:0,BOTTOM_AUTO IDENT:) LENGTH_UNIT:( UNIT_PX:BOTTOM_SET ALLOW:unit&(UNIT_LENGTH|UNIT_PCT) LENGTH_UNIT:) CALC:( UNIT_PX:BOTTOM_CALC CALC:)
top:CSS_PROP_TOP WRAP:css__parse_side
bottom:CSS_PROP_BOTTOM WRAP:css__parse_side
@@ -76,7 +83,7 @@ right:CSS_PROP_RIGHT WRAP:css__parse_side
#generic for border_{top, bottom, left, right}_width.c
-border_side_width:op GENERIC: IDENT:( INHERIT: INITIAL: REVERT: UNSET: THIN:0,BORDER_WIDTH_THIN MEDIUM:0,BORDER_WIDTH_MEDIUM THICK:0,BORDER_WIDTH_THICK IDENT:) LENGTH_UNIT:( UNIT_PX:BORDER_WIDTH_SET MASK:UNIT_MASK_BORDER_SIDE_WIDTH RANGE:<0 LENGTH_UNIT:)
+border_side_width:op GENERIC: IDENT:( INHERIT: INITIAL: REVERT: UNSET: THIN:0,BORDER_WIDTH_THIN MEDIUM:0,BORDER_WIDTH_MEDIUM THICK:0,BORDER_WIDTH_THICK IDENT:) LENGTH_UNIT:( UNIT_PX:BORDER_WIDTH_SET MASK:UNIT_MASK_BORDER_SIDE_WIDTH RANGE:<0 LENGTH_UNIT:) CALC:( UNIT_PX:BORDER_WIDTH_CALC CALC:)
border_top_width:CSS_PROP_BORDER_TOP_WIDTH WRAP:css__parse_border_side_width
border_bottom_width:CSS_PROP_BORDER_BOTTOM_WIDTH WRAP:css__parse_border_side_width
@@ -120,7 +127,7 @@ list_style_image:CSS_PROP_LIST_STYLE_IMAGE IDENT:( INHERIT: INITIAL: REVERT: UNS
list_style_position:CSS_PROP_LIST_STYLE_POSITION IDENT:( INHERIT: INITIAL: REVERT: UNSET: INSIDE:0,LIST_STYLE_POSITION_INSIDE OUTSIDE:0,LIST_STYLE_POSITION_OUTSIDE IDENT:)
-orphans:CSS_PROP_ORPHANS IDENT:( INHERIT: INITIAL: REVERT: UNSET: IDENT:) NUMBER:( true:ORPHANS_SET RANGE:num<0 NUMBER:)
+orphans:CSS_PROP_ORPHANS IDENT:( INHERIT: INITIAL: REVERT: UNSET: IDENT:) NUMBER:( true:ORPHANS_SET RANGE:num<0 NUMBER:) CALC:( NUMBER:ORPHANS_CALC CALC:)
outline_color:CSS_PROP_OUTLINE_COLOR IDENT:( INHERIT: INITIAL: REVERT: UNSET: INVERT:0,OUTLINE_COLOR_INVERT IDENT:) COLOR:OUTLINE_COLOR_SET
@@ -133,24 +140,23 @@ overflow_x:CSS_PROP_OVERFLOW_X IDENT:( INHERIT: INITIAL: REVERT: UNSET: VISIBLE:
overflow_y:CSS_PROP_OVERFLOW_Y IDENT:( INHERIT: INITIAL: REVERT: UNSET: VISIBLE:0,OVERFLOW_VISIBLE HIDDEN:0,OVERFLOW_HIDDEN SCROLL:0,OVERFLOW_SCROLL AUTO:0,OVERFLOW_AUTO IDENT:)
-
page_break_after:CSS_PROP_PAGE_BREAK_AFTER IDENT:( INHERIT: INITIAL: REVERT: UNSET: AUTO:0,PAGE_BREAK_AFTER_AUTO ALWAYS:0,PAGE_BREAK_AFTER_ALWAYS AVOID:0,PAGE_BREAK_AFTER_AVOID LEFT:0,PAGE_BREAK_AFTER_LEFT RIGHT:0,PAGE_BREAK_AFTER_RIGHT IDENT:)
page_break_before:CSS_PROP_PAGE_BREAK_BEFORE IDENT:( INHERIT: INITIAL: REVERT: UNSET: AUTO:0,PAGE_BREAK_BEFORE_AUTO ALWAYS:0,PAGE_BREAK_BEFORE_ALWAYS AVOID:0,PAGE_BREAK_BEFORE_AVOID LEFT:0,PAGE_BREAK_BEFORE_LEFT RIGHT:0,PAGE_BREAK_BEFORE_RIGHT IDENT:)
page_break_inside:CSS_PROP_PAGE_BREAK_INSIDE IDENT:( INHERIT: INITIAL: REVERT: UNSET: AUTO:0,PAGE_BREAK_INSIDE_AUTO AVOID:0,PAGE_BREAK_INSIDE_AVOID IDENT:)
-pause_after:CSS_PROP_PAUSE_AFTER IDENT:( INHERIT: INITIAL: REVERT: UNSET: IDENT:) LENGTH_UNIT:( UNIT_S:PAUSE_AFTER_SET MASK:UNIT_MASK_PAUSE_AFTER RANGE:<0 LENGTH_UNIT:)
+pause_after:CSS_PROP_PAUSE_AFTER IDENT:( INHERIT: INITIAL: REVERT: UNSET: IDENT:) LENGTH_UNIT:( UNIT_S:PAUSE_AFTER_SET MASK:UNIT_MASK_PAUSE_AFTER RANGE:<0 LENGTH_UNIT:) CALC:( UNIT_S:PAUSE_AFTER_CALC CALC:)
-pause_before:CSS_PROP_PAUSE_BEFORE IDENT:( INHERIT: INITIAL: REVERT: UNSET: IDENT:) LENGTH_UNIT:( UNIT_S:PAUSE_BEFORE_SET MASK:UNIT_MASK_PAUSE_BEFORE RANGE:<0 LENGTH_UNIT:)
+pause_before:CSS_PROP_PAUSE_BEFORE IDENT:( INHERIT: INITIAL: REVERT: UNSET: IDENT:) LENGTH_UNIT:( UNIT_S:PAUSE_BEFORE_SET MASK:UNIT_MASK_PAUSE_BEFORE RANGE:<0 LENGTH_UNIT:) CALC:( UNIT_S:PAUSE_BEFORE_CALC CALC:)
-pitch:CSS_PROP_PITCH IDENT:( INHERIT: INITIAL: REVERT: UNSET: X_LOW:0,PITCH_X_LOW LOW:0,PITCH_LOW MEDIUM:0,PITCH_MEDIUM HIGH:0,PITCH_HIGH X_HIGH:0,PITCH_X_HIGH IDENT:) LENGTH_UNIT:( UNIT_HZ:PITCH_FREQUENCY MASK:UNIT_MASK_PITCH RANGE:<0 LENGTH_UNIT:)
+pitch:CSS_PROP_PITCH IDENT:( INHERIT: INITIAL: REVERT: UNSET: X_LOW:0,PITCH_X_LOW LOW:0,PITCH_LOW MEDIUM:0,PITCH_MEDIUM HIGH:0,PITCH_HIGH X_HIGH:0,PITCH_X_HIGH IDENT:) LENGTH_UNIT:( UNIT_HZ:PITCH_FREQUENCY MASK:UNIT_MASK_PITCH RANGE:<0 LENGTH_UNIT:) CALC:( UNIT_HZ:PITCH_CALC CALC:)
-pitch_range:CSS_PROP_PITCH_RANGE IDENT:( INHERIT: INITIAL: REVERT: UNSET: IDENT:) NUMBER:( false:PITCH_RANGE_SET RANGE:num<0||num>F_100 NUMBER:)
+pitch_range:CSS_PROP_PITCH_RANGE IDENT:( INHERIT: INITIAL: REVERT: UNSET: IDENT:) NUMBER:( false:PITCH_RANGE_SET RANGE:num<0||num>F_100 NUMBER:) CALC:( NUMBER:PITCH_RANGE_CALC CALC:)
position:CSS_PROP_POSITION IDENT:( INHERIT: INITIAL: REVERT: UNSET: LIBCSS_STATIC:0,POSITION_STATIC RELATIVE:0,POSITION_RELATIVE ABSOLUTE:0,POSITION_ABSOLUTE FIXED:0,POSITION_FIXED STICKY:0,POSITION_STICKY IDENT:)
-richness:CSS_PROP_RICHNESS IDENT:( INHERIT: INITIAL: REVERT: UNSET: IDENT:) NUMBER:( false:RICHNESS_SET RANGE:num<0||num>F_100 NUMBER:)
+richness:CSS_PROP_RICHNESS IDENT:( INHERIT: INITIAL: REVERT: UNSET: IDENT:) NUMBER:( false:RICHNESS_SET RANGE:num<0||num>F_100 NUMBER:) CALC:( NUMBER:RICHNESS_CALC CALC:)
speak:CSS_PROP_SPEAK IDENT:( INHERIT: INITIAL: REVERT: UNSET: NORMAL:0,SPEAK_NORMAL NONE:0,SPEAK_NONE SPELL_OUT:0,SPEAK_SPELL_OUT IDENT:)
@@ -160,37 +166,35 @@ speak_numeral:CSS_PROP_SPEAK_NUMERAL IDENT:( INHERIT: INITIAL: REVERT: UNSET: DI
speak_punctuation:CSS_PROP_SPEAK_PUNCTUATION IDENT:( INHERIT: INITIAL: REVERT: UNSET: CODE:0,SPEAK_PUNCTUATION_CODE NONE:0,SPEAK_PUNCTUATION_NONE IDENT:)
-speech_rate:CSS_PROP_SPEECH_RATE IDENT:( INHERIT: INITIAL: REVERT: UNSET: X_SLOW:0,SPEECH_RATE_X_SLOW SLOW:0,SPEECH_RATE_SLOW MEDIUM:0,SPEECH_RATE_MEDIUM FAST:0,SPEECH_RATE_FAST X_FAST:0,SPEECH_RATE_X_FAST FASTER:0,SPEECH_RATE_FASTER SLOWER:0,SPEECH_RATE_SLOWER IDENT:) NUMBER:( false:SPEECH_RATE_SET RANGE:num<0 NUMBER:)
+speech_rate:CSS_PROP_SPEECH_RATE IDENT:( INHERIT: INITIAL: REVERT: UNSET: X_SLOW:0,SPEECH_RATE_X_SLOW SLOW:0,SPEECH_RATE_SLOW MEDIUM:0,SPEECH_RATE_MEDIUM FAST:0,SPEECH_RATE_FAST X_FAST:0,SPEECH_RATE_X_FAST FASTER:0,SPEECH_RATE_FASTER SLOWER:0,SPEECH_RATE_SLOWER IDENT:) NUMBER:( false:SPEECH_RATE_SET RANGE:num<0 NUMBER:) CALC:( NUMBER:SPEECH_RATE_CALC CALC:)
-stress:CSS_PROP_STRESS IDENT:( INHERIT: INITIAL: REVERT: UNSET: IDENT:) NUMBER:( false:STRESS_SET RANGE:num<0||num>INTTOFIX(100) NUMBER:)
+stress:CSS_PROP_STRESS IDENT:( INHERIT: INITIAL: REVERT: UNSET: IDENT:) NUMBER:( false:STRESS_SET RANGE:num<0||num>INTTOFIX(100) NUMBER:) CALC:( NUMBER:STRESS_CALC CALC:)
table_layout:CSS_PROP_TABLE_LAYOUT IDENT:( INHERIT: INITIAL: REVERT: UNSET: AUTO:0,TABLE_LAYOUT_AUTO FIXED:0,TABLE_LAYOUT_FIXED IDENT:)
text_align:CSS_PROP_TEXT_ALIGN IDENT:( INHERIT: INITIAL: REVERT: UNSET: LEFT:0,TEXT_ALIGN_LEFT RIGHT:0,TEXT_ALIGN_RIGHT CENTER:0,TEXT_ALIGN_CENTER JUSTIFY:0,TEXT_ALIGN_JUSTIFY LIBCSS_LEFT:0,TEXT_ALIGN_LIBCSS_LEFT LIBCSS_CENTER:0,TEXT_ALIGN_LIBCSS_CENTER LIBCSS_RIGHT:0,TEXT_ALIGN_LIBCSS_RIGHT IDENT:)
-text_indent:CSS_PROP_TEXT_INDENT IDENT:( INHERIT: INITIAL: REVERT: UNSET: IDENT:) LENGTH_UNIT:( UNIT_PX:TEXT_INDENT_SET MASK:UNIT_MASK_TEXT_INDENT LENGTH_UNIT:)
+text_indent:CSS_PROP_TEXT_INDENT IDENT:( INHERIT: INITIAL: REVERT: UNSET: IDENT:) LENGTH_UNIT:( UNIT_PX:TEXT_INDENT_SET MASK:UNIT_MASK_TEXT_INDENT LENGTH_UNIT:) CALC:( UNIT_PX:TEXT_INDENT_CALC CALC:)
text_transform:CSS_PROP_TEXT_TRANSFORM IDENT:( INHERIT: INITIAL: REVERT: UNSET: CAPITALIZE:0,TEXT_TRANSFORM_CAPITALIZE UPPERCASE:0,TEXT_TRANSFORM_UPPERCASE LOWERCASE:0,TEXT_TRANSFORM_LOWERCASE NONE:0,TEXT_TRANSFORM_NONE IDENT:)
unicode_bidi:CSS_PROP_UNICODE_BIDI IDENT:( INHERIT: INITIAL: REVERT: UNSET: NORMAL:0,UNICODE_BIDI_NORMAL EMBED:0,UNICODE_BIDI_EMBED BIDI_OVERRIDE:0,UNICODE_BIDI_BIDI_OVERRIDE IDENT:)
-vertical_align:CSS_PROP_VERTICAL_ALIGN IDENT:( INHERIT: INITIAL: REVERT: UNSET: BASELINE:0,VERTICAL_ALIGN_BASELINE SUB:0,VERTICAL_ALIGN_SUB SUPER:0,VERTICAL_ALIGN_SUPER TOP:0,VERTICAL_ALIGN_TOP TEXT_TOP:0,VERTICAL_ALIGN_TEXT_TOP MIDDLE:0,VERTICAL_ALIGN_MIDDLE BOTTOM:0,VERTICAL_ALIGN_BOTTOM TEXT_BOTTOM:0,VERTICAL_ALIGN_TEXT_BOTTOM IDENT:) LENGTH_UNIT:( UNIT_PX:VERTICAL_ALIGN_SET MASK:UNIT_MASK_VERTICAL_ALIGN LENGTH_UNIT:)
+vertical_align:CSS_PROP_VERTICAL_ALIGN IDENT:( INHERIT: INITIAL: REVERT: UNSET: BASELINE:0,VERTICAL_ALIGN_BASELINE SUB:0,VERTICAL_ALIGN_SUB SUPER:0,VERTICAL_ALIGN_SUPER TOP:0,VERTICAL_ALIGN_TOP TEXT_TOP:0,VERTICAL_ALIGN_TEXT_TOP MIDDLE:0,VERTICAL_ALIGN_MIDDLE BOTTOM:0,VERTICAL_ALIGN_BOTTOM TEXT_BOTTOM:0,VERTICAL_ALIGN_TEXT_BOTTOM IDENT:) LENGTH_UNIT:( UNIT_PX:VERTICAL_ALIGN_SET MASK:UNIT_MASK_VERTICAL_ALIGN LENGTH_UNIT:) CALC:( UNIT_PX:VERTICAL_ALIGN_CALC CALC:)
visibility:CSS_PROP_VISIBILITY IDENT:( INHERIT: INITIAL: REVERT: UNSET: VISIBLE:0,VISIBILITY_VISIBLE HIDDEN:0,VISIBILITY_HIDDEN COLLAPSE:0,VISIBILITY_COLLAPSE IDENT:)
-volume:CSS_PROP_VOLUME IDENT:( INHERIT: INITIAL: REVERT: UNSET: SILENT:0,VOLUME_SILENT X_SOFT:0,VOLUME_X_SOFT SOFT:0,VOLUME_SOFT MEDIUM:0,VOLUME_MEDIUM LOUD:0,VOLUME_LOUD X_LOUD:0,VOLUME_X_LOUD IDENT:) NUMBER:( false:VOLUME_NUMBER RANGE:num<0||num>F_100 NUMBER:) LENGTH_UNIT:( UNIT_PX:VOLUME_DIMENSION MASK:UNIT_MASK_VOLUME RANGE:<0 LENGTH_UNIT:)
+volume:CSS_PROP_VOLUME IDENT:( INHERIT: INITIAL: REVERT: UNSET: SILENT:0,VOLUME_SILENT X_SOFT:0,VOLUME_X_SOFT SOFT:0,VOLUME_SOFT MEDIUM:0,VOLUME_MEDIUM LOUD:0,VOLUME_LOUD X_LOUD:0,VOLUME_X_LOUD IDENT:) NUMBER:( false:VOLUME_NUMBER RANGE:num<0||num>F_100 NUMBER:) LENGTH_UNIT:( UNIT_PX:VOLUME_DIMENSION MASK:UNIT_MASK_VOLUME RANGE:<0 LENGTH_UNIT:) CALC:( ANY:VOLUME_CALC CALC:)
white_space:CSS_PROP_WHITE_SPACE IDENT:( INHERIT: INITIAL: REVERT: UNSET: NORMAL:0,WHITE_SPACE_NORMAL PRE:0,WHITE_SPACE_PRE NOWRAP:0,WHITE_SPACE_NOWRAP PRE_WRAP:0,WHITE_SPACE_PRE_WRAP PRE_LINE:0,WHITE_SPACE_PRE_LINE IDENT:)
-widows:CSS_PROP_WIDOWS IDENT:( INHERIT: INITIAL: REVERT: UNSET: IDENT:) NUMBER:( true:WIDOWS_SET RANGE:num<0 NUMBER:)
-
-
-width:CSS_PROP_WIDTH IDENT:( INHERIT: INITIAL: REVERT: UNSET: AUTO:0,WIDTH_AUTO IDENT:) LENGTH_UNIT:( UNIT_PX:WIDTH_SET MASK:UNIT_MASK_WIDTH RANGE:<0 LENGTH_UNIT:)
+widows:CSS_PROP_WIDOWS IDENT:( INHERIT: INITIAL: REVERT: UNSET: IDENT:) NUMBER:( true:WIDOWS_SET RANGE:num<0 NUMBER:) CALC:( NUMBER:WIDOWS_CALC CALC:)
-word_spacing:CSS_PROP_WORD_SPACING IDENT:( INHERIT: INITIAL: REVERT: UNSET: NORMAL:0,WORD_SPACING_NORMAL IDENT:) LENGTH_UNIT:( UNIT_PX:WORD_SPACING_SET MASK:UNIT_MASK_WORD_SPACING LENGTH_UNIT:)
+width:CSS_PROP_WIDTH IDENT:( INHERIT: INITIAL: REVERT: UNSET: AUTO:0,WIDTH_AUTO IDENT:) LENGTH_UNIT:( UNIT_PX:WIDTH_SET MASK:UNIT_MASK_WIDTH RANGE:<0 LENGTH_UNIT:) CALC:( UNIT_PX:WIDTH_CALC CALC:)
-z_index:CSS_PROP_Z_INDEX IDENT:( INHERIT: INITIAL: REVERT: UNSET: AUTO:0,Z_INDEX_AUTO IDENT:) NUMBER:( true:Z_INDEX_SET NUMBER:)
+word_spacing:CSS_PROP_WORD_SPACING IDENT:( INHERIT: INITIAL: REVERT: UNSET: NORMAL:0,WORD_SPACING_NORMAL IDENT:) LENGTH_UNIT:( UNIT_PX:WORD_SPACING_SET MASK:UNIT_MASK_WORD_SPACING LENGTH_UNIT:) CALC:( UNIT_PX:WORD_SPACING_CALC CALC:)
+z_index:CSS_PROP_Z_INDEX IDENT:( INHERIT: INITIAL: REVERT: UNSET: AUTO:0,Z_INDEX_AUTO IDENT:) NUMBER:( true:Z_INDEX_SET NUMBER:) CALC:( NUMBER:Z_INDEX_CALC CALC:)
break_after:CSS_PROP_BREAK_AFTER IDENT:( INHERIT: INITIAL: REVERT: UNSET: AUTO:0,BREAK_AFTER_AUTO ALWAYS:0,BREAK_AFTER_ALWAYS AVOID:0,BREAK_AFTER_AVOID LEFT:0,BREAK_AFTER_LEFT RIGHT:0,BREAK_AFTER_RIGHT PAGE:0,BREAK_AFTER_PAGE COLUMN:0,BREAK_AFTER_COLUMN AVOID_PAGE:0,BREAK_AFTER_AVOID_PAGE AVOID_COLUMN:0,BREAK_AFTER_AVOID_COLUMN IDENT:)
@@ -198,11 +202,11 @@ break_before:CSS_PROP_BREAK_BEFORE IDENT:( INHERIT: INITIAL: REVERT: UNSET: AUTO
break_inside:CSS_PROP_BREAK_INSIDE IDENT:( INHERIT: INITIAL: REVERT: UNSET: AUTO:0,BREAK_INSIDE_AUTO AVOID:0,BREAK_INSIDE_AVOID AVOID_PAGE:0,BREAK_INSIDE_AVOID_PAGE AVOID_COLUMN:0,BREAK_INSIDE_AVOID_COLUMN IDENT:)
-column_count:CSS_PROP_COLUMN_COUNT IDENT:( INHERIT: INITIAL: REVERT: UNSET: AUTO:0,COLUMN_COUNT_AUTO IDENT:) NUMBER:( true:COLUMN_COUNT_SET RANGE:num<0 NUMBER:)
+column_count:CSS_PROP_COLUMN_COUNT IDENT:( INHERIT: INITIAL: REVERT: UNSET: AUTO:0,COLUMN_COUNT_AUTO IDENT:) NUMBER:( true:COLUMN_COUNT_SET RANGE:num<0 NUMBER:) CALC:( NUMBER:COLUMN_COUNT_CALC CALC:)
column_fill:CSS_PROP_COLUMN_FILL IDENT:( INHERIT: INITIAL: REVERT: UNSET: BALANCE:0,COLUMN_FILL_BALANCE AUTO:0,COLUMN_FILL_AUTO IDENT:)
-column_gap:CSS_PROP_COLUMN_GAP IDENT:( INHERIT: INITIAL: REVERT: UNSET: NORMAL:0,COLUMN_GAP_NORMAL IDENT:) LENGTH_UNIT:( UNIT_PX:COLUMN_GAP_SET RANGE:<0 MASK:UNIT_MASK_COLUMN_GAP LENGTH_UNIT:)
+column_gap:CSS_PROP_COLUMN_GAP IDENT:( INHERIT: INITIAL: REVERT: UNSET: NORMAL:0,COLUMN_GAP_NORMAL IDENT:) LENGTH_UNIT:( UNIT_PX:COLUMN_GAP_SET RANGE:<0 MASK:UNIT_MASK_COLUMN_GAP LENGTH_UNIT:) CALC:( UNIT_PX:COLUMN_GAP_CALC CALC:)
column_rule_color:CSS_PROP_COLUMN_RULE_COLOR IDENT:( INHERIT: INITIAL: REVERT: UNSET: IDENT:) COLOR:COLUMN_RULE_COLOR_SET
@@ -212,7 +216,7 @@ column_rule_width:CSS_PROP_COLUMN_RULE_WIDTH WRAP:css__parse_border_side_width
column_span:CSS_PROP_COLUMN_SPAN IDENT:( INHERIT: INITIAL: REVERT: UNSET: NONE:0,COLUMN_SPAN_NONE ALL:0,COLUMN_SPAN_ALL IDENT:)
-column_width:CSS_PROP_COLUMN_WIDTH IDENT:( INHERIT: INITIAL: REVERT: UNSET: AUTO:0,COLUMN_WIDTH_AUTO IDENT:) LENGTH_UNIT:( UNIT_PX:COLUMN_WIDTH_SET MASK:UNIT_MASK_COLUMN_WIDTH LENGTH_UNIT:)
+column_width:CSS_PROP_COLUMN_WIDTH IDENT:( INHERIT: INITIAL: REVERT: UNSET: AUTO:0,COLUMN_WIDTH_AUTO IDENT:) LENGTH_UNIT:( UNIT_PX:COLUMN_WIDTH_SET MASK:UNIT_MASK_COLUMN_WIDTH LENGTH_UNIT:) CALC:( UNIT_PX:COLUMN_WIDTH_CALC CALC:)
writing_mode:CSS_PROP_WRITING_MODE IDENT:( INHERIT: INITIAL: REVERT: UNSET: HORIZONTAL_TB:0,WRITING_MODE_HORIZONTAL_TB VERTICAL_RL:0,WRITING_MODE_VERTICAL_RL VERTICAL_LR:0,WRITING_MODE_VERTICAL_LR IDENT:)
@@ -224,16 +228,16 @@ align_items:CSS_PROP_ALIGN_ITEMS IDENT:( INHERIT: INITIAL: REVERT: UNSET: STRETC
align_self:CSS_PROP_ALIGN_SELF IDENT:( INHERIT: INITIAL: REVERT: UNSET: STRETCH:0,ALIGN_SELF_STRETCH FLEX_START:0,ALIGN_SELF_FLEX_START FLEX_END:0,ALIGN_SELF_FLEX_END CENTER:0,ALIGN_SELF_CENTER BASELINE:0,ALIGN_SELF_BASELINE AUTO:0,ALIGN_SELF_AUTO IDENT:)
-flex_basis:CSS_PROP_FLEX_BASIS IDENT:( INHERIT: INITIAL: REVERT: UNSET: AUTO:0,FLEX_BASIS_AUTO CONTENT:0,FLEX_BASIS_CONTENT IDENT:) LENGTH_UNIT:( UNIT_PX:FLEX_BASIS_SET MASK:UNIT_MASK_FLEX_BASIS RANGE:<0 LENGTH_UNIT:)
+flex_basis:CSS_PROP_FLEX_BASIS IDENT:( INHERIT: INITIAL: REVERT: UNSET: AUTO:0,FLEX_BASIS_AUTO CONTENT:0,FLEX_BASIS_CONTENT IDENT:) LENGTH_UNIT:( UNIT_PX:FLEX_BASIS_SET MASK:UNIT_MASK_FLEX_BASIS RANGE:<0 LENGTH_UNIT:) CALC:( UNIT_PX:FLEX_BASIS_CALC CALC:)
flex_direction:CSS_PROP_FLEX_DIRECTION IDENT:( INHERIT: INITIAL: REVERT: UNSET: ROW:0,FLEX_DIRECTION_ROW ROW_REVERSE:0,FLEX_DIRECTION_ROW_REVERSE COLUMN:0,FLEX_DIRECTION_COLUMN COLUMN_REVERSE:0,FLEX_DIRECTION_COLUMN_REVERSE IDENT:)
-flex_grow:CSS_PROP_FLEX_GROW IDENT:( INHERIT: INITIAL: REVERT: UNSET: IDENT:) NUMBER:( false:FLEX_GROW_SET RANGE:num<0 NUMBER:)
+flex_grow:CSS_PROP_FLEX_GROW IDENT:( INHERIT: INITIAL: REVERT: UNSET: IDENT:) NUMBER:( false:FLEX_GROW_SET RANGE:num<0 NUMBER:) CALC:( NUMBER:FLEX_GROW_CALC CALC:)
-flex_shrink:CSS_PROP_FLEX_SHRINK IDENT:( INHERIT: INITIAL: REVERT: UNSET: IDENT:) NUMBER:( false:FLEX_SHRINK_SET RANGE:num<0 NUMBER:)
+flex_shrink:CSS_PROP_FLEX_SHRINK IDENT:( INHERIT: INITIAL: REVERT: UNSET: IDENT:) NUMBER:( false:FLEX_SHRINK_SET RANGE:num<0 NUMBER:) CALC:( NUMBER:FLEX_SHRINK_CALC CALC:)
flex_wrap:CSS_PROP_FLEX_WRAP IDENT:( INHERIT: INITIAL: REVERT: UNSET: NOWRAP:0,FLEX_WRAP_NOWRAP WRAP_STRING:0,FLEX_WRAP_WRAP WRAP_REVERSE:0,FLEX_WRAP_WRAP_REVERSE IDENT:)
justify_content:CSS_PROP_JUSTIFY_CONTENT IDENT:( INHERIT: INITIAL: REVERT: UNSET: FLEX_START:0,JUSTIFY_CONTENT_FLEX_START FLEX_END:0,JUSTIFY_CONTENT_FLEX_END CENTER:0,JUSTIFY_CONTENT_CENTER SPACE_BETWEEN:0,JUSTIFY_CONTENT_SPACE_BETWEEN SPACE_AROUND:0,JUSTIFY_CONTENT_SPACE_AROUND SPACE_EVENLY:0,JUSTIFY_CONTENT_SPACE_EVENLY IDENT:)
-order:CSS_PROP_ORDER IDENT:( INHERIT: INITIAL: REVERT: UNSET: IDENT:) NUMBER:( true:ORDER_SET NUMBER:)
+order:CSS_PROP_ORDER IDENT:( INHERIT: INITIAL: REVERT: UNSET: IDENT:) NUMBER:( true:ORDER_SET NUMBER:) CALC:( NUMBER:ORDER_CALC CALC:)
diff --git a/src/parse/properties/text_decoration.c b/src/parse/properties/text_decoration.c
index 4849a12..acfda5f 100644
--- a/src/parse/properties/text_decoration.c
+++ b/src/parse/properties/text_decoration.c
@@ -35,7 +35,7 @@ css_error css__parse_text_decoration(css_language *c,
css_error error = CSS_INVALID;
const css_token *token;
enum flag_value flag_value;
- bool match;
+ bool match = false;
/* IDENT([ underline || overline || line-through || blink ])
* | IDENT (none, inherit) */
diff --git a/src/parse/properties/utils.c b/src/parse/properties/utils.c
index e6ab872..5af1695 100644
--- a/src/parse/properties/utils.c
+++ b/src/parse/properties/utils.c
@@ -1333,3 +1333,364 @@ cleanup:
return error;
}
+
+/******************************************************************************/
+
+/* CALC
+ *
+ * calc( <calc-sum> )
+ *
+ * where
+ * <calc-sum> = <calc-product> [ [ '+' | '-' ] <calc-product> ]*
+ *
+ * where
+ * <calc-product> = <calc-value> [ '*' <calc-value> | '/' <number> ]*
+ *
+ * where
+ * <calc-value> = <number> | <dimension> | <percentage> | ( <calc-sum> )
+ *
+ *
+ * Once a calc() expression is parsed, it generates into the bytecode as
+ * an opV where the V is VALUE_IS_CALC, then a unit kind which is the
+ * expected resolved type for the calc, and a string index. The string is
+ * another kind of bytecode, essentially it's a sequence of stack machine
+ * operations which are one of the calc_opcodes enum. They are:
+ *
+ * * CALC_PUSH_NUMBER (N)
+ * - takes a css_fixed and pushes it onto the operand stack
+ * * CALC_PUSH_VALUE (V)
+ * - takes a css_fixed and a unit, and pushes them
+ * * CALC_{ADD,SUBTRACT,MULTIPLY,DIVIDE} (+ - * /)
+ * - pop two values, perform the operation, push the result
+ * * CALC_FINISH (=)
+ * - pop the top value from the stack and return it.
+ *
+ * As an example:
+ *
+ * calc(10px + (4rem / 2)) =>
+ * V 10 px
+ * V 4 rem
+ * N 2
+ * /
+ * +
+ * =
+ */
+
+static css_error
+css__parse_calc_sum(css_language *c,
+ enum css_properties_e property,
+ const parserutils_vector *vector, int *ctx,
+ parserutils_buffer *result);
+
+static css_error
+css__parse_calc_number(
+ const parserutils_vector *vector, int *ctx,
+ parserutils_buffer *result)
+{
+ const css_token *token;
+ css_fixed num;
+ size_t consumed;
+ css_code_t push = CALC_PUSH_NUMBER;
+
+ /* Consume the number token */
+ token = parserutils_vector_iterate(vector, ctx);
+ if (token == NULL || token->type != CSS_TOKEN_NUMBER) {
+ return CSS_INVALID;
+ }
+
+ num = css__number_from_string((const uint8_t *)lwc_string_data(token->idata),
+ lwc_string_length(token->idata), false, &consumed);
+
+ if (consumed != lwc_string_length(token->idata)) {
+ return CSS_INVALID;
+ }
+
+ return css_error_from_parserutils_error(
+ parserutils_buffer_appendv(result, 2,
+ &push, sizeof(push),
+ &num, sizeof(num)
+ )
+ );
+}
+
+static css_error
+css__parse_calc_value(css_language *c,
+ enum css_properties_e property,
+ const parserutils_vector *vector, int *ctx,
+ parserutils_buffer *result)
+{
+ css_error error;
+ int orig_ctx = *ctx;
+ const css_token *token;
+
+ /* 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);
+ consumeWhitespace(vector, ctx);
+ error = css__parse_calc_sum(c, property, vector, ctx, result);
+ if (error != CSS_OK) {
+ return error;
+ }
+
+ token = parserutils_vector_peek(vector, *ctx);
+ 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:
+ error = css__parse_calc_number(vector, ctx, result);
+ if (error != CSS_OK) {
+ return error;
+ }
+ break;
+ case CSS_TOKEN_DIMENSION: /* Fall through */
+ case CSS_TOKEN_PERCENTAGE:
+ {
+ css_fixed length = 0;
+ uint32_t unit = 0;
+ css_code_t push = CALC_PUSH_VALUE;
+ *ctx = orig_ctx;
+
+ error = css__parse_unit_specifier(c, vector, ctx, UNIT_CALC_NUMBER, &length, &unit);
+ if (error != CSS_OK) {
+ *ctx = orig_ctx;
+ return error;
+ }
+
+ if (!(unit & property_unit_mask[property])) {
+ /* This unit is not valid for this property. */
+ return CSS_INVALID;
+ }
+
+ error = css_error_from_parserutils_error(
+ parserutils_buffer_appendv(result, 3,
+ &push, sizeof(push),
+ &length, sizeof(length),
+ &unit, sizeof(unit)
+ )
+ );
+
+ }
+ break;
+
+ default:
+ error = CSS_INVALID;
+ break;
+ }
+
+ consumeWhitespace(vector, ctx);
+ return error;
+}
+
+/* Both this, and css_parse_calc_sum must stop when it encounters a close-paren.
+ * If it hasn't had any useful tokens before that, it's an error. It does not
+ * need to restore ctx before returning an error but it does need to ensure that
+ * the close paren has not been consumed
+ */
+static css_error
+css__parse_calc_product(css_language *c,
+ enum css_properties_e property,
+ const parserutils_vector *vector, int *ctx,
+ parserutils_buffer *result)
+{
+ css_error error = CSS_OK;
+ const css_token *token;
+ css_code_t operator;
+
+ /* First parse a value */
+ error = css__parse_calc_value(c, property, vector, ctx, result);
+ if (error != CSS_OK) {
+ return error;
+ }
+
+ do {
+ /* What is our next token? */
+ token = parserutils_vector_peek(vector, *ctx);
+ if (token == NULL) {
+ error = CSS_INVALID;
+ break;
+ } else if (
+ tokenIsChar(token, ')') ||
+ tokenIsChar(token, '+') ||
+ tokenIsChar(token, '-'))
+ break;
+ else if (tokenIsChar(token, '*'))
+ operator = CALC_MULTIPLY;
+ else if (tokenIsChar(token, '/'))
+ operator = CALC_DIVIDE;
+ else {
+ error = CSS_INVALID;
+ break;
+ }
+ /* Consume that * or / now */
+ parserutils_vector_iterate(vector, ctx);
+
+ consumeWhitespace(vector, ctx);
+
+ if (operator == CALC_MULTIPLY) {
+ /* parse another value */
+ error = css__parse_calc_value(c, property, vector,
+ ctx, result);
+ } else {
+ error = css__parse_calc_number(vector, ctx, result);
+ }
+ if (error != CSS_OK)
+ break;
+
+ /* emit the multiplication/division operator */
+ error = css_error_from_parserutils_error(
+ parserutils_buffer_append(result, (const uint8_t *)&operator, sizeof(operator))
+ );
+ } while (1);
+ /* We've fallen off, either we had an error or we're left with ')' */
+ return error;
+}
+
+
+css_error
+css__parse_calc_sum(css_language *c,
+ enum css_properties_e property,
+ const parserutils_vector *vector, int *ctx,
+ parserutils_buffer *result)
+{
+ css_error error = CSS_OK;
+ const css_token *token;
+ css_code_t operator;
+
+ /* First parse a product */
+ error = css__parse_calc_product(c, property, vector, ctx, result);
+ if (error != CSS_OK) {
+ return error;
+ }
+
+ do {
+ /* What is our next token? */
+ token = parserutils_vector_peek(vector, *ctx);
+ if (token == NULL) {
+ error = CSS_INVALID;
+ break;
+ } else if (tokenIsChar(token, ')'))
+ break;
+ else if (tokenIsChar(token, '+'))
+ operator = CALC_ADD;
+ else if (tokenIsChar(token, '-'))
+ operator = CALC_SUBTRACT;
+ else {
+ error = CSS_INVALID;
+ break;
+ }
+ /* Consume that + or - now */
+ parserutils_vector_iterate(vector, ctx);
+ consumeWhitespace(vector, ctx);
+
+ /* parse another product */
+ error = css__parse_calc_product(c, property, vector, ctx, result);
+ if (error != CSS_OK)
+ break;
+
+ /* emit the addition/subtraction operator */
+ error = css_error_from_parserutils_error(
+ parserutils_buffer_append(result, (const uint8_t *)&operator, sizeof(operator))
+ );
+ } while (1);
+ /* We've fallen off, either we had an error or we're left with ')' */
+ return error;
+}
+
+/* Documented in utils.h */
+css_error css__parse_calc(css_language *c,
+ const parserutils_vector *vector, int *ctx,
+ css_style *result,
+ css_code_t OPV,
+ uint32_t unit)
+{
+ int orig_ctx = *ctx;
+ const css_token *token;
+ css_error error = CSS_OK;
+ css_style *calc_style = NULL;
+ parserutils_buffer *calc_buffer = NULL;
+ lwc_string *calc_expr = NULL;
+ uint32_t expr_index = 0;
+ css_code_t finish = CALC_FINISH;
+ enum css_properties_e property = getOpcode(OPV);
+
+ consumeWhitespace(vector, ctx);
+
+ token = parserutils_vector_peek(vector, *ctx);
+ if (token == NULL) {
+ *ctx = orig_ctx;
+ return CSS_INVALID;
+ }
+
+ if (parserutils_buffer_create(&calc_buffer) != PARSERUTILS_OK) {
+ /* Since &calc_buffer is valid, the only error case is NONMEM */
+ *ctx = orig_ctx;
+ return CSS_NOMEM;
+ }
+
+ error = css__stylesheet_style_create(c->sheet, &calc_style);
+ if (error != CSS_OK)
+ goto cleanup;
+
+ error = css__stylesheet_style_append(calc_style, OPV);
+ if (error != CSS_OK)
+ 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, property, vector, ctx, calc_buffer);
+ if (error != CSS_OK)
+ goto cleanup;
+
+ consumeWhitespace(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;
+ }
+
+ /* Append the indicator that the calc is finished */
+ error = css_error_from_parserutils_error(
+ parserutils_buffer_append(calc_buffer, (const uint8_t *)&finish, sizeof(finish))
+ );
+ if (error != CSS_OK)
+ goto cleanup;
+
+ /* Swallow that close paren */
+ parserutils_vector_iterate(vector, ctx);
+
+ /* Create the lwc string representing the calculation and store it in */
+ error = css_error_from_lwc_error(
+ lwc_intern_string((const char *)calc_buffer->data, calc_buffer->length, &calc_expr)
+ );
+ if (error != CSS_OK)
+ goto cleanup;
+
+ /* This always takes ownership of calc_expr, so we should not use after this */
+ error = css__stylesheet_string_add(calc_style->sheet, calc_expr, &expr_index);
+ if (error != CSS_OK)
+ goto cleanup;
+
+ error = css__stylesheet_style_append(calc_style,
+ (css_code_t) expr_index);
+ if (error != CSS_OK) {
+ goto cleanup;
+ }
+
+ error = css__stylesheet_merge_style(result, calc_style);
+cleanup:
+ css__stylesheet_style_destroy(calc_style);
+ parserutils_buffer_destroy(calc_buffer);
+ /* We do not need to clean up calc_expr, it will never leak */
+ if (error != CSS_OK) {
+ *ctx = orig_ctx;
+ }
+
+ return error;
+}
diff --git a/src/parse/properties/utils.h b/src/parse/properties/utils.h
index aab14e8..a079f35 100644
--- a/src/parse/properties/utils.h
+++ b/src/parse/properties/utils.h
@@ -228,4 +228,28 @@ css_error css__comma_list_to_style(css_language *c,
bool first),
css_style *result);
+/**
+ * Parse a CSS calc() invocation
+ *
+ * Calc can generate a number of kinds of units, so we have to tell the
+ * parser the kind of unit we're aiming for (e.g. UNIT_PX, UNIT_ANGLE, etc.)
+ *
+ * \param[in] c Parsing context
+ * \param[in] vector Vector of tokens to process
+ * \param[in] ctx Pointer to vector iteration context
+ * \param[in] result Pointer to location to receive resulting style
+ * \param[in] OPV The CSS property we are calculating for
+ * \param[in] unit The kind of unit which we want to come out of this calc()
+ * \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 css__parse_calc(css_language *c,
+ const parserutils_vector *vector, int *ctx,
+ css_style *result,
+ css_code_t OPV,
+ uint32_t unit);
#endif