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