1 /*
2 * This file is part of LibCSS.
3 * Licensed under the MIT License,
4 * http://www.opensource.org/licenses/mit-license.php
5 * Copyright 2009 John-Mark Bell <jmb@netsurf-browser.org>
6 */
7
8 #include <assert.h>
9 #include <string.h>
10
11 #include "bytecode/bytecode.h"
12 #include "bytecode/opcodes.h"
13 #include "parse/properties/properties.h"
14 #include "parse/properties/utils.h"
15
16 /**
17 * Parse quotes
18 *
19 * \param c Parsing context
20 * \param vector Vector of tokens to process
21 * \param ctx Pointer to vector iteration context
22 * \param result Pointer to location to receive resulting style
23 * \return CSS_OK on success,
24 * CSS_NOMEM on memory exhaustion,
25 * CSS_INVALID if the input is not valid
26 *
27 * Post condition: \a *ctx is updated with the next token to process
28 * If the input is invalid, then \a *ctx remains unchanged.
29 */
css__parse_quotes(css_language * c,const parserutils_vector * vector,int * ctx,css_style * result)30 css_error css__parse_quotes(css_language *c,
31 const parserutils_vector *vector, int *ctx,
32 css_style *result)
33 {
34 int orig_ctx = *ctx;
35 css_error error = CSS_INVALID;
36 const css_token *token;
37 bool match;
38
39 /* [ STRING STRING ]+ | IDENT(none,inherit) */
40 token = parserutils_vector_iterate(vector, ctx);
41 if ((token == NULL) ||
42 ((token->type != CSS_TOKEN_IDENT) &&
43 (token->type != CSS_TOKEN_STRING))) {
44 *ctx = orig_ctx;
45 return CSS_INVALID;
46 }
47
48 if ((token->type == CSS_TOKEN_IDENT) &&
49 (lwc_string_caseless_isequal(token->idata,
50 c->strings[INHERIT],
51 &match) == lwc_error_ok && match)) {
52 error = css_stylesheet_style_inherit(result, CSS_PROP_QUOTES);
53 } else if ((token->type == CSS_TOKEN_IDENT) &&
54 (lwc_string_caseless_isequal(token->idata,
55 c->strings[NONE],
56 &match) == lwc_error_ok && match)) {
57 error = css__stylesheet_style_appendOPV(result,
58 CSS_PROP_QUOTES, 0, QUOTES_NONE);
59 } else if (token->type == CSS_TOKEN_STRING) {
60 bool first = true;
61
62 /* Macro to output the value marker, awkward because we need to check
63 * first to determine how the value is constructed.
64 */
65 #define CSS_FIRST_APPEND(CSSVAL) css__stylesheet_style_append(result, first?buildOPV(CSS_PROP_QUOTES, 0, CSSVAL):CSSVAL)
66
67 /* [ STRING STRING ]+ */
68 while ((token != NULL) && (token->type == CSS_TOKEN_STRING)) {
69 uint32_t open_snumber;
70 uint32_t close_snumber;
71
72 error = css__stylesheet_string_add(c->sheet,
73 lwc_string_ref(token->idata),
74 &open_snumber);
75 if (error != CSS_OK)
76 break;
77
78 consumeWhitespace(vector, ctx);
79
80 token = parserutils_vector_iterate(vector, ctx);
81 if ((token == NULL) ||
82 (token->type != CSS_TOKEN_STRING)) {
83 error = CSS_INVALID;
84 break;
85 }
86
87 error = css__stylesheet_string_add(c->sheet,
88 lwc_string_ref(token->idata),
89 &close_snumber);
90 if (error != CSS_OK)
91 break;
92
93 consumeWhitespace(vector, ctx);
94
95 error = CSS_FIRST_APPEND(QUOTES_STRING);
96 if (error != CSS_OK)
97 break;
98
99 error = css__stylesheet_style_append(result, open_snumber);
100 if (error != CSS_OK)
101 break;
102
103 error = css__stylesheet_style_append(result, close_snumber);
104 if (error != CSS_OK)
105 break;
106
107 first = false;
108
109 token = parserutils_vector_peek(vector, *ctx);
110 if (token == NULL || token->type != CSS_TOKEN_STRING)
111 break;
112 token = parserutils_vector_iterate(vector, ctx);
113 }
114
115 if (error == CSS_OK) {
116 /* AddTerminator */
117 error = css__stylesheet_style_append(result, QUOTES_NONE);
118 }
119 } else {
120 error = CSS_INVALID;
121 }
122
123 if (error != CSS_OK)
124 *ctx = orig_ctx;
125
126 return error;
127 }
128