Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3584 sourcerer 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 
6
 */
7
 
8
#include 
9
#include 
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
/**
18
 * Parse content
19
 *
20
 * \param c	  Parsing context
21
 * \param vector  Vector of tokens to process
22
 * \param ctx	  Pointer to vector iteration context
23
 * \param result  Pointer to location to receive resulting style
24
 * \return CSS_OK on success,
25
 *	   CSS_NOMEM on memory exhaustion,
26
 *	   CSS_INVALID if the input is not valid
27
 *
28
 * Post condition: \a *ctx is updated with the next token to process
29
 *		   If the input is invalid, then \a *ctx remains unchanged.
30
 */
31
css_error css__parse_content(css_language *c,
32
		const parserutils_vector *vector, int *ctx,
33
		css_style *result)
34
{
35
	int orig_ctx = *ctx;
36
	css_error error;
37
	const css_token *token;
38
	bool match;
39
 
40
	/* IDENT(normal, none, inherit) | [ ... ]+ */
41
	token = parserutils_vector_iterate(vector, ctx);
42
	if (token == NULL) {
43
		*ctx = orig_ctx;
44
		return CSS_INVALID;
45
	}
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_CONTENT);
53
	} else if ((token->type == CSS_TOKEN_IDENT) &&
54
		   (lwc_string_caseless_isequal(token->idata,
55
						c->strings[NORMAL],
56
						&match) == lwc_error_ok && match)) {
57
		error = css__stylesheet_style_appendOPV(result, CSS_PROP_CONTENT, 0, CONTENT_NORMAL);
58
	} else if ((token->type == CSS_TOKEN_IDENT) &&
59
		   (lwc_string_caseless_isequal(token->idata,
60
						c->strings[NONE],
61
						&match) == lwc_error_ok && match)) {
62
		error = css__stylesheet_style_appendOPV(result, CSS_PROP_CONTENT, 0, CONTENT_NONE);
63
	} else {
64
 
65
/* Macro to output the value marker, awkward because we need to check
66
 * first to determine how the value is constructed.
67
 */
68
#define CSS_APPEND(CSSVAL) css__stylesheet_style_append(result, first?buildOPV(CSS_PROP_CONTENT, 0, CSSVAL):CSSVAL)
69
 
70
		bool first = true;
71
		int prev_ctx = orig_ctx;
72
 
73
		/* [
74
		 *   IDENT(open-quote, close-quote, no-open-quote,
75
		 *         no-close-quote) |
76
		 *   STRING |
77
		 *   URI |
78
		 *   FUNCTION(attr) IDENT ')' |
79
		 *   FUNCTION(counter) IDENT IDENT? ')' |
80
		 *   FUNCTION(counters) IDENT STRING IDENT? ')'
81
		 * ]+
82
		 */
83
 
84
		while (token != NULL) {
85
			if ((token->type == CSS_TOKEN_IDENT) &&
86
			    (lwc_string_caseless_isequal(
87
				    token->idata, c->strings[OPEN_QUOTE],
88
				    &match) == lwc_error_ok && match)) {
89
 
90
				error = CSS_APPEND(CONTENT_OPEN_QUOTE);
91
 
92
			} else if (token->type == CSS_TOKEN_IDENT &&
93
				   (lwc_string_caseless_isequal(
94
					   token->idata, c->strings[CLOSE_QUOTE],
95
					   &match) == lwc_error_ok && match)) {
96
 
97
				error = CSS_APPEND(CONTENT_CLOSE_QUOTE);
98
			} else if (token->type == CSS_TOKEN_IDENT &&
99
				   (lwc_string_caseless_isequal(
100
					   token->idata, c->strings[NO_OPEN_QUOTE],
101
					   &match) == lwc_error_ok && match)) {
102
				error = CSS_APPEND(CONTENT_NO_OPEN_QUOTE);
103
			} else if (token->type == CSS_TOKEN_IDENT &&
104
				   (lwc_string_caseless_isequal(
105
					   token->idata, c->strings[NO_CLOSE_QUOTE],
106
					   &match) == lwc_error_ok && match)) {
107
				error = CSS_APPEND(CONTENT_NO_CLOSE_QUOTE);
108
			} else if (token->type == CSS_TOKEN_STRING) {
109
				uint32_t snumber;
110
 
111
				error = css__stylesheet_string_add(c->sheet, lwc_string_ref(token->idata), &snumber);
112
				if (error != CSS_OK) {
113
					*ctx = orig_ctx;
114
					return error;
115
				}
116
 
117
				error = CSS_APPEND(CONTENT_STRING);
118
				if (error != CSS_OK) {
119
					*ctx = orig_ctx;
120
					return error;
121
				}
122
 
123
				error = css__stylesheet_style_append(result, snumber);
124
			} else if (token->type == CSS_TOKEN_URI) {
125
				lwc_string *uri;
126
				uint32_t uri_snumber;
127
 
128
				error = c->sheet->resolve(c->sheet->resolve_pw,
129
							  c->sheet->url,
130
							  token->idata,
131
							  &uri);
132
				if (error != CSS_OK) {
133
					*ctx = orig_ctx;
134
					return error;
135
				}
136
 
137
				error = css__stylesheet_string_add(c->sheet,
138
								  uri,
139
								  &uri_snumber);
140
				if (error != CSS_OK) {
141
					*ctx = orig_ctx;
142
					return error;
143
				}
144
 
145
				error = CSS_APPEND(CONTENT_URI);
146
				if (error != CSS_OK) {
147
					*ctx = orig_ctx;
148
					return error;
149
				}
150
 
151
				error = css__stylesheet_style_append(result, uri_snumber);
152
			} else if (token->type == CSS_TOKEN_FUNCTION &&
153
				   (lwc_string_caseless_isequal(
154
					   token->idata, c->strings[ATTR],
155
					   &match) == lwc_error_ok && match)) {
156
				uint32_t snumber;
157
 
158
				consumeWhitespace(vector, ctx);
159
 
160
				/* Expect IDENT */
161
				token = parserutils_vector_iterate(vector, ctx);
162
				if (token == NULL || token->type != CSS_TOKEN_IDENT) {
163
					*ctx = orig_ctx;
164
					return CSS_INVALID;
165
				}
166
 
167
				error = css__stylesheet_string_add(c->sheet, lwc_string_ref(token->idata), &snumber);
168
				if (error != CSS_OK) {
169
					*ctx = orig_ctx;
170
					return error;
171
				}
172
 
173
				error = CSS_APPEND(CONTENT_ATTR);
174
				if (error != CSS_OK) {
175
					*ctx = orig_ctx;
176
					return error;
177
				}
178
 
179
				error = css__stylesheet_style_append(result, snumber);
180
 
181
				consumeWhitespace(vector, ctx);
182
 
183
				/* Expect ')' */
184
				token = parserutils_vector_iterate(vector, ctx);
185
				if (token == NULL || tokenIsChar(token, ')') == false) {
186
					*ctx = orig_ctx;
187
					return CSS_INVALID;
188
				}
189
			} else if (token->type == CSS_TOKEN_FUNCTION &&
190
				   (lwc_string_caseless_isequal(
191
					   token->idata, c->strings[COUNTER],
192
					   &match) == lwc_error_ok && match)) {
193
				lwc_string *name;
194
				uint32_t snumber;
195
				uint32_t opv;
196
 
197
				opv = CONTENT_COUNTER;
198
 
199
				consumeWhitespace(vector, ctx);
200
 
201
				/* Expect IDENT */
202
				token = parserutils_vector_iterate(vector, ctx);
203
				if (token == NULL || token->type != CSS_TOKEN_IDENT) {
204
					*ctx = orig_ctx;
205
					return CSS_INVALID;
206
				}
207
 
208
				name = token->idata;
209
 
210
				consumeWhitespace(vector, ctx);
211
 
212
				/* Possible ',' */
213
				token = parserutils_vector_peek(vector, *ctx);
214
				if (token == NULL ||
215
				    (tokenIsChar(token, ',') == false &&
216
				     tokenIsChar(token, ')') == false)) {
217
					*ctx = orig_ctx;
218
					return CSS_INVALID;
219
				}
220
 
221
				if (tokenIsChar(token, ',')) {
222
					uint16_t v;
223
 
224
					parserutils_vector_iterate(vector, ctx);
225
 
226
					consumeWhitespace(vector, ctx);
227
 
228
					/* Expect IDENT */
229
					token = parserutils_vector_peek(vector, *ctx);
230
					if (token == NULL || token->type !=
231
					    CSS_TOKEN_IDENT) {
232
						*ctx = orig_ctx;
233
						return CSS_INVALID;
234
					}
235
 
236
					error = css__parse_list_style_type_value(c, token, &v);
237
					if (error != CSS_OK) {
238
						*ctx = orig_ctx;
239
						return error;
240
					}
241
 
242
					opv |= v << CONTENT_COUNTER_STYLE_SHIFT;
243
 
244
					parserutils_vector_iterate(vector, ctx);
245
 
246
					consumeWhitespace(vector, ctx);
247
				} else {
248
					opv |= LIST_STYLE_TYPE_DECIMAL <<
249
						CONTENT_COUNTER_STYLE_SHIFT;
250
				}
251
 
252
				/* Expect ')' */
253
				token = parserutils_vector_iterate(vector, ctx);
254
				if (token == NULL || tokenIsChar(token,	')') == false) {
255
					*ctx = orig_ctx;
256
					return CSS_INVALID;
257
				}
258
 
259
 
260
				error = css__stylesheet_string_add(c->sheet, lwc_string_ref(name), &snumber);
261
				if (error != CSS_OK) {
262
					*ctx = orig_ctx;
263
					return error;
264
				}
265
 
266
				error = CSS_APPEND(opv);
267
				if (error != CSS_OK) {
268
					*ctx = orig_ctx;
269
					return error;
270
				}
271
 
272
				error = css__stylesheet_style_append(result, snumber);
273
			} else if (token->type == CSS_TOKEN_FUNCTION &&
274
				   (lwc_string_caseless_isequal(
275
					   token->idata, c->strings[COUNTERS],
276
					   &match) == lwc_error_ok && match)) {
277
				lwc_string *name;
278
				lwc_string *sep;
279
				uint32_t name_snumber;
280
				uint32_t sep_snumber;
281
				uint32_t opv;
282
 
283
				opv = CONTENT_COUNTERS;
284
 
285
				consumeWhitespace(vector, ctx);
286
 
287
				/* Expect IDENT */
288
				token = parserutils_vector_iterate(vector, ctx);
289
				if (token == NULL || token->type != CSS_TOKEN_IDENT) {
290
					*ctx = orig_ctx;
291
					return CSS_INVALID;
292
				}
293
 
294
				name = token->idata;
295
 
296
				consumeWhitespace(vector, ctx);
297
 
298
				/* Expect ',' */
299
				token = parserutils_vector_iterate(vector, ctx);
300
				if (token == NULL || tokenIsChar(token, ',') == false) {
301
					*ctx = orig_ctx;
302
					return CSS_INVALID;
303
				}
304
 
305
				consumeWhitespace(vector, ctx);
306
 
307
				/* Expect STRING */
308
				token = parserutils_vector_iterate(vector, ctx);
309
				if (token == NULL || token->type != CSS_TOKEN_STRING) {
310
					*ctx = orig_ctx;
311
					return CSS_INVALID;
312
				}
313
 
314
				sep = token->idata;
315
 
316
				consumeWhitespace(vector, ctx);
317
 
318
				/* Possible ',' */
319
				token = parserutils_vector_peek(vector, *ctx);
320
				if (token == NULL ||
321
				    (tokenIsChar(token, ',') == false &&
322
				     tokenIsChar(token, ')') == false)) {
323
					*ctx = orig_ctx;
324
					return CSS_INVALID;
325
				}
326
 
327
				if (tokenIsChar(token, ',')) {
328
					uint16_t v;
329
 
330
					parserutils_vector_iterate(vector, ctx);
331
 
332
					consumeWhitespace(vector, ctx);
333
 
334
					/* Expect IDENT */
335
					token = parserutils_vector_peek(vector, *ctx);
336
					if (token == NULL || token->type !=
337
					    CSS_TOKEN_IDENT) {
338
						*ctx = orig_ctx;
339
						return CSS_INVALID;
340
					}
341
 
342
					error = css__parse_list_style_type_value(c,
343
									    token, &v);
344
					if (error != CSS_OK) {
345
						*ctx = orig_ctx;
346
						return error;
347
					}
348
 
349
					opv |= v << CONTENT_COUNTERS_STYLE_SHIFT;
350
 
351
					parserutils_vector_iterate(vector, ctx);
352
 
353
					consumeWhitespace(vector, ctx);
354
				} else {
355
					opv |= LIST_STYLE_TYPE_DECIMAL <<
356
						CONTENT_COUNTERS_STYLE_SHIFT;
357
				}
358
 
359
				/* Expect ')' */
360
				token = parserutils_vector_iterate(vector, ctx);
361
				if (token == NULL || tokenIsChar(token, ')') == false) {
362
					*ctx = orig_ctx;
363
					return CSS_INVALID;
364
				}
365
 
366
 
367
				error = css__stylesheet_string_add(c->sheet, lwc_string_ref(name), &name_snumber);
368
				if (error != CSS_OK) {
369
					*ctx = orig_ctx;
370
					return error;
371
				}
372
 
373
				error = css__stylesheet_string_add(c->sheet, lwc_string_ref(sep), &sep_snumber);
374
				if (error != CSS_OK) {
375
					*ctx = orig_ctx;
376
					return error;
377
				}
378
 
379
				error = CSS_APPEND(opv);
380
				if (error != CSS_OK) {
381
					*ctx = orig_ctx;
382
					return error;
383
				}
384
 
385
				error = css__stylesheet_style_append(result, name_snumber);
386
				if (error != CSS_OK) {
387
					*ctx = orig_ctx;
388
					return error;
389
				}
390
 
391
				error = css__stylesheet_style_append(result, sep_snumber);
392
			} else if (first) {
393
				/* Invalid if this is the first iteration */
394
				error = CSS_INVALID;
395
			} else {
396
				/* Give up, ensuring current token is reprocessed */
397
				*ctx = prev_ctx;
398
				error = CSS_OK;
399
				break;
400
			}
401
 
402
			/* if there was an error bail */
403
			if (error != CSS_OK) {
404
				*ctx = orig_ctx;
405
				return error;
406
			}
407
 
408
			first = false;
409
 
410
			consumeWhitespace(vector, ctx);
411
 
412
			prev_ctx = *ctx;
413
			token = parserutils_vector_iterate(vector, ctx);
414
		} /* while */
415
 
416
		/* Write list terminator */
417
		css__stylesheet_style_append(result, CONTENT_NORMAL);
418
	}
419
 
420
	if (error != CSS_OK)
421
		*ctx = orig_ctx;
422
 
423
	return error;
424
}
425