summaryrefslogtreecommitdiff
path: root/source/html/css-parse.c
diff options
context:
space:
mode:
authorTor Andersson <tor.andersson@artifex.com>2015-05-19 17:14:28 +0200
committerTor Andersson <tor.andersson@artifex.com>2015-05-19 17:22:53 +0200
commit02cc7931ef0f04218bd50b3e0e396a6dcb009962 (patch)
tree0c286621e1498561d23bdc543e1852ea88deaf63 /source/html/css-parse.c
parent0dc2cbf8fedd5615898b09314d0c899c6e911baa (diff)
downloadmupdf-02cc7931ef0f04218bd50b3e0e396a6dcb009962.tar.xz
epub: Parse CSS combinators left-associatively.
Fixes bug 695994 where multiple child selectors would not match properly. The "a > b > c" rule should be interpreted as ((a > b) > c) in order to match properly.
Diffstat (limited to 'source/html/css-parse.c')
-rw-r--r--source/html/css-parse.c67
1 files changed, 27 insertions, 40 deletions
diff --git a/source/html/css-parse.c b/source/html/css-parse.c
index 0946043e..f9d7595c 100644
--- a/source/html/css-parse.c
+++ b/source/html/css-parse.c
@@ -776,55 +776,42 @@ static fz_css_selector *parse_simple_selector(struct lexbuf *buf)
fz_css_error(buf, "expected selector");
}
-static fz_css_selector *parse_combinator(struct lexbuf *buf, fz_css_selector *a)
+static fz_css_selector *parse_combinator(struct lexbuf *buf, int c, fz_css_selector *a)
{
- fz_css_selector *s, *b;
- if (accept(buf, '+'))
- {
- white(buf);
- b = parse_selector(buf);
- s = fz_new_css_selector(buf->ctx, NULL);
- s->combine = '+';
- s->left = a;
- s->right = b;
- return s;
- }
- if (accept(buf, '>'))
- {
- white(buf);
- b = parse_selector(buf);
- s = fz_new_css_selector(buf->ctx, NULL);
- s->combine = '>';
- s->left = a;
- s->right = b;
- return s;
- }
- return a;
+ fz_css_selector *sel, *b;
+ white(buf);
+ b = parse_simple_selector(buf);
+ sel = fz_new_css_selector(buf->ctx, NULL);
+ sel->combine = c;
+ sel->left = a;
+ sel->right = b;
+ return sel;
}
static fz_css_selector *parse_selector(struct lexbuf *buf)
{
- fz_css_selector *s, *a, *b;
-
- a = parse_simple_selector(buf);
- if (accept(buf, ' '))
+ fz_css_selector *sel = parse_simple_selector(buf);
+ for (;;)
{
- s = parse_combinator(buf, a);
- if (s == a && buf->lookahead != ',' && buf->lookahead != '{' && buf->lookahead != EOF)
+ if (accept(buf, ' '))
{
- b = parse_selector(buf);
- s = fz_new_css_selector(buf->ctx, NULL);
- s->combine = ' ';
- s->left = a;
- s->right = b;
- return s;
+ if (accept(buf, '+'))
+ sel = parse_combinator(buf, '+', sel);
+ else if (accept(buf, '>'))
+ sel = parse_combinator(buf, '>', sel);
+ else if (buf->lookahead != ',' && buf->lookahead != '{' && buf->lookahead != EOF)
+ sel = parse_combinator(buf, ' ', sel);
+ else
+ break;
}
+ else if (accept(buf, '+'))
+ sel = parse_combinator(buf, '+', sel);
+ else if (accept(buf, '>'))
+ sel = parse_combinator(buf, '>', sel);
+ else
+ break;
}
- else
- {
- s = parse_combinator(buf, a);
- }
- return s;
+ return sel;
}
static fz_css_selector *parse_selector_list(struct lexbuf *buf)