From 9d1482bc78d72ba330c2130170b49b4e18702623 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Mon, 8 Sep 2014 15:49:59 +0200 Subject: html: CSS lexer and parser. --- source/html/css-parse.c | 734 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 734 insertions(+) create mode 100644 source/html/css-parse.c (limited to 'source/html/css-parse.c') diff --git a/source/html/css-parse.c b/source/html/css-parse.c new file mode 100644 index 00000000..5f7fd254 --- /dev/null +++ b/source/html/css-parse.c @@ -0,0 +1,734 @@ +#include "mupdf/fitz.h" +#include "mupdf/html.h" + +struct lexbuf +{ + fz_context *ctx; + const char *s; + int lookahead; + int c; + int color; + int string_len; + char string[1024]; +}; + +static void css_lex_next(struct lexbuf *buf) +{ + // buf->s += fz_chartorune(&buf->c, buf->s); + buf->c = *(buf->s++); +} + +static void css_lex_init(fz_context *ctx, struct lexbuf *buf, const char *s) +{ + buf->ctx = ctx; + buf->s = s; + buf->c = 0; + css_lex_next(buf); + + buf->color = 0; + buf->string_len = 0; +} + +static int iswhite(int c) +{ + return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '\f'; +} + +static int isnmstart(int c) +{ + return c == '\\' || c == '_' || (c >= 'a' && c <= 'z') || + (c >= 128 && c <= 255); +} + +static int isnmchar(int c) +{ + return c == '\\' || c == '_' || (c >= 'a' && c <= 'z') || + (c >= '0' && c <= '9') || c == '-' || (c >= 128 && c <= 255); +} + +static void css_push_char(struct lexbuf *buf, int c) +{ + if (buf->string_len + 1 >= nelem(buf->string)) + fz_throw(buf->ctx, FZ_ERROR_GENERIC, "token too long"); + buf->string[buf->string_len++] = c; +} + +static int css_lex_accept(struct lexbuf *buf, int t) +{ + if (buf->c == t) + { + css_lex_next(buf); + return 1; + } + return 0; +} + +static void css_lex_expect(struct lexbuf *buf, int t) +{ + if (!css_lex_accept(buf, t)) + fz_throw(buf->ctx, FZ_ERROR_GENERIC, "syntax error: expected '%c'", t); +} + +static int ishex(int c, int *v) +{ + if (c >= '0' && c <= '9') + { + *v = c - '0'; + return 1; + } + if (c >= 'A' && c <= 'F') + { + *v = c - 'A' + 0xA; + return 1; + } + if (c >= 'a' && c <= 'f') + { + *v = c - 'a' + 0xA; + return 1; + } + return 0; +} + +static int css_lex_accept_hex(struct lexbuf *buf, int *v) +{ + if (ishex(buf->c, v)) + { + css_lex_next(buf); + return 1; + } + return 0; +} + +static int css_lex_number(struct lexbuf *buf) +{ + while (buf->c >= '0' && buf->c <= '9') + { + css_push_char(buf, buf->c); + css_lex_next(buf); + } + + if (css_lex_accept(buf, '.')) + { + css_push_char(buf, '.'); + while (buf->c >= '0' && buf->c <= '9') + { + css_push_char(buf, buf->c); + css_lex_next(buf); + } + } + + if (css_lex_accept(buf, '%')) + { + css_push_char(buf, '%'); + css_push_char(buf, 0); + return CSS_PERCENT; + } + + if (isnmstart(buf->c)) + { + css_push_char(buf, buf->c); + css_lex_next(buf); + while (isnmchar(buf->c)) + { + css_push_char(buf, buf->c); + css_lex_next(buf); + } + css_push_char(buf, 0); + return CSS_LENGTH; + } + + css_push_char(buf, 0); + return CSS_NUMBER; +} + +static int css_lex_keyword(struct lexbuf *buf) +{ + while (isnmchar(buf->c)) + { + css_push_char(buf, buf->c); + css_lex_next(buf); + } + css_push_char(buf, 0); + return CSS_KEYWORD; +} + +static int css_lex_string(struct lexbuf *buf, int q) +{ + while (buf->c && buf->c != q) + { + if (css_lex_accept(buf, '\\')) + { + if (css_lex_accept(buf, 'n')) + css_push_char(buf, '\n'); + else if (css_lex_accept(buf, 'r')) + css_push_char(buf, '\r'); + else if (css_lex_accept(buf, 'f')) + css_push_char(buf, '\f'); + else if (css_lex_accept(buf, '\f')) + /* line continuation */ ; + else if (css_lex_accept(buf, '\n')) + /* line continuation */ ; + else if (css_lex_accept(buf, '\r')) + css_lex_accept(buf, '\n'); + else + { + css_push_char(buf, buf->c); + css_lex_next(buf); + } + } + else + { + css_push_char(buf, buf->c); + css_lex_next(buf); + } + } + css_lex_expect(buf, q); + css_push_char(buf, 0); + return CSS_STRING; +} + +static int css_lex(struct lexbuf *buf) +{ + int t; + + // TODO: keyword escape sequences + + buf->string_len = 0; + + while (buf->c) + { + while (iswhite(buf->c)) + css_lex_next(buf); + + if (buf->c == 0) + break; + + if (css_lex_accept(buf, '/')) + { + if (css_lex_accept(buf, '*')) + { + while (buf->c) + { + if (css_lex_accept(buf, '*')) + { + while (buf->c == '*') + css_lex_next(buf); + if (css_lex_accept(buf, '/')) + continue; + } + css_lex_next(buf); + } + fz_throw(buf->ctx, FZ_ERROR_GENERIC, "syntax error: unterminated comment"); + } + return '/'; + } + + if (css_lex_accept(buf, '<')) + { + if (css_lex_accept(buf, '!')) + { + css_lex_expect(buf, '-'); + css_lex_expect(buf, '-'); + continue; /* ignore CDO */ + } + return '<'; + } + + if (css_lex_accept(buf, '-')) + { + if (css_lex_accept(buf, '-')) + { + css_lex_expect(buf, '>'); + continue; /* ignore CDC */ + } + if (buf->c >= '0' && buf->c <= '9') + { + css_push_char(buf, '-'); + return css_lex_number(buf); + } + if (isnmstart(buf->c)) + { + css_push_char(buf, '-'); + css_push_char(buf, buf->c); + css_lex_next(buf); + return css_lex_keyword(buf); + } + return '-'; + } + + if (css_lex_accept(buf, '.')) + { + if (buf->c >= '0' && buf->c <= '9') + { + css_push_char(buf, '.'); + return css_lex_number(buf); + } + return '.'; + } + + if (css_lex_accept(buf, '#')) + { + int a, b, c, d, e, f; + if (!css_lex_accept_hex(buf, &a)) goto colorerror; + if (!css_lex_accept_hex(buf, &b)) goto colorerror; + if (!css_lex_accept_hex(buf, &c)) goto colorerror; + if (css_lex_accept_hex(buf, &d)) + { + if (!css_lex_accept_hex(buf, &e)) goto colorerror; + if (!css_lex_accept_hex(buf, &f)) goto colorerror; + buf->color = (a << 20) | (b << 16) | (c << 12) | (d << 8) | (e << 4) | f; + } + else + { + buf->color = (a << 20) | (b << 12) | (c << 4); + } + sprintf(buf->string, "%06x", buf->color); // XXX + return CSS_COLOR; +colorerror: + fz_throw(buf->ctx, FZ_ERROR_GENERIC, "syntax error in color"); + } + + if (css_lex_accept(buf, '"')) + return css_lex_string(buf, '"'); + if (css_lex_accept(buf, '\'')) + return css_lex_string(buf, '\''); + + if (buf->c >= '0' && buf->c <= '9') + return css_lex_number(buf); + + if (css_lex_accept(buf, 'u')) + { + if (css_lex_accept(buf, 'r')) + { + if (css_lex_accept(buf, 'l')) + { + if (css_lex_accept(buf, '(')) + { + // string or url + css_lex_expect(buf, ')'); + return CSS_URI; + } + css_push_char(buf, 'u'); + css_push_char(buf, 'r'); + css_push_char(buf, 'l'); + return css_lex_keyword(buf); + } + css_push_char(buf, 'u'); + css_push_char(buf, 'r'); + return css_lex_keyword(buf); + } + css_push_char(buf, 'u'); + return css_lex_keyword(buf); + } + + if (isnmstart(buf->c)) + { + css_push_char(buf, buf->c); + css_lex_next(buf); + return css_lex_keyword(buf); + } + + t = buf->c; + css_lex_next(buf); + return t; + } + return EOF; +} + +static void next(struct lexbuf *buf) +{ + buf->lookahead = css_lex(buf); +} + +static int accept(struct lexbuf *buf, int t) +{ + if (buf->lookahead == t) + { + next(buf); + return 1; + } + return 0; +} + +static void expect(struct lexbuf *buf, int t) +{ + if (accept(buf, t)) + return; + if (t < 256) + fz_throw(buf->ctx, FZ_ERROR_GENERIC, "syntax error: expected '%c'", t); + else + fz_throw(buf->ctx, FZ_ERROR_GENERIC, "syntax error: unexpected token"); +} + +static int iscond(int t) +{ + return t == ':' || t == '.' || t == '#' || t == '['; +} + +static struct value *parse_value_list(struct lexbuf *buf); + +static struct value *parse_value(struct lexbuf *buf) +{ + struct value *v; + + if (buf->lookahead == CSS_KEYWORD) + { + v = new_value(CSS_KEYWORD, buf->string); + next(buf); + + if (accept(buf, '(')) + { + v->type = '('; + v->args = parse_value_list(buf); + expect(buf, ')'); + } + + return v; + } + + switch (buf->lookahead) + { + case CSS_NUMBER: + case CSS_LENGTH: + case CSS_PERCENT: + case CSS_STRING: + case CSS_COLOR: + case CSS_URI: + v = new_value(buf->lookahead, buf->string); + next(buf); + return v; + } + + if (accept(buf, ',')) + return new_value(',', ","); + if (accept(buf, '/')) + return new_value('/', "/"); + + fz_throw(buf->ctx, FZ_ERROR_GENERIC, "syntax error: expected value"); +} + +static struct value *parse_value_list(struct lexbuf *buf) +{ + struct value *v, *vv; + + vv = NULL; + + while (buf->lookahead != '}' && buf->lookahead != ';' && buf->lookahead != '!' && + buf->lookahead != ')' && buf->lookahead != EOF) + { + v = parse_value(buf); + v->next = vv; + vv = v; + } + + return vv; +} + +static struct property *parse_declaration(struct lexbuf *buf) +{ + struct property *p; + + if (buf->lookahead != CSS_KEYWORD) + fz_throw(buf->ctx, FZ_ERROR_GENERIC, "syntax error: expected keyword in property"); + p = new_property(buf->string, NULL, 0); + next(buf); + + expect(buf, ':'); + + p->value = parse_value_list(buf); + + /* !important */ + if (accept(buf, '!')) + expect(buf, CSS_KEYWORD); + + return p; +} + +static struct property *parse_declaration_list(struct lexbuf *buf) +{ + struct property *p, *pp; + + if (buf->lookahead == '}') + return NULL; + + pp = parse_declaration(buf); + + while (accept(buf, ';')) + { + if (buf->lookahead != '}' && buf->lookahead != ';') + { + p = parse_declaration(buf); + p->next = pp; + pp = p; + } + } + + return pp; +} + +static const char *parse_attrib_value(struct lexbuf *buf) +{ + const char *s; + + if (buf->lookahead == CSS_KEYWORD || buf->lookahead == CSS_STRING) + { + s = strdup(buf->string); + next(buf); + return s; + } + + fz_throw(buf->ctx, FZ_ERROR_GENERIC, "syntax error: expected attribute value"); +} + +static struct condition *parse_condition(struct lexbuf *buf) +{ + struct condition *c; + + if (accept(buf, ':')) + { + if (buf->lookahead != CSS_KEYWORD) + fz_throw(buf->ctx, FZ_ERROR_GENERIC, "syntax error: expected keyword after ':'"); + c = new_condition(':', "pseudo", buf->string); + next(buf); + return c; + } + + if (accept(buf, '.')) + { + if (buf->lookahead != CSS_KEYWORD) + fz_throw(buf->ctx, FZ_ERROR_GENERIC, "syntax error: expected keyword after '.'"); + c = new_condition('.', "class", buf->string); + next(buf); + return c; + } + + if (accept(buf, '#')) + { + if (buf->lookahead != CSS_KEYWORD) + fz_throw(buf->ctx, FZ_ERROR_GENERIC, "syntax error: expected keyword after '#'"); + c = new_condition('#', "id", buf->string); + next(buf); + return c; + } + + if (accept(buf, '[')) + { + if (buf->lookahead != CSS_KEYWORD) + fz_throw(buf->ctx, FZ_ERROR_GENERIC, "syntax error: expected keyword after '['"); + + c = new_condition('[', buf->string, NULL); + next(buf); + + if (accept(buf, '=')) + { + c->type = '='; + c->val = parse_attrib_value(buf); + } + else if (accept(buf, '|')) + { + expect(buf, '='); + c->type = '|'; + c->val = parse_attrib_value(buf); + } + else if (accept(buf, '~')) + { + expect(buf, '='); + c->type = '~'; + c->val = parse_attrib_value(buf); + } + + expect(buf, ']'); + + return c; + } + + fz_throw(buf->ctx, FZ_ERROR_GENERIC, "syntax error: expected condition"); +} + +static struct condition *parse_condition_list(struct lexbuf *buf) +{ + struct condition *c, *cc; + + cc = parse_condition(buf); + while (iscond(buf->lookahead)) + { + c = parse_condition(buf); + c->next = cc; + cc = c; + } + return cc; +} + +static struct selector *parse_simple_selector(struct lexbuf *buf) +{ + struct selector *s; + + if (accept(buf, '*')) + { + s = new_selector(NULL); + if (iscond(buf->lookahead)) + s->cond = parse_condition_list(buf); + return s; + } + else if (buf->lookahead == CSS_KEYWORD) + { + s = new_selector(buf->string); + next(buf); + if (iscond(buf->lookahead)) + s->cond = parse_condition_list(buf); + return s; + } + else if (iscond(buf->lookahead)) + { + s = new_selector(NULL); + s->cond = parse_condition_list(buf); + return s; + } + + fz_throw(buf->ctx, FZ_ERROR_GENERIC, "syntax error: expected selector"); +} + +static struct selector *parse_adjacent_selector(struct lexbuf *buf) +{ + struct selector *s, *a, *b; + + a = parse_simple_selector(buf); + if (accept(buf, '+')) + { + b = parse_adjacent_selector(buf); + s = new_selector(NULL); + s->combine = '>'; + s->left = a; + s->right = b; + return s; + } + return a; +} + +static struct selector *parse_child_selector(struct lexbuf *buf) +{ + struct selector *s, *a, *b; + + a = parse_adjacent_selector(buf); + if (accept(buf, '>')) + { + b = parse_child_selector(buf); + s = new_selector(NULL); + s->combine = '>'; + s->left = a; + s->right = b; + return s; + } + return a; +} + +static struct selector *parse_descendant_selector(struct lexbuf *buf) +{ + struct selector *s, *a, *b; + + a = parse_child_selector(buf); + if (buf->lookahead != ',' && buf->lookahead != '{' && buf->lookahead != EOF) + { + b = parse_descendant_selector(buf); + s = new_selector(NULL); + s->combine = ' '; + s->left = a; + s->right = b; + return s; + } + return a; +} + +static struct selector *parse_selector_list(struct lexbuf *buf) +{ + struct selector *s, *ss; + + ss = parse_descendant_selector(buf); + while (accept(buf, ',')) + { + s = parse_descendant_selector(buf); + s->next = ss; + ss = s; + } + return ss; +} + +static struct rule *parse_rule(struct lexbuf *buf) +{ + struct selector *s; + struct property *p; + + s = parse_selector_list(buf); + expect(buf, '{'); + p = parse_declaration_list(buf); + expect(buf, '}'); + return new_rule(s, p); +} + +static void parse_media_list(struct lexbuf *buf) +{ + struct rule *r; + + while (buf->lookahead != '}' && buf->lookahead != EOF) + { + r = parse_rule(buf); + // TODO: free_rule(r); + } +} + +static void parse_at_rule(struct lexbuf *buf) +{ + struct property *p; + struct value *v; + + expect(buf, CSS_KEYWORD); + if (accept(buf, '{')) /* @page */ + { + p = parse_declaration_list(buf); + // TODO: free_properties(p); + expect(buf, '}'); + } + else + { + v = parse_value_list(buf); + // TODO: free_value_list(v); + if (accept(buf, '{')) /* @media */ + { + parse_media_list(buf); + expect(buf, '}'); + } + else /* @import */ + { + expect(buf, ';'); + } + } +} + +static struct rule *parse_stylesheet(struct lexbuf *buf, struct rule *chain) +{ + struct rule *r; + + while (buf->lookahead != EOF) + { + if (accept(buf, '@')) + { + parse_at_rule(buf); + } + else + { + r = parse_rule(buf); + r->next = chain; + chain = r; + } + } + + return chain; +} + +struct rule *fz_parse_css(fz_context *ctx, struct rule *chain, const char *source) +{ + struct lexbuf buf; + css_lex_init(ctx, &buf, source); + next(&buf); + return parse_stylesheet(&buf, chain); +} -- cgit v1.2.3 From 5cb1a29be4993d72cf6ab2af128135e2b7e40dd2 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Mon, 13 Oct 2014 16:16:28 +0200 Subject: html: Parse inline style attributes. --- source/html/css-parse.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'source/html/css-parse.c') diff --git a/source/html/css-parse.c b/source/html/css-parse.c index 5f7fd254..4ceb10b5 100644 --- a/source/html/css-parse.c +++ b/source/html/css-parse.c @@ -448,14 +448,14 @@ static struct property *parse_declaration_list(struct lexbuf *buf) { struct property *p, *pp; - if (buf->lookahead == '}') + if (buf->lookahead == '}' || buf->lookahead == EOF) return NULL; pp = parse_declaration(buf); while (accept(buf, ';')) { - if (buf->lookahead != '}' && buf->lookahead != ';') + if (buf->lookahead != '}' && buf->lookahead != ';' && buf->lookahead != EOF) { p = parse_declaration(buf); p->next = pp; @@ -725,6 +725,14 @@ static struct rule *parse_stylesheet(struct lexbuf *buf, struct rule *chain) return chain; } +struct property *fz_parse_css_properties(fz_context *ctx, const char *source) +{ + struct lexbuf buf; + css_lex_init(ctx, &buf, source); + next(&buf); + return parse_declaration_list(&buf); +} + struct rule *fz_parse_css(fz_context *ctx, struct rule *chain, const char *source) { struct lexbuf buf; -- cgit v1.2.3 From 5dc64869a5e3bdf851d82ff445b32b609084931b Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Thu, 23 Oct 2014 16:35:51 +0200 Subject: html: Create lists in order when parsing CSS. --- source/html/css-parse.c | 51 +++++++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 23 deletions(-) (limited to 'source/html/css-parse.c') diff --git a/source/html/css-parse.c b/source/html/css-parse.c index 4ceb10b5..066eb0f7 100644 --- a/source/html/css-parse.c +++ b/source/html/css-parse.c @@ -446,24 +446,22 @@ static struct property *parse_declaration(struct lexbuf *buf) static struct property *parse_declaration_list(struct lexbuf *buf) { - struct property *p, *pp; + struct property *head, *tail; if (buf->lookahead == '}' || buf->lookahead == EOF) return NULL; - pp = parse_declaration(buf); + head = tail = parse_declaration(buf); while (accept(buf, ';')) { if (buf->lookahead != '}' && buf->lookahead != ';' && buf->lookahead != EOF) { - p = parse_declaration(buf); - p->next = pp; - pp = p; + tail = tail->next = parse_declaration(buf); } } - return pp; + return head; } static const char *parse_attrib_value(struct lexbuf *buf) @@ -547,16 +545,14 @@ static struct condition *parse_condition(struct lexbuf *buf) static struct condition *parse_condition_list(struct lexbuf *buf) { - struct condition *c, *cc; + struct condition *head, *tail; - cc = parse_condition(buf); + head = tail = parse_condition(buf); while (iscond(buf->lookahead)) { - c = parse_condition(buf); - c->next = cc; - cc = c; + tail = tail->next = parse_condition(buf); } - return cc; + return head; } static struct selector *parse_simple_selector(struct lexbuf *buf) @@ -641,16 +637,14 @@ static struct selector *parse_descendant_selector(struct lexbuf *buf) static struct selector *parse_selector_list(struct lexbuf *buf) { - struct selector *s, *ss; + struct selector *head, *tail; - ss = parse_descendant_selector(buf); + head = tail = parse_descendant_selector(buf); while (accept(buf, ',')) { - s = parse_descendant_selector(buf); - s->next = ss; - ss = s; + tail = tail->next = parse_descendant_selector(buf); } - return ss; + return head; } static struct rule *parse_rule(struct lexbuf *buf) @@ -706,7 +700,19 @@ static void parse_at_rule(struct lexbuf *buf) static struct rule *parse_stylesheet(struct lexbuf *buf, struct rule *chain) { - struct rule *r; + struct rule *rule, **nextp, *tail; + + tail = chain; + if (tail) + { + while (tail->next) + tail = tail->next; + nextp = &tail->next; + } + else + { + nextp = &tail; + } while (buf->lookahead != EOF) { @@ -716,13 +722,12 @@ static struct rule *parse_stylesheet(struct lexbuf *buf, struct rule *chain) } else { - r = parse_rule(buf); - r->next = chain; - chain = r; + rule = *nextp = parse_rule(buf); + nextp = &rule->next; } } - return chain; + return chain ? chain : tail; } struct property *fz_parse_css_properties(fz_context *ctx, const char *source) -- cgit v1.2.3 From b8f932bba1ca5003700a8c6465e6b67bffb5ea38 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Tue, 4 Nov 2014 17:01:19 +0100 Subject: html: Parse white-space property. --- source/html/css-parse.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source/html/css-parse.c') diff --git a/source/html/css-parse.c b/source/html/css-parse.c index 066eb0f7..28176d14 100644 --- a/source/html/css-parse.c +++ b/source/html/css-parse.c @@ -1,4 +1,3 @@ -#include "mupdf/fitz.h" #include "mupdf/html.h" struct lexbuf -- cgit v1.2.3 From 2dca8942c2ad00fefdd95133c2620f318ccde1b2 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Thu, 13 Nov 2014 12:03:28 +0100 Subject: html: Create value lists in the correct order. --- source/html/css-parse.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'source/html/css-parse.c') diff --git a/source/html/css-parse.c b/source/html/css-parse.c index 28176d14..fe91a933 100644 --- a/source/html/css-parse.c +++ b/source/html/css-parse.c @@ -408,19 +408,20 @@ static struct value *parse_value(struct lexbuf *buf) static struct value *parse_value_list(struct lexbuf *buf) { - struct value *v, *vv; + struct value *head, *tail; - vv = NULL; + head = tail = NULL; while (buf->lookahead != '}' && buf->lookahead != ';' && buf->lookahead != '!' && buf->lookahead != ')' && buf->lookahead != EOF) { - v = parse_value(buf); - v->next = vv; - vv = v; + if (!head) + head = tail = parse_value(buf); + else + tail = tail->next = parse_value(buf); } - return vv; + return head; } static struct property *parse_declaration(struct lexbuf *buf) -- cgit v1.2.3 From eea982f2ea75a39a0c1218f528cfaa6678baf263 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Thu, 13 Nov 2014 12:06:46 +0100 Subject: html: Parse external CSS files and basic pagination. Show a translated view of the continuous layout for each page. --- source/html/css-parse.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'source/html/css-parse.c') diff --git a/source/html/css-parse.c b/source/html/css-parse.c index fe91a933..93c5ff58 100644 --- a/source/html/css-parse.c +++ b/source/html/css-parse.c @@ -745,3 +745,30 @@ struct rule *fz_parse_css(fz_context *ctx, struct rule *chain, const char *sourc next(&buf); return parse_stylesheet(&buf, chain); } + +struct rule *fz_parse_css_file(fz_context *ctx, struct rule *chain, const char *filename) +{ + fz_stream *stm = NULL; + fz_buffer *buf = NULL; + + fz_var(buf); + + stm = fz_open_file(ctx, filename); + fz_try(ctx) + { + buf = fz_read_all(stm, 0); + fz_write_buffer_byte(ctx, buf, 0); + chain = fz_parse_css(ctx, chain, buf->data); + } + fz_always(ctx) + { + fz_drop_buffer(ctx, buf); + fz_close(stm); + } + fz_catch(ctx) + { + fz_rethrow(ctx); + } + + return chain; +} -- cgit v1.2.3 From 5ba0b431a80707230c0e7e14c2b4eb520efb3e2d Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Fri, 14 Nov 2014 10:52:55 +0100 Subject: html: Fix CSS parsing mixed-case selectors and comments. --- source/html/css-parse.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source/html/css-parse.c') diff --git a/source/html/css-parse.c b/source/html/css-parse.c index 93c5ff58..63abee42 100644 --- a/source/html/css-parse.c +++ b/source/html/css-parse.c @@ -35,13 +35,13 @@ static int iswhite(int c) static int isnmstart(int c) { - return c == '\\' || c == '_' || (c >= 'a' && c <= 'z') || + return c == '\\' || c == '_' || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= 128 && c <= 255); } static int isnmchar(int c) { - return c == '\\' || c == '_' || (c >= 'a' && c <= 'z') || + return c == '\\' || c == '_' || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '-' || (c >= 128 && c <= 255); } @@ -196,6 +196,7 @@ static int css_lex(struct lexbuf *buf) while (buf->c) { +restart: while (iswhite(buf->c)) css_lex_next(buf); @@ -213,7 +214,7 @@ static int css_lex(struct lexbuf *buf) while (buf->c == '*') css_lex_next(buf); if (css_lex_accept(buf, '/')) - continue; + goto restart; } css_lex_next(buf); } -- cgit v1.2.3 From b3a9f7e5d838e095a5cf4f6d73a73316089190ec Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Fri, 14 Nov 2014 11:15:58 +0100 Subject: html: Only draw the boxes and lines if they're on the current page. --- source/html/css-parse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/html/css-parse.c') diff --git a/source/html/css-parse.c b/source/html/css-parse.c index 63abee42..1708f550 100644 --- a/source/html/css-parse.c +++ b/source/html/css-parse.c @@ -759,7 +759,7 @@ struct rule *fz_parse_css_file(fz_context *ctx, struct rule *chain, const char * { buf = fz_read_all(stm, 0); fz_write_buffer_byte(ctx, buf, 0); - chain = fz_parse_css(ctx, chain, buf->data); + chain = fz_parse_css(ctx, chain, (char*)buf->data); } fz_always(ctx) { -- cgit v1.2.3 From 4860398de42bbaee9bbbdd28ccb16761d5f06e0b Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Mon, 17 Nov 2014 13:49:16 +0100 Subject: html: Fix adjacency selector matching. --- source/html/css-parse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/html/css-parse.c') diff --git a/source/html/css-parse.c b/source/html/css-parse.c index 1708f550..c3ec8431 100644 --- a/source/html/css-parse.c +++ b/source/html/css-parse.c @@ -594,7 +594,7 @@ static struct selector *parse_adjacent_selector(struct lexbuf *buf) { b = parse_adjacent_selector(buf); s = new_selector(NULL); - s->combine = '>'; + s->combine = '+'; s->left = a; s->right = b; return s; -- cgit v1.2.3 From 105d9d938396f867607406167c6e78f18625004d Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Wed, 19 Nov 2014 14:57:18 +0100 Subject: html: Images. --- source/html/css-parse.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'source/html/css-parse.c') diff --git a/source/html/css-parse.c b/source/html/css-parse.c index c3ec8431..d454dbf1 100644 --- a/source/html/css-parse.c +++ b/source/html/css-parse.c @@ -749,22 +749,16 @@ struct rule *fz_parse_css(fz_context *ctx, struct rule *chain, const char *sourc struct rule *fz_parse_css_file(fz_context *ctx, struct rule *chain, const char *filename) { - fz_stream *stm = NULL; - fz_buffer *buf = NULL; + fz_buffer *buf = fz_read_file(ctx, filename); - fz_var(buf); - - stm = fz_open_file(ctx, filename); fz_try(ctx) { - buf = fz_read_all(stm, 0); fz_write_buffer_byte(ctx, buf, 0); chain = fz_parse_css(ctx, chain, (char*)buf->data); } fz_always(ctx) { fz_drop_buffer(ctx, buf); - fz_close(stm); } fz_catch(ctx) { -- cgit v1.2.3 From a3b0ce19561c42cc165a0c459286100af50ba615 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Wed, 26 Nov 2014 02:23:54 +0100 Subject: html: Some cleaning. --- source/html/css-parse.c | 21 --------------------- 1 file changed, 21 deletions(-) (limited to 'source/html/css-parse.c') diff --git a/source/html/css-parse.c b/source/html/css-parse.c index d454dbf1..d4aa39ec 100644 --- a/source/html/css-parse.c +++ b/source/html/css-parse.c @@ -746,24 +746,3 @@ struct rule *fz_parse_css(fz_context *ctx, struct rule *chain, const char *sourc next(&buf); return parse_stylesheet(&buf, chain); } - -struct rule *fz_parse_css_file(fz_context *ctx, struct rule *chain, const char *filename) -{ - fz_buffer *buf = fz_read_file(ctx, filename); - - fz_try(ctx) - { - fz_write_buffer_byte(ctx, buf, 0); - chain = fz_parse_css(ctx, chain, (char*)buf->data); - } - fz_always(ctx) - { - fz_drop_buffer(ctx, buf); - } - fz_catch(ctx) - { - fz_rethrow(ctx); - } - - return chain; -} -- cgit v1.2.3 From 1d2d217346c246f7283a1274bb7313e41084337b Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Wed, 26 Nov 2014 02:47:36 +0100 Subject: html: Namespace prefix CSS functions. --- source/html/css-parse.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'source/html/css-parse.c') diff --git a/source/html/css-parse.c b/source/html/css-parse.c index d4aa39ec..35d11a1d 100644 --- a/source/html/css-parse.c +++ b/source/html/css-parse.c @@ -373,7 +373,7 @@ static struct value *parse_value(struct lexbuf *buf) if (buf->lookahead == CSS_KEYWORD) { - v = new_value(CSS_KEYWORD, buf->string); + v = fz_new_css_value(buf->ctx, CSS_KEYWORD, buf->string); next(buf); if (accept(buf, '(')) @@ -394,15 +394,15 @@ static struct value *parse_value(struct lexbuf *buf) case CSS_STRING: case CSS_COLOR: case CSS_URI: - v = new_value(buf->lookahead, buf->string); + v = fz_new_css_value(buf->ctx, buf->lookahead, buf->string); next(buf); return v; } if (accept(buf, ',')) - return new_value(',', ","); + return fz_new_css_value(buf->ctx, ',', ","); if (accept(buf, '/')) - return new_value('/', "/"); + return fz_new_css_value(buf->ctx, '/', "/"); fz_throw(buf->ctx, FZ_ERROR_GENERIC, "syntax error: expected value"); } @@ -431,7 +431,7 @@ static struct property *parse_declaration(struct lexbuf *buf) if (buf->lookahead != CSS_KEYWORD) fz_throw(buf->ctx, FZ_ERROR_GENERIC, "syntax error: expected keyword in property"); - p = new_property(buf->string, NULL, 0); + p = fz_new_css_property(buf->ctx, buf->string, NULL, 0); next(buf); expect(buf, ':'); @@ -487,7 +487,7 @@ static struct condition *parse_condition(struct lexbuf *buf) { if (buf->lookahead != CSS_KEYWORD) fz_throw(buf->ctx, FZ_ERROR_GENERIC, "syntax error: expected keyword after ':'"); - c = new_condition(':', "pseudo", buf->string); + c = fz_new_css_condition(buf->ctx, ':', "pseudo", buf->string); next(buf); return c; } @@ -496,7 +496,7 @@ static struct condition *parse_condition(struct lexbuf *buf) { if (buf->lookahead != CSS_KEYWORD) fz_throw(buf->ctx, FZ_ERROR_GENERIC, "syntax error: expected keyword after '.'"); - c = new_condition('.', "class", buf->string); + c = fz_new_css_condition(buf->ctx, '.', "class", buf->string); next(buf); return c; } @@ -505,7 +505,7 @@ static struct condition *parse_condition(struct lexbuf *buf) { if (buf->lookahead != CSS_KEYWORD) fz_throw(buf->ctx, FZ_ERROR_GENERIC, "syntax error: expected keyword after '#'"); - c = new_condition('#', "id", buf->string); + c = fz_new_css_condition(buf->ctx, '#', "id", buf->string); next(buf); return c; } @@ -515,7 +515,7 @@ static struct condition *parse_condition(struct lexbuf *buf) if (buf->lookahead != CSS_KEYWORD) fz_throw(buf->ctx, FZ_ERROR_GENERIC, "syntax error: expected keyword after '['"); - c = new_condition('[', buf->string, NULL); + c = fz_new_css_condition(buf->ctx, '[', buf->string, NULL); next(buf); if (accept(buf, '=')) @@ -562,14 +562,14 @@ static struct selector *parse_simple_selector(struct lexbuf *buf) if (accept(buf, '*')) { - s = new_selector(NULL); + s = fz_new_css_selector(buf->ctx, NULL); if (iscond(buf->lookahead)) s->cond = parse_condition_list(buf); return s; } else if (buf->lookahead == CSS_KEYWORD) { - s = new_selector(buf->string); + s = fz_new_css_selector(buf->ctx, buf->string); next(buf); if (iscond(buf->lookahead)) s->cond = parse_condition_list(buf); @@ -577,7 +577,7 @@ static struct selector *parse_simple_selector(struct lexbuf *buf) } else if (iscond(buf->lookahead)) { - s = new_selector(NULL); + s = fz_new_css_selector(buf->ctx, NULL); s->cond = parse_condition_list(buf); return s; } @@ -593,7 +593,7 @@ static struct selector *parse_adjacent_selector(struct lexbuf *buf) if (accept(buf, '+')) { b = parse_adjacent_selector(buf); - s = new_selector(NULL); + s = fz_new_css_selector(buf->ctx, NULL); s->combine = '+'; s->left = a; s->right = b; @@ -610,7 +610,7 @@ static struct selector *parse_child_selector(struct lexbuf *buf) if (accept(buf, '>')) { b = parse_child_selector(buf); - s = new_selector(NULL); + s = fz_new_css_selector(buf->ctx, NULL); s->combine = '>'; s->left = a; s->right = b; @@ -627,7 +627,7 @@ static struct selector *parse_descendant_selector(struct lexbuf *buf) if (buf->lookahead != ',' && buf->lookahead != '{' && buf->lookahead != EOF) { b = parse_descendant_selector(buf); - s = new_selector(NULL); + s = fz_new_css_selector(buf->ctx, NULL); s->combine = ' '; s->left = a; s->right = b; @@ -657,7 +657,7 @@ static struct rule *parse_rule(struct lexbuf *buf) expect(buf, '{'); p = parse_declaration_list(buf); expect(buf, '}'); - return new_rule(s, p); + return fz_new_css_rule(buf->ctx, s, p); } static void parse_media_list(struct lexbuf *buf) -- cgit v1.2.3 From 8fd13d8825c14b28787a106acb47e1e3ef47d0f4 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Wed, 26 Nov 2014 13:19:26 +0100 Subject: html: Rename rule and style (match) structs. --- source/html/css-parse.c | 66 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 61 insertions(+), 5 deletions(-) (limited to 'source/html/css-parse.c') diff --git a/source/html/css-parse.c b/source/html/css-parse.c index 35d11a1d..fbae49bb 100644 --- a/source/html/css-parse.c +++ b/source/html/css-parse.c @@ -1,5 +1,61 @@ #include "mupdf/html.h" +static fz_css_rule * +fz_new_css_rule(fz_context *ctx, struct selector *selector, struct property *declaration) +{ + fz_css_rule *rule = fz_malloc_struct(ctx, fz_css_rule); + rule->selector = selector; + rule->declaration = declaration; + rule->next = NULL; + return rule; +} + +static struct selector * +fz_new_css_selector(fz_context *ctx, const char *name) +{ + struct selector *sel = fz_malloc_struct(ctx, struct selector); + sel->name = name ? fz_strdup(ctx, name) : NULL; + sel->combine = 0; + sel->cond = NULL; + sel->left = NULL; + sel->right = NULL; + sel->next = NULL; + return sel; +} + +static struct condition * +fz_new_css_condition(fz_context *ctx, int type, const char *key, const char *val) +{ + struct condition *cond = fz_malloc_struct(ctx, struct condition); + cond->type = type; + cond->key = key ? fz_strdup(ctx, key) : NULL; + cond->val = val ? fz_strdup(ctx, val) : NULL; + cond->next = NULL; + return cond; +} + +static struct property * +fz_new_css_property(fz_context *ctx, const char *name, struct value *value, int spec) +{ + struct property *prop = fz_malloc_struct(ctx, struct property); + prop->name = fz_strdup(ctx, name); + prop->value = value; + prop->spec = spec; + prop->next = NULL; + return prop; +} + +static struct value * +fz_new_css_value(fz_context *ctx, int type, const char *data) +{ + struct value *val = fz_malloc_struct(ctx, struct value); + val->type = type; + val->data = fz_strdup(ctx, data); + val->args = NULL; + val->next = NULL; + return val; +} + struct lexbuf { fz_context *ctx; @@ -648,7 +704,7 @@ static struct selector *parse_selector_list(struct lexbuf *buf) return head; } -static struct rule *parse_rule(struct lexbuf *buf) +static fz_css_rule *parse_rule(struct lexbuf *buf) { struct selector *s; struct property *p; @@ -662,7 +718,7 @@ static struct rule *parse_rule(struct lexbuf *buf) static void parse_media_list(struct lexbuf *buf) { - struct rule *r; + fz_css_rule *r; while (buf->lookahead != '}' && buf->lookahead != EOF) { @@ -699,9 +755,9 @@ static void parse_at_rule(struct lexbuf *buf) } } -static struct rule *parse_stylesheet(struct lexbuf *buf, struct rule *chain) +static fz_css_rule *parse_stylesheet(struct lexbuf *buf, fz_css_rule *chain) { - struct rule *rule, **nextp, *tail; + fz_css_rule *rule, **nextp, *tail; tail = chain; if (tail) @@ -739,7 +795,7 @@ struct property *fz_parse_css_properties(fz_context *ctx, const char *source) return parse_declaration_list(&buf); } -struct rule *fz_parse_css(fz_context *ctx, struct rule *chain, const char *source) +fz_css_rule *fz_parse_css(fz_context *ctx, fz_css_rule *chain, const char *source) { struct lexbuf buf; css_lex_init(ctx, &buf, source); -- cgit v1.2.3 From ff7694216fa480c7424b2b6698d08104a7b80e89 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Wed, 26 Nov 2014 13:53:24 +0100 Subject: html: Rename internal css structs. --- source/html/css-parse.c | 101 +++++++++++++++++++++++------------------------- 1 file changed, 48 insertions(+), 53 deletions(-) (limited to 'source/html/css-parse.c') diff --git a/source/html/css-parse.c b/source/html/css-parse.c index fbae49bb..aaf0a623 100644 --- a/source/html/css-parse.c +++ b/source/html/css-parse.c @@ -1,7 +1,17 @@ #include "mupdf/html.h" -static fz_css_rule * -fz_new_css_rule(fz_context *ctx, struct selector *selector, struct property *declaration) +struct lexbuf +{ + fz_context *ctx; + const char *s; + int lookahead; + int c; + int color; + int string_len; + char string[1024]; +}; + +static fz_css_rule *fz_new_css_rule(fz_context *ctx, fz_css_selector *selector, fz_css_property *declaration) { fz_css_rule *rule = fz_malloc_struct(ctx, fz_css_rule); rule->selector = selector; @@ -10,10 +20,9 @@ fz_new_css_rule(fz_context *ctx, struct selector *selector, struct property *dec return rule; } -static struct selector * -fz_new_css_selector(fz_context *ctx, const char *name) +static fz_css_selector *fz_new_css_selector(fz_context *ctx, const char *name) { - struct selector *sel = fz_malloc_struct(ctx, struct selector); + fz_css_selector *sel = fz_malloc_struct(ctx, fz_css_selector); sel->name = name ? fz_strdup(ctx, name) : NULL; sel->combine = 0; sel->cond = NULL; @@ -23,10 +32,9 @@ fz_new_css_selector(fz_context *ctx, const char *name) return sel; } -static struct condition * -fz_new_css_condition(fz_context *ctx, int type, const char *key, const char *val) +static fz_css_condition *fz_new_css_condition(fz_context *ctx, int type, const char *key, const char *val) { - struct condition *cond = fz_malloc_struct(ctx, struct condition); + fz_css_condition *cond = fz_malloc_struct(ctx, fz_css_condition); cond->type = type; cond->key = key ? fz_strdup(ctx, key) : NULL; cond->val = val ? fz_strdup(ctx, val) : NULL; @@ -34,10 +42,9 @@ fz_new_css_condition(fz_context *ctx, int type, const char *key, const char *val return cond; } -static struct property * -fz_new_css_property(fz_context *ctx, const char *name, struct value *value, int spec) +static fz_css_property *fz_new_css_property(fz_context *ctx, const char *name, fz_css_value *value, int spec) { - struct property *prop = fz_malloc_struct(ctx, struct property); + fz_css_property *prop = fz_malloc_struct(ctx, fz_css_property); prop->name = fz_strdup(ctx, name); prop->value = value; prop->spec = spec; @@ -45,10 +52,9 @@ fz_new_css_property(fz_context *ctx, const char *name, struct value *value, int return prop; } -static struct value * -fz_new_css_value(fz_context *ctx, int type, const char *data) +static fz_css_value *fz_new_css_value(fz_context *ctx, int type, const char *data) { - struct value *val = fz_malloc_struct(ctx, struct value); + fz_css_value *val = fz_malloc_struct(ctx, fz_css_value); val->type = type; val->data = fz_strdup(ctx, data); val->args = NULL; @@ -56,17 +62,6 @@ fz_new_css_value(fz_context *ctx, int type, const char *data) return val; } -struct lexbuf -{ - fz_context *ctx; - const char *s; - int lookahead; - int c; - int color; - int string_len; - char string[1024]; -}; - static void css_lex_next(struct lexbuf *buf) { // buf->s += fz_chartorune(&buf->c, buf->s); @@ -421,11 +416,11 @@ static int iscond(int t) return t == ':' || t == '.' || t == '#' || t == '['; } -static struct value *parse_value_list(struct lexbuf *buf); +static fz_css_value *parse_value_list(struct lexbuf *buf); -static struct value *parse_value(struct lexbuf *buf) +static fz_css_value *parse_value(struct lexbuf *buf) { - struct value *v; + fz_css_value *v; if (buf->lookahead == CSS_KEYWORD) { @@ -463,9 +458,9 @@ static struct value *parse_value(struct lexbuf *buf) fz_throw(buf->ctx, FZ_ERROR_GENERIC, "syntax error: expected value"); } -static struct value *parse_value_list(struct lexbuf *buf) +static fz_css_value *parse_value_list(struct lexbuf *buf) { - struct value *head, *tail; + fz_css_value *head, *tail; head = tail = NULL; @@ -481,9 +476,9 @@ static struct value *parse_value_list(struct lexbuf *buf) return head; } -static struct property *parse_declaration(struct lexbuf *buf) +static fz_css_property *parse_declaration(struct lexbuf *buf) { - struct property *p; + fz_css_property *p; if (buf->lookahead != CSS_KEYWORD) fz_throw(buf->ctx, FZ_ERROR_GENERIC, "syntax error: expected keyword in property"); @@ -501,9 +496,9 @@ static struct property *parse_declaration(struct lexbuf *buf) return p; } -static struct property *parse_declaration_list(struct lexbuf *buf) +static fz_css_property *parse_declaration_list(struct lexbuf *buf) { - struct property *head, *tail; + fz_css_property *head, *tail; if (buf->lookahead == '}' || buf->lookahead == EOF) return NULL; @@ -535,9 +530,9 @@ static const char *parse_attrib_value(struct lexbuf *buf) fz_throw(buf->ctx, FZ_ERROR_GENERIC, "syntax error: expected attribute value"); } -static struct condition *parse_condition(struct lexbuf *buf) +static fz_css_condition *parse_condition(struct lexbuf *buf) { - struct condition *c; + fz_css_condition *c; if (accept(buf, ':')) { @@ -600,9 +595,9 @@ static struct condition *parse_condition(struct lexbuf *buf) fz_throw(buf->ctx, FZ_ERROR_GENERIC, "syntax error: expected condition"); } -static struct condition *parse_condition_list(struct lexbuf *buf) +static fz_css_condition *parse_condition_list(struct lexbuf *buf) { - struct condition *head, *tail; + fz_css_condition *head, *tail; head = tail = parse_condition(buf); while (iscond(buf->lookahead)) @@ -612,9 +607,9 @@ static struct condition *parse_condition_list(struct lexbuf *buf) return head; } -static struct selector *parse_simple_selector(struct lexbuf *buf) +static fz_css_selector *parse_simple_selector(struct lexbuf *buf) { - struct selector *s; + fz_css_selector *s; if (accept(buf, '*')) { @@ -641,9 +636,9 @@ static struct selector *parse_simple_selector(struct lexbuf *buf) fz_throw(buf->ctx, FZ_ERROR_GENERIC, "syntax error: expected selector"); } -static struct selector *parse_adjacent_selector(struct lexbuf *buf) +static fz_css_selector *parse_adjacent_selector(struct lexbuf *buf) { - struct selector *s, *a, *b; + fz_css_selector *s, *a, *b; a = parse_simple_selector(buf); if (accept(buf, '+')) @@ -658,9 +653,9 @@ static struct selector *parse_adjacent_selector(struct lexbuf *buf) return a; } -static struct selector *parse_child_selector(struct lexbuf *buf) +static fz_css_selector *parse_child_selector(struct lexbuf *buf) { - struct selector *s, *a, *b; + fz_css_selector *s, *a, *b; a = parse_adjacent_selector(buf); if (accept(buf, '>')) @@ -675,9 +670,9 @@ static struct selector *parse_child_selector(struct lexbuf *buf) return a; } -static struct selector *parse_descendant_selector(struct lexbuf *buf) +static fz_css_selector *parse_descendant_selector(struct lexbuf *buf) { - struct selector *s, *a, *b; + fz_css_selector *s, *a, *b; a = parse_child_selector(buf); if (buf->lookahead != ',' && buf->lookahead != '{' && buf->lookahead != EOF) @@ -692,9 +687,9 @@ static struct selector *parse_descendant_selector(struct lexbuf *buf) return a; } -static struct selector *parse_selector_list(struct lexbuf *buf) +static fz_css_selector *parse_selector_list(struct lexbuf *buf) { - struct selector *head, *tail; + fz_css_selector *head, *tail; head = tail = parse_descendant_selector(buf); while (accept(buf, ',')) @@ -706,8 +701,8 @@ static struct selector *parse_selector_list(struct lexbuf *buf) static fz_css_rule *parse_rule(struct lexbuf *buf) { - struct selector *s; - struct property *p; + fz_css_selector *s; + fz_css_property *p; s = parse_selector_list(buf); expect(buf, '{'); @@ -729,8 +724,8 @@ static void parse_media_list(struct lexbuf *buf) static void parse_at_rule(struct lexbuf *buf) { - struct property *p; - struct value *v; + fz_css_property *p; + fz_css_value *v; expect(buf, CSS_KEYWORD); if (accept(buf, '{')) /* @page */ @@ -787,7 +782,7 @@ static fz_css_rule *parse_stylesheet(struct lexbuf *buf, fz_css_rule *chain) return chain ? chain : tail; } -struct property *fz_parse_css_properties(fz_context *ctx, const char *source) +fz_css_property *fz_parse_css_properties(fz_context *ctx, const char *source) { struct lexbuf buf; css_lex_init(ctx, &buf, source); -- cgit v1.2.3 From c4a45e25b92269e9e44594fd410b272718d939bc Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Wed, 26 Nov 2014 16:27:20 +0100 Subject: html: Free css structures. --- source/html/css-parse.c | 74 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 68 insertions(+), 6 deletions(-) (limited to 'source/html/css-parse.c') diff --git a/source/html/css-parse.c b/source/html/css-parse.c index aaf0a623..0b12319f 100644 --- a/source/html/css-parse.c +++ b/source/html/css-parse.c @@ -62,6 +62,68 @@ static fz_css_value *fz_new_css_value(fz_context *ctx, int type, const char *dat return val; } +static void fz_free_css_value(fz_context *ctx, fz_css_value *val) +{ + while (val) + { + fz_css_value *next = val->next; + fz_free_css_value(ctx, val->args); + fz_free(ctx, val->data); + fz_free(ctx, val); + val = next; + } +} + +static void fz_free_css_condition(fz_context *ctx, fz_css_condition *cond) +{ + while (cond) + { + fz_css_condition *next = cond->next; + fz_free(ctx, cond->key); + fz_free(ctx, cond->val); + fz_free(ctx, cond); + cond = next; + } +} + +static void fz_free_css_selector(fz_context *ctx, fz_css_selector *sel) +{ + while (sel) + { + fz_css_selector *next = sel->next; + fz_free(ctx, sel->name); + fz_free_css_condition(ctx, sel->cond); + fz_free_css_selector(ctx, sel->left); + fz_free_css_selector(ctx, sel->right); + fz_free(ctx, sel); + sel = next; + } +} + +static void fz_free_css_property(fz_context *ctx, fz_css_property *prop) +{ + while (prop) + { + fz_css_property *next = prop->next; + fz_free(ctx, prop->name); + fz_free_css_value(ctx, prop->value); + fz_free(ctx, prop); + prop = next; + } +} + +void fz_free_css(fz_context *ctx, fz_css_rule *rule) +{ + while (rule) + { + fz_css_rule *next = rule->next; + fz_free_css_selector(ctx, rule->selector); + fz_free_css_property(ctx, rule->declaration); + fz_free(ctx, rule); + rule = next; + } +} + static void css_lex_next(struct lexbuf *buf) { // buf->s += fz_chartorune(&buf->c, buf->s); @@ -516,13 +578,13 @@ static fz_css_property *parse_declaration_list(struct lexbuf *buf) return head; } -static const char *parse_attrib_value(struct lexbuf *buf) +static char *parse_attrib_value(struct lexbuf *buf) { - const char *s; + char *s; if (buf->lookahead == CSS_KEYWORD || buf->lookahead == CSS_STRING) { - s = strdup(buf->string); + s = fz_strdup(buf->ctx, buf->string); next(buf); return s; } @@ -718,7 +780,7 @@ static void parse_media_list(struct lexbuf *buf) while (buf->lookahead != '}' && buf->lookahead != EOF) { r = parse_rule(buf); - // TODO: free_rule(r); + fz_free_css(buf->ctx, r); } } @@ -731,13 +793,13 @@ static void parse_at_rule(struct lexbuf *buf) if (accept(buf, '{')) /* @page */ { p = parse_declaration_list(buf); - // TODO: free_properties(p); + fz_free_css_property(buf->ctx, p); expect(buf, '}'); } else { v = parse_value_list(buf); - // TODO: free_value_list(v); + fz_free_css_value(buf->ctx, v); if (accept(buf, '{')) /* @media */ { parse_media_list(buf); -- cgit v1.2.3 From f1bfe4b861621ad7554670acf91cb029e4482569 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Wed, 26 Nov 2014 17:26:51 +0100 Subject: html: Free inline style properties at the end. --- source/html/css-parse.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source/html/css-parse.c') diff --git a/source/html/css-parse.c b/source/html/css-parse.c index 0b12319f..a751903d 100644 --- a/source/html/css-parse.c +++ b/source/html/css-parse.c @@ -16,6 +16,7 @@ static fz_css_rule *fz_new_css_rule(fz_context *ctx, fz_css_selector *selector, fz_css_rule *rule = fz_malloc_struct(ctx, fz_css_rule); rule->selector = selector; rule->declaration = declaration; + rule->garbage = NULL; rule->next = NULL; return rule; } @@ -119,6 +120,7 @@ void fz_free_css(fz_context *ctx, fz_css_rule *rule) fz_css_rule *next = rule->next; fz_free_css_selector(ctx, rule->selector); fz_free_css_property(ctx, rule->declaration); + fz_free_css_property(ctx, rule->garbage); fz_free(ctx, rule); rule = next; } -- cgit v1.2.3 From 602146c0c833d7cb41f9d369047e36a2f412f40a Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Thu, 27 Nov 2014 15:55:12 +0100 Subject: html: Record line number and source file for CSS error messages. --- source/html/css-parse.c | 51 ++++++++++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 22 deletions(-) (limited to 'source/html/css-parse.c') diff --git a/source/html/css-parse.c b/source/html/css-parse.c index a751903d..e0bdc616 100644 --- a/source/html/css-parse.c +++ b/source/html/css-parse.c @@ -4,6 +4,8 @@ struct lexbuf { fz_context *ctx; const char *s; + const char *file; + int line; int lookahead; int c; int color; @@ -11,6 +13,11 @@ struct lexbuf char string[1024]; }; +FZ_NORETURN static void fz_css_error(struct lexbuf *buf, const char *msg) +{ + fz_throw(buf->ctx, FZ_ERROR_GENERIC, "css syntax error: %s (%s:%d)", msg, buf->file, buf->line); +} + static fz_css_rule *fz_new_css_rule(fz_context *ctx, fz_css_selector *selector, fz_css_property *declaration) { fz_css_rule *rule = fz_malloc_struct(ctx, fz_css_rule); @@ -128,15 +135,18 @@ void fz_free_css(fz_context *ctx, fz_css_rule *rule) static void css_lex_next(struct lexbuf *buf) { - // buf->s += fz_chartorune(&buf->c, buf->s); buf->c = *(buf->s++); + if (buf->c == '\n') + ++buf->line; } -static void css_lex_init(fz_context *ctx, struct lexbuf *buf, const char *s) +static void css_lex_init(fz_context *ctx, struct lexbuf *buf, const char *s, const char *file, int line) { buf->ctx = ctx; buf->s = s; buf->c = 0; + buf->file = file; + buf->line = line; css_lex_next(buf); buf->color = 0; @@ -163,7 +173,7 @@ static int isnmchar(int c) static void css_push_char(struct lexbuf *buf, int c) { if (buf->string_len + 1 >= nelem(buf->string)) - fz_throw(buf->ctx, FZ_ERROR_GENERIC, "token too long"); + fz_css_error(buf, "token too long"); buf->string[buf->string_len++] = c; } @@ -180,7 +190,7 @@ static int css_lex_accept(struct lexbuf *buf, int t) static void css_lex_expect(struct lexbuf *buf, int t) { if (!css_lex_accept(buf, t)) - fz_throw(buf->ctx, FZ_ERROR_GENERIC, "syntax error: expected '%c'", t); + fz_css_error(buf, "unexpected character"); } static int ishex(int c, int *v) @@ -333,7 +343,7 @@ restart: } css_lex_next(buf); } - fz_throw(buf->ctx, FZ_ERROR_GENERIC, "syntax error: unterminated comment"); + fz_css_error(buf, "unterminated comment"); } return '/'; } @@ -400,7 +410,7 @@ restart: sprintf(buf->string, "%06x", buf->color); // XXX return CSS_COLOR; colorerror: - fz_throw(buf->ctx, FZ_ERROR_GENERIC, "syntax error in color"); + fz_css_error(buf, "invalid color"); } if (css_lex_accept(buf, '"')) @@ -469,10 +479,7 @@ static void expect(struct lexbuf *buf, int t) { if (accept(buf, t)) return; - if (t < 256) - fz_throw(buf->ctx, FZ_ERROR_GENERIC, "syntax error: expected '%c'", t); - else - fz_throw(buf->ctx, FZ_ERROR_GENERIC, "syntax error: unexpected token"); + fz_css_error(buf, "unexpected token"); } static int iscond(int t) @@ -519,7 +526,7 @@ static fz_css_value *parse_value(struct lexbuf *buf) if (accept(buf, '/')) return fz_new_css_value(buf->ctx, '/', "/"); - fz_throw(buf->ctx, FZ_ERROR_GENERIC, "syntax error: expected value"); + fz_css_error(buf, "expected value"); } static fz_css_value *parse_value_list(struct lexbuf *buf) @@ -545,7 +552,7 @@ static fz_css_property *parse_declaration(struct lexbuf *buf) fz_css_property *p; if (buf->lookahead != CSS_KEYWORD) - fz_throw(buf->ctx, FZ_ERROR_GENERIC, "syntax error: expected keyword in property"); + fz_css_error(buf, "expected keyword in property"); p = fz_new_css_property(buf->ctx, buf->string, NULL, 0); next(buf); @@ -591,7 +598,7 @@ static char *parse_attrib_value(struct lexbuf *buf) return s; } - fz_throw(buf->ctx, FZ_ERROR_GENERIC, "syntax error: expected attribute value"); + fz_css_error(buf, "expected attribute value"); } static fz_css_condition *parse_condition(struct lexbuf *buf) @@ -601,7 +608,7 @@ static fz_css_condition *parse_condition(struct lexbuf *buf) if (accept(buf, ':')) { if (buf->lookahead != CSS_KEYWORD) - fz_throw(buf->ctx, FZ_ERROR_GENERIC, "syntax error: expected keyword after ':'"); + fz_css_error(buf, "expected keyword after ':'"); c = fz_new_css_condition(buf->ctx, ':', "pseudo", buf->string); next(buf); return c; @@ -610,7 +617,7 @@ static fz_css_condition *parse_condition(struct lexbuf *buf) if (accept(buf, '.')) { if (buf->lookahead != CSS_KEYWORD) - fz_throw(buf->ctx, FZ_ERROR_GENERIC, "syntax error: expected keyword after '.'"); + fz_css_error(buf, "expected keyword after '.'"); c = fz_new_css_condition(buf->ctx, '.', "class", buf->string); next(buf); return c; @@ -619,7 +626,7 @@ static fz_css_condition *parse_condition(struct lexbuf *buf) if (accept(buf, '#')) { if (buf->lookahead != CSS_KEYWORD) - fz_throw(buf->ctx, FZ_ERROR_GENERIC, "syntax error: expected keyword after '#'"); + fz_css_error(buf, "expected keyword after '#'"); c = fz_new_css_condition(buf->ctx, '#', "id", buf->string); next(buf); return c; @@ -628,7 +635,7 @@ static fz_css_condition *parse_condition(struct lexbuf *buf) if (accept(buf, '[')) { if (buf->lookahead != CSS_KEYWORD) - fz_throw(buf->ctx, FZ_ERROR_GENERIC, "syntax error: expected keyword after '['"); + fz_css_error(buf, "expected keyword after '['"); c = fz_new_css_condition(buf->ctx, '[', buf->string, NULL); next(buf); @@ -656,7 +663,7 @@ static fz_css_condition *parse_condition(struct lexbuf *buf) return c; } - fz_throw(buf->ctx, FZ_ERROR_GENERIC, "syntax error: expected condition"); + fz_css_error(buf, "expected condition"); } static fz_css_condition *parse_condition_list(struct lexbuf *buf) @@ -697,7 +704,7 @@ static fz_css_selector *parse_simple_selector(struct lexbuf *buf) return s; } - fz_throw(buf->ctx, FZ_ERROR_GENERIC, "syntax error: expected selector"); + fz_css_error(buf, "expected selector"); } static fz_css_selector *parse_adjacent_selector(struct lexbuf *buf) @@ -849,15 +856,15 @@ static fz_css_rule *parse_stylesheet(struct lexbuf *buf, fz_css_rule *chain) fz_css_property *fz_parse_css_properties(fz_context *ctx, const char *source) { struct lexbuf buf; - css_lex_init(ctx, &buf, source); + css_lex_init(ctx, &buf, source, "", 1); next(&buf); return parse_declaration_list(&buf); } -fz_css_rule *fz_parse_css(fz_context *ctx, fz_css_rule *chain, const char *source) +fz_css_rule *fz_parse_css(fz_context *ctx, fz_css_rule *chain, const char *source, const char *file, int line) { struct lexbuf buf; - css_lex_init(ctx, &buf, source); + css_lex_init(ctx, &buf, source, file, line); next(&buf); return parse_stylesheet(&buf, chain); } -- cgit v1.2.3 From 71fdae79c38fee74c060cb41eee9b6e1257e1fb6 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Thu, 27 Nov 2014 15:55:51 +0100 Subject: html: Allow +number in CSS syntax. --- source/html/css-parse.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'source/html/css-parse.c') diff --git a/source/html/css-parse.c b/source/html/css-parse.c index e0bdc616..db17e431 100644 --- a/source/html/css-parse.c +++ b/source/html/css-parse.c @@ -381,6 +381,13 @@ restart: return '-'; } + if (css_lex_accept(buf, '+')) + { + if (buf->c >= '0' && buf->c <= '9') + return css_lex_number(buf); + return '+'; + } + if (css_lex_accept(buf, '.')) { if (buf->c >= '0' && buf->c <= '9') -- cgit v1.2.3 From 1cb7f8f9ae768b680477212c678a3111fca71ef7 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Thu, 27 Nov 2014 15:56:06 +0100 Subject: html: Fix parsing of @-rules in CSS. --- source/html/css-parse.c | 48 ++++++++++++++++++------------------------------ 1 file changed, 18 insertions(+), 30 deletions(-) (limited to 'source/html/css-parse.c') diff --git a/source/html/css-parse.c b/source/html/css-parse.c index db17e431..18f33e16 100644 --- a/source/html/css-parse.c +++ b/source/html/css-parse.c @@ -789,42 +789,30 @@ static fz_css_rule *parse_rule(struct lexbuf *buf) return fz_new_css_rule(buf->ctx, s, p); } -static void parse_media_list(struct lexbuf *buf) -{ - fz_css_rule *r; - - while (buf->lookahead != '}' && buf->lookahead != EOF) - { - r = parse_rule(buf); - fz_free_css(buf->ctx, r); - } -} - static void parse_at_rule(struct lexbuf *buf) { - fz_css_property *p; - fz_css_value *v; - expect(buf, CSS_KEYWORD); - if (accept(buf, '{')) /* @page */ - { - p = parse_declaration_list(buf); - fz_free_css_property(buf->ctx, p); - expect(buf, '}'); - } - else + + /* skip until '{' or ';' */ + while (buf->lookahead != EOF) { - v = parse_value_list(buf); - fz_free_css_value(buf->ctx, v); - if (accept(buf, '{')) /* @media */ + if (accept(buf, ';')) + return; + if (accept(buf, '{')) { - parse_media_list(buf); - expect(buf, '}'); - } - else /* @import */ - { - expect(buf, ';'); + int depth = 1; + while (buf->lookahead != EOF && depth > 0) + { + if (accept(buf, '{')) + ++depth; + else if (accept(buf, '}')) + --depth; + else + next(buf); + } + return; } + next(buf); } } -- cgit v1.2.3 From 46c3e7d3731c4e869e8b6b7b1e7f1a1b2d2491cd Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Fri, 28 Nov 2014 11:52:08 +0100 Subject: html: Clean up some naming. --- source/html/css-parse.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source/html/css-parse.c') diff --git a/source/html/css-parse.c b/source/html/css-parse.c index 18f33e16..abe20e74 100644 --- a/source/html/css-parse.c +++ b/source/html/css-parse.c @@ -140,13 +140,13 @@ static void css_lex_next(struct lexbuf *buf) ++buf->line; } -static void css_lex_init(fz_context *ctx, struct lexbuf *buf, const char *s, const char *file, int line) +static void css_lex_init(fz_context *ctx, struct lexbuf *buf, const char *s, const char *file) { buf->ctx = ctx; buf->s = s; buf->c = 0; buf->file = file; - buf->line = line; + buf->line = 1; css_lex_next(buf); buf->color = 0; @@ -851,15 +851,15 @@ static fz_css_rule *parse_stylesheet(struct lexbuf *buf, fz_css_rule *chain) fz_css_property *fz_parse_css_properties(fz_context *ctx, const char *source) { struct lexbuf buf; - css_lex_init(ctx, &buf, source, "", 1); + css_lex_init(ctx, &buf, source, ""); next(&buf); return parse_declaration_list(&buf); } -fz_css_rule *fz_parse_css(fz_context *ctx, fz_css_rule *chain, const char *source, const char *file, int line) +fz_css_rule *fz_parse_css(fz_context *ctx, fz_css_rule *chain, const char *source, const char *file) { struct lexbuf buf; - css_lex_init(ctx, &buf, source, file, line); + css_lex_init(ctx, &buf, source, file); next(&buf); return parse_stylesheet(&buf, chain); } -- cgit v1.2.3