Libcroco
cr-parser.c
Go to the documentation of this file.
1 /* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
2 
3 /*
4  * This file is part of The Croco Library
5  *
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of version 2.1 of the
9  * GNU Lesser General Public
10  * License as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20  * USA
21  *
22  * Author: Dodji Seketeli
23  * See COPYRIGHTS file for copyrights information.
24  */
25 
26 /**
27  *@CRParser:
28  *
29  *The definition of the #CRParser class.
30  */
31 
32 #include "string.h"
33 #include "cr-parser.h"
34 #include "cr-num.h"
35 #include "cr-term.h"
36 #include "cr-simple-sel.h"
37 #include "cr-attr-sel.h"
38 
39 /*
40  *Random notes:
41  *CSS core syntax vs CSS level 2 syntax
42  *=====================================
43  *
44  *One must keep in mind
45  *that css UA must comply with two syntaxes.
46  *
47  *1/the specific syntax that defines the css language
48  *for a given level of specificatin (e.g css2 syntax
49  *defined in appendix D.1 of the css2 spec)
50  *
51  *2/the core (general) syntax that is there to allow
52  *UAs to parse style sheets written in levels of CSS that
53  *didn't exist at the time the UAs were created.
54  *
55  *the name of parsing functions (or methods) contained in this file
56  *follows the following scheme: cr_parser_parse_<production_name> (...) ;
57  *where <production_name> is the name
58  *of a production of the css2 language.
59  *When a given production is
60  *defined by the css2 level grammar *and* by the
61  *css core syntax, there will be two functions to parse that production:
62  *one will parse the production defined by the css2 level grammar and the
63  *other will parse the production defined by the css core grammar.
64  *The css2 level grammar related parsing function will be called:
65  *cr_parser_parse_<production_name> (...) ;
66  *Then css core grammar related parsing function will be called:
67  *cr_parser_parse_<production_name>_core (...) ;
68  *
69  *If a production is defined only by the css core grammar, then
70  *it will be named:
71  *cr_parser_parse_<production_name>_core (...) ;
72  */
73 
75 
76 /**
77  *An abstraction of an error reported by by the
78  *parsing routines.
79  */
81  guchar *msg;
83  glong line;
84  glong column;
85  glong byte_num;
86 };
87 
102 } ;
103 
104 /**
105  *The private attributes of
106  *#CRParser.
107  */
109  /**
110  *The tokenizer
111  */
113 
114  /**
115  *The sac handlers to call
116  *to notify the parsing of
117  *the css2 constructions.
118  */
120 
121  /**
122  *A stack of errors reported
123  *by the parsing routines.
124  *Contains instance of #CRParserError.
125  *This pointer is the top of the stack.
126  */
127  GList *err_stack;
128 
130  gboolean resolve_import;
133 };
134 
135 #define PRIVATE(obj) ((obj)->priv)
136 
137 #define CHARS_TAB_SIZE 12
138 
139 /**
140  * IS_NUM:
141  *@a_char: the char to test.
142  *return TRUE if the character is a number ([0-9]), FALSE otherwise
143  */
144 #define IS_NUM(a_char) (((a_char) >= '0' && (a_char) <= '9')?TRUE:FALSE)
145 
146 /**
147  *Checks if 'status' equals CR_OK. If not, goto the 'error' label.
148  *
149  *@param status the status (of type enum CRStatus) to test.
150  *@param is_exception if set to FALSE, the final status returned
151  *by the current function will be CR_PARSING_ERROR. If set to TRUE, the
152  *current status will be the current value of the 'status' variable.
153  *
154  */
155 #define CHECK_PARSING_STATUS(status, is_exception) \
156 if ((status) != CR_OK) \
157 { \
158  if (is_exception == FALSE) \
159  { \
160  status = CR_PARSING_ERROR ; \
161  } \
162  goto error ; \
163 }
164 
165 /**
166  * CHECK_PARSING_STATUS_ERR:
167  *@a_this: the current instance of #CRParser .
168  *@a_status: the status to check. Is of type enum #CRStatus.
169  *@a_is_exception: in case of error, if is TRUE, the status
170  *is set to CR_PARSING_ERROR before goto error. If is false, the
171  *real low level status is kept and will be returned by the
172  *upper level function that called this macro. Usally,this must
173  *be set to FALSE.
174  *
175  *same as CHECK_PARSING_STATUS() but this one pushes an error
176  *on the parser error stack when an error arises.
177  *
178  */
179 #define CHECK_PARSING_STATUS_ERR(a_this, a_status, a_is_exception,\
180  a_err_msg, a_err_status) \
181 if ((a_status) != CR_OK) \
182 { \
183  if (a_is_exception == FALSE) a_status = CR_PARSING_ERROR ; \
184  cr_parser_push_error (a_this, a_err_msg, a_err_status) ; \
185  goto error ; \
186 }
187 
188 /**
189  *Peeks the next char from the input stream of the current parser
190  *by invoking cr_tknzr_input_peek_char().
191  *invokes CHECK_PARSING_STATUS on the status returned by
192  *cr_tknzr_peek_char().
193  *
194  *@param a_this the current instance of #CRParser.
195  *@param a_to_char a pointer to the char where to store the
196  *char peeked.
197  */
198 #define PEEK_NEXT_CHAR(a_this, a_to_char) \
199 {\
200 enum CRStatus pnc_status ; \
201 pnc_status = cr_tknzr_peek_char (PRIVATE (a_this)->tknzr, a_to_char) ; \
202 CHECK_PARSING_STATUS (pnc_status, TRUE) \
203 }
204 
205 /**
206  *Reads the next char from the input stream of the current parser.
207  *In case of error, jumps to the "error:" label located in the
208  *function where this macro is called.
209  *@param a_this the curent instance of #CRParser
210  *@param to_char a pointer to the guint32 char where to store
211  *the character read.
212  */
213 #define READ_NEXT_CHAR(a_this, a_to_char) \
214 status = cr_tknzr_read_char (PRIVATE (a_this)->tknzr, a_to_char) ; \
215 CHECK_PARSING_STATUS (status, TRUE)
216 
217 /**
218  *Gets information about the current position in
219  *the input of the parser.
220  *In case of failure, this macro returns from the
221  *calling function and
222  *returns a status code of type enum #CRStatus.
223  *@param a_this the current instance of #CRParser.
224  *@param a_pos out parameter. A pointer to the position
225  *inside the current parser input. Must
226  */
227 #define RECORD_INITIAL_POS(a_this, a_pos) \
228 status = cr_tknzr_get_cur_pos (PRIVATE \
229 (a_this)->tknzr, a_pos) ; \
230 g_return_val_if_fail (status == CR_OK, status)
231 
232 /**
233  *Gets the address of the current byte inside the
234  *parser input.
235  *@param parser the current instance of #CRParser.
236  *@param addr out parameter a pointer (guchar*)
237  *to where the address must be put.
238  */
239 #define RECORD_CUR_BYTE_ADDR(a_this, a_addr) \
240 status = cr_tknzr_get_cur_byte_addr \
241  (PRIVATE (a_this)->tknzr, a_addr) ; \
242 CHECK_PARSING_STATUS (status, TRUE)
243 
244 /**
245  *Peeks a byte from the topmost parser input at
246  *a given offset from the current position.
247  *If it fails, goto the "error:" label.
248  *
249  *@param a_parser the current instance of #CRParser.
250  *@param a_offset the offset of the byte to peek, the
251  *current byte having the offset '0'.
252  *@param a_byte_ptr out parameter a pointer (guchar*) to
253  *where the peeked char is to be stored.
254  */
255 #define PEEK_BYTE(a_parser, a_offset, a_byte_ptr) \
256 status = cr_tknzr_peek_byte (PRIVATE (a_this)->tknzr, \
257  a_offset, \
258  a_byte_ptr) ; \
259 CHECK_PARSING_STATUS (status, TRUE) ;
260 
261 #define BYTE(a_parser, a_offset, a_eof) \
262 cr_tknzr_peek_byte2 (PRIVATE (a_this)->tknzr, a_offset, a_eof)
263 
264 /**
265  *Reads a byte from the topmost parser input
266  *steam.
267  *If it fails, goto the "error" label.
268  *@param a_this the current instance of #CRParser.
269  *@param a_byte_ptr the guchar * where to put the read char.
270  */
271 #define READ_NEXT_BYTE(a_this, a_byte_ptr) \
272 status = cr_tknzr_read_byte (PRIVATE (a_this)->tknzr, a_byte_ptr) ; \
273 CHECK_PARSING_STATUS (status, TRUE) ;
274 
275 /**
276  *Skips a given number of byte in the topmost
277  *parser input. Don't update line and column number.
278  *In case of error, jumps to the "error:" label
279  *of the surrounding function.
280  *@param a_parser the current instance of #CRParser.
281  *@param a_nb_bytes the number of bytes to skip.
282  */
283 #define SKIP_BYTES(a_this, a_nb_bytes) \
284 status = cr_tknzr_seek_index (PRIVATE (a_this)->tknzr, \
285  CR_SEEK_CUR, a_nb_bytes) ; \
286 CHECK_PARSING_STATUS (status, TRUE) ;
287 
288 /**
289  *Skip utf8 encoded characters.
290  *Updates line and column numbers.
291  *@param a_parser the current instance of #CRParser.
292  *@param a_nb_chars the number of chars to skip. Must be of
293  *type glong.
294  */
295 #define SKIP_CHARS(a_parser, a_nb_chars) \
296 { \
297 glong nb_chars = a_nb_chars ; \
298 status = cr_tknzr_consume_chars \
299  (PRIVATE (a_parser)->tknzr,0, &nb_chars) ; \
300 CHECK_PARSING_STATUS (status, TRUE) ; \
301 }
302 
303 /**
304  *Tests the condition and if it is false, sets
305  *status to "CR_PARSING_ERROR" and goto the 'error'
306  *label.
307  *@param condition the condition to test.
308  */
309 #define ENSURE_PARSING_COND(condition) \
310 if (! (condition)) {status = CR_PARSING_ERROR; goto error ;}
311 
312 #define ENSURE_PARSING_COND_ERR(a_this, a_condition, \
313  a_err_msg, a_err_status) \
314 if (! (a_condition)) \
315 { \
316  status = CR_PARSING_ERROR; \
317  cr_parser_push_error (a_this, a_err_msg, a_err_status) ; \
318  goto error ; \
319 }
320 
321 #define GET_NEXT_TOKEN(a_this, a_token_ptr) \
322 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, \
323  a_token_ptr) ; \
324 ENSURE_PARSING_COND (status == CR_OK) ;
325 
326 #ifdef WITH_UNICODE_ESCAPE_AND_RANGE
327 static enum CRStatus cr_parser_parse_unicode_escape (CRParser * a_this,
328  guint32 * a_unicode);
329 static enum CRStatus cr_parser_parse_escape (CRParser * a_this,
330  guint32 * a_esc_code);
331 
332 static enum CRStatus cr_parser_parse_unicode_range (CRParser * a_this,
333  CRString ** a_inf,
334  CRString ** a_sup);
335 #endif
336 
337 static enum CRStatus cr_parser_parse_stylesheet_core (CRParser * a_this);
338 
339 static enum CRStatus cr_parser_parse_atrule_core (CRParser * a_this);
340 
341 static enum CRStatus cr_parser_parse_ruleset_core (CRParser * a_this);
342 
343 static enum CRStatus cr_parser_parse_selector_core (CRParser * a_this);
344 
345 static enum CRStatus cr_parser_parse_declaration_core (CRParser * a_this);
346 
347 static enum CRStatus cr_parser_parse_any_core (CRParser * a_this);
348 
349 static enum CRStatus cr_parser_parse_block_core (CRParser * a_this);
350 
351 static enum CRStatus cr_parser_parse_value_core (CRParser * a_this);
352 
353 static enum CRStatus cr_parser_parse_string (CRParser * a_this,
354  CRString ** a_str);
355 
356 static enum CRStatus cr_parser_parse_ident (CRParser * a_this,
357  CRString ** a_str);
358 
359 static enum CRStatus cr_parser_parse_uri (CRParser * a_this,
360  CRString ** a_str);
361 
362 static enum CRStatus cr_parser_parse_function (CRParser * a_this,
363  CRString ** a_func_name,
364  CRTerm ** a_expr);
365 static enum CRStatus cr_parser_parse_property (CRParser * a_this,
366  CRString ** a_property);
367 
368 static enum CRStatus cr_parser_parse_attribute_selector (CRParser * a_this,
369  CRAttrSel ** a_sel);
370 
371 static enum CRStatus cr_parser_parse_simple_selector (CRParser * a_this,
372  CRSimpleSel ** a_sel);
373 
374 static enum CRStatus cr_parser_parse_simple_sels (CRParser * a_this,
375  CRSimpleSel ** a_sel);
376 
377 static CRParserError *cr_parser_error_new (const guchar * a_msg,
378  enum CRStatus);
379 
380 static void cr_parser_error_set_msg (CRParserError * a_this,
381  const guchar * a_msg);
382 
383 static void cr_parser_error_dump (CRParserError * a_this);
384 
385 static void cr_parser_error_set_status (CRParserError * a_this,
386  enum CRStatus a_status);
387 
388 static void cr_parser_error_set_pos (CRParserError * a_this,
389  glong a_line,
390  glong a_column, glong a_byte_num);
391 static void
392  cr_parser_error_destroy (CRParserError * a_this);
393 
394 static enum CRStatus cr_parser_push_error (CRParser * a_this,
395  const guchar * a_msg,
396  enum CRStatus a_status);
397 
398 static enum CRStatus cr_parser_dump_err_stack (CRParser * a_this,
399  gboolean a_clear_errs);
400 static enum CRStatus
401  cr_parser_clear_errors (CRParser * a_this);
402 
403 /*****************************
404  *error managemet methods
405  *****************************/
406 
407 /**
408  *Constructor of #CRParserError class.
409  *@param a_msg the brute error message.
410  *@param a_status the error status.
411  *@return the newly built instance of #CRParserError.
412  */
413 static CRParserError *
414 cr_parser_error_new (const guchar * a_msg, enum CRStatus a_status)
415 {
416  CRParserError *result = NULL;
417 
418  result = g_try_malloc (sizeof (CRParserError));
419 
420  if (result == NULL) {
421  cr_utils_trace_info ("Out of memory");
422  return NULL;
423  }
424 
425  memset (result, 0, sizeof (CRParserError));
426 
427  cr_parser_error_set_msg (result, a_msg);
428  cr_parser_error_set_status (result, a_status);
429 
430  return result;
431 }
432 
433 /**
434  *Sets the message associated to this instance of #CRError.
435  *@param a_this the current instance of #CRParserError.
436  *@param a_msg the new message.
437  */
438 static void
439 cr_parser_error_set_msg (CRParserError * a_this, const guchar * a_msg)
440 {
441  g_return_if_fail (a_this);
442 
443  if (a_this->msg) {
444  g_free (a_this->msg);
445  }
446 
447  a_this->msg = (guchar *) g_strdup ((const gchar *) a_msg);
448 }
449 
450 /**
451  *Sets the error status.
452  *@param a_this the current instance of #CRParserError.
453  *@param a_status the new error status.
454  *
455  */
456 static void
457 cr_parser_error_set_status (CRParserError * a_this, enum CRStatus a_status)
458 {
459  g_return_if_fail (a_this);
460 
461  a_this->status = a_status;
462 }
463 
464 /**
465  *Sets the position of the parser error.
466  *@param a_this the current instance of #CRParserError.
467  *@param a_line the line number.
468  *@param a_column the column number.
469  *@param a_byte_num the byte number.
470  */
471 static void
472 cr_parser_error_set_pos (CRParserError * a_this,
473  glong a_line, glong a_column, glong a_byte_num)
474 {
475  g_return_if_fail (a_this);
476 
477  a_this->line = a_line;
478  a_this->column = a_column;
479  a_this->byte_num = a_byte_num;
480 }
481 
482 static void
483 cr_parser_error_dump (CRParserError * a_this)
484 {
485  g_return_if_fail (a_this);
486 
487  g_printerr ("parsing error: %ld:%ld:", a_this->line, a_this->column);
488 
489  g_printerr ("%s\n", a_this->msg);
490 }
491 
492 /**
493  *The destructor of #CRParserError.
494  *@param a_this the current instance of #CRParserError.
495  */
496 static void
497 cr_parser_error_destroy (CRParserError * a_this)
498 {
499  g_return_if_fail (a_this);
500 
501  if (a_this->msg) {
502  g_free (a_this->msg);
503  a_this->msg = NULL;
504  }
505 
506  g_free (a_this);
507 }
508 
509 /**
510  *Pushes an error on the parser error stack.
511  *@param a_this the current instance of #CRParser.
512  *@param a_msg the error message.
513  *@param a_status the error status.
514  *@return CR_OK upon successfull completion, an error code otherwise.
515  */
516 static enum CRStatus
517 cr_parser_push_error (CRParser * a_this,
518  const guchar * a_msg, enum CRStatus a_status)
519 {
520  enum CRStatus status = CR_OK;
521 
522  CRParserError *error = NULL;
523  CRInputPos pos;
524 
525  g_return_val_if_fail (a_this && PRIVATE (a_this)
526  && a_msg, CR_BAD_PARAM_ERROR);
527 
528  error = cr_parser_error_new (a_msg, a_status);
529 
530  g_return_val_if_fail (error, CR_ERROR);
531 
532  RECORD_INITIAL_POS (a_this, &pos);
533 
534  cr_parser_error_set_pos
535  (error, pos.line, pos.col, pos.next_byte_index - 1);
536 
537  PRIVATE (a_this)->err_stack =
538  g_list_prepend (PRIVATE (a_this)->err_stack, error);
539 
540  if (PRIVATE (a_this)->err_stack == NULL)
541  goto error;
542 
543  return CR_OK;
544 
545  error:
546 
547  if (error) {
548  cr_parser_error_destroy (error);
549  error = NULL;
550  }
551 
552  return status;
553 }
554 
555 /**
556  *Dumps the error stack on stdout.
557  *@param a_this the current instance of #CRParser.
558  *@param a_clear_errs whether to clear the error stack
559  *after the dump or not.
560  *@return CR_OK upon successfull completion, an error code
561  *otherwise.
562  */
563 static enum CRStatus
564 cr_parser_dump_err_stack (CRParser * a_this, gboolean a_clear_errs)
565 {
566  GList *cur = NULL;
567 
568  g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
569 
570  if (PRIVATE (a_this)->err_stack == NULL)
571  return CR_OK;
572 
573  for (cur = PRIVATE (a_this)->err_stack; cur; cur = cur->next) {
574  cr_parser_error_dump ((CRParserError *) cur->data);
575  }
576 
577  if (a_clear_errs == TRUE) {
578  cr_parser_clear_errors (a_this);
579  }
580 
581  return CR_OK;
582 }
583 
584 /**
585  *Clears all the errors contained in the parser error stack.
586  *Frees all the errors, and the stack that contains'em.
587  *@param a_this the current instance of #CRParser.
588  */
589 static enum CRStatus
590 cr_parser_clear_errors (CRParser * a_this)
591 {
592  GList *cur = NULL;
593 
594  g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
595 
596  for (cur = PRIVATE (a_this)->err_stack; cur; cur = cur->next) {
597  if (cur->data) {
598  cr_parser_error_destroy ((CRParserError *)
599  cur->data);
600  }
601  }
602 
603  if (PRIVATE (a_this)->err_stack) {
604  g_list_free (PRIVATE (a_this)->err_stack);
605  PRIVATE (a_this)->err_stack = NULL;
606  }
607 
608  return CR_OK;
609 }
610 
611 /**
612  * cr_parser_try_to_skip_spaces_and_comments:
613  *@a_this: the current instance of #CRParser.
614  *
615  *Same as cr_parser_try_to_skip_spaces() but this one skips
616  *spaces and comments.
617  *
618  *Returns CR_OK upon successfull completion, an error code otherwise.
619  */
620 enum CRStatus
622 {
623  enum CRStatus status = CR_ERROR;
624  CRToken *token = NULL;
625 
626  g_return_val_if_fail (a_this && PRIVATE (a_this)
627  && PRIVATE (a_this)->tknzr, CR_BAD_PARAM_ERROR);
628  do {
629  if (token) {
630  cr_token_destroy (token);
631  token = NULL;
632  }
633 
634  status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
635  &token);
636  if (status != CR_OK)
637  goto error;
638  }
639  while ((token != NULL)
640  && (token->type == COMMENT_TK || token->type == S_TK));
641 
642  cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
643 
644  return status;
645 
646  error:
647 
648  if (token) {
649  cr_token_destroy (token);
650  token = NULL;
651  }
652 
653  return status;
654 }
655 
656 /***************************************
657  *End of Parser input handling routines
658  ***************************************/
659 
660 
661 /*************************************
662  *Non trivial terminal productions
663  *parsing routines
664  *************************************/
665 
666 /**
667  *Parses a css stylesheet following the core css grammar.
668  *This is mainly done for test purposes.
669  *During the parsing, no callback is called. This is just
670  *to validate that the stylesheet is well formed according to the
671  *css core syntax.
672  *stylesheet : [ CDO | CDC | S | statement ]*;
673  *@param a_this the current instance of #CRParser.
674  *@return CR_OK upon successful completion, an error code otherwise.
675  */
676 static enum CRStatus
677 cr_parser_parse_stylesheet_core (CRParser * a_this)
678 {
679  CRToken *token = NULL;
680  CRInputPos init_pos;
681  enum CRStatus status = CR_ERROR;
682 
683  g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
684 
685  RECORD_INITIAL_POS (a_this, &init_pos);
686 
687  continue_parsing:
688 
689  if (token) {
690  cr_token_destroy (token);
691  token = NULL;
692  }
693 
695  status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
696  if (status == CR_END_OF_INPUT_ERROR) {
697  status = CR_OK;
698  goto done;
699  } else if (status != CR_OK) {
700  goto error;
701  }
702 
703  switch (token->type) {
704 
705  case CDO_TK:
706  case CDC_TK:
707  goto continue_parsing;
708  break;
709  default:
710  status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
711  token);
712  CHECK_PARSING_STATUS (status, TRUE);
713  token = NULL;
714  status = cr_parser_parse_statement_core (a_this);
715  cr_parser_clear_errors (a_this);
716  if (status == CR_OK) {
717  goto continue_parsing;
718  } else if (status == CR_END_OF_INPUT_ERROR) {
719  goto done;
720  } else {
721  goto error;
722  }
723  }
724 
725  done:
726  if (token) {
727  cr_token_destroy (token);
728  token = NULL;
729  }
730 
731  cr_parser_clear_errors (a_this);
732  return CR_OK;
733 
734  error:
735  cr_parser_push_error
736  (a_this, (const guchar *) "could not recognize next production", CR_ERROR);
737 
738  cr_parser_dump_err_stack (a_this, TRUE);
739 
740  if (token) {
741  cr_token_destroy (token);
742  token = NULL;
743  }
744 
745  cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
746 
747  return status;
748 }
749 
750 /**
751  *Parses an at-rule as defined by the css core grammar
752  *in chapter 4.1 in the css2 spec.
753  *at-rule : ATKEYWORD S* any* [ block | ';' S* ];
754  *@param a_this the current instance of #CRParser.
755  *@return CR_OK upon successfull completion, an error code
756  *otherwise.
757  */
758 static enum CRStatus
759 cr_parser_parse_atrule_core (CRParser * a_this)
760 {
761  CRToken *token = NULL;
762  CRInputPos init_pos;
763  enum CRStatus status = CR_ERROR;
764 
765  g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
766 
767  RECORD_INITIAL_POS (a_this, &init_pos);
768 
769  status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
770  &token);
771  ENSURE_PARSING_COND (status == CR_OK
772  && token
773  &&
774  (token->type == ATKEYWORD_TK
775  || token->type == IMPORT_SYM_TK
776  || token->type == PAGE_SYM_TK
777  || token->type == MEDIA_SYM_TK
778  || token->type == FONT_FACE_SYM_TK
779  || token->type == CHARSET_SYM_TK));
780 
781  cr_token_destroy (token);
782  token = NULL;
783 
785 
786  do {
787  status = cr_parser_parse_any_core (a_this);
788  } while (status == CR_OK);
789 
790  status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
791  &token);
792  ENSURE_PARSING_COND (status == CR_OK && token);
793 
794  if (token->type == CBO_TK) {
795  cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
796  token);
797  token = NULL;
798  status = cr_parser_parse_block_core (a_this);
799  CHECK_PARSING_STATUS (status,
800  FALSE);
801  goto done;
802  } else if (token->type == SEMICOLON_TK) {
803  goto done;
804  } else {
805  status = CR_PARSING_ERROR ;
806  goto error;
807  }
808 
809  done:
810  if (token) {
811  cr_token_destroy (token);
812  token = NULL;
813  }
814  return CR_OK;
815 
816  error:
817  if (token) {
818  cr_token_destroy (token);
819  token = NULL;
820  }
821  cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr,
822  &init_pos);
823  return status;
824 }
825 
826 /**
827  *Parses a ruleset as defined by the css core grammar in chapter
828  *4.1 of the css2 spec.
829  *ruleset ::= selector? '{' S* declaration? [ ';' S* declaration? ]* '}' S*;
830  *@param a_this the current instance of #CRParser.
831  *@return CR_OK upon successfull completion, an error code otherwise.
832  */
833 static enum CRStatus
834 cr_parser_parse_ruleset_core (CRParser * a_this)
835 {
836  CRToken *token = NULL;
837  CRInputPos init_pos;
838  enum CRStatus status = CR_ERROR;
839 
840  g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
841  RECORD_INITIAL_POS (a_this, &init_pos);
842 
843  status = cr_parser_parse_selector_core (a_this);
844 
845  ENSURE_PARSING_COND (status == CR_OK
846  || status == CR_PARSING_ERROR
847  || status == CR_END_OF_INPUT_ERROR);
848 
849  status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
850  ENSURE_PARSING_COND (status == CR_OK && token
851  && token->type == CBO_TK);
852  cr_token_destroy (token);
853  token = NULL;
854 
856  status = cr_parser_parse_declaration_core (a_this);
857 
858  parse_declaration_list:
859  if (token) {
860  cr_token_destroy (token);
861  token = NULL;
862  }
863 
864  status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
865  ENSURE_PARSING_COND (status == CR_OK && token);
866  if (token->type == CBC_TK) {
867  goto done;
868  }
869 
870  ENSURE_PARSING_COND (status == CR_OK
871  && token && token->type == SEMICOLON_TK);
872 
873  cr_token_destroy (token);
874  token = NULL;
876  status = cr_parser_parse_declaration_core (a_this);
877  cr_parser_clear_errors (a_this);
878  ENSURE_PARSING_COND (status == CR_OK || status == CR_PARSING_ERROR);
879  status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
880  ENSURE_PARSING_COND (status == CR_OK && token);
881  if (token->type == CBC_TK) {
882  cr_token_destroy (token);
883  token = NULL;
885  goto done;
886  } else {
887  status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
888  token);
889  token = NULL;
890  goto parse_declaration_list;
891  }
892 
893  done:
894  if (token) {
895  cr_token_destroy (token);
896  token = NULL;
897  }
898 
899  if (status == CR_OK) {
900  return CR_OK;
901  }
902 
903  error:
904  if (token) {
905  cr_token_destroy (token);
906  token = NULL;
907  }
908 
909  cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
910 
911  return status;
912 }
913 
914 /**
915  *Parses a "selector" as specified by the css core
916  *grammar.
917  *selector : any+;
918  *@param a_this the current instance of #CRParser.
919  *@return CR_OK upon successfull completion, an error code
920  *otherwise.
921  */
922 static enum CRStatus
923 cr_parser_parse_selector_core (CRParser * a_this)
924 {
925  CRToken *token = NULL;
926  CRInputPos init_pos;
927  enum CRStatus status = CR_ERROR;
928 
929  g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
930 
931  RECORD_INITIAL_POS (a_this, &init_pos);
932 
933  status = cr_parser_parse_any_core (a_this);
934  CHECK_PARSING_STATUS (status, FALSE);
935 
936  do {
937  status = cr_parser_parse_any_core (a_this);
938 
939  } while (status == CR_OK);
940 
941  return CR_OK;
942 
943  error:
944  if (token) {
945  cr_token_destroy (token);
946  token = NULL;
947  }
948 
949  cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
950 
951  return status;
952 }
953 
954 /**
955  *Parses a "block" as defined in the css core grammar
956  *in chapter 4.1 of the css2 spec.
957  *block ::= '{' S* [ any | block | ATKEYWORD S* | ';' ]* '}' S*;
958  *@param a_this the current instance of #CRParser.
959  *FIXME: code this function.
960  */
961 static enum CRStatus
962 cr_parser_parse_block_core (CRParser * a_this)
963 {
964  CRToken *token = NULL;
965  CRInputPos init_pos;
966  enum CRStatus status = CR_ERROR;
967 
968  g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
969 
970  RECORD_INITIAL_POS (a_this, &init_pos);
971 
972  status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
973  ENSURE_PARSING_COND (status == CR_OK && token
974  && token->type == CBO_TK);
975 
976  parse_block_content:
977 
978  if (token) {
979  cr_token_destroy (token);
980  token = NULL;
981  }
982 
984 
985  status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
986  ENSURE_PARSING_COND (status == CR_OK && token);
987 
988  if (token->type == CBC_TK) {
990  goto done;
991  } else if (token->type == SEMICOLON_TK) {
992  goto parse_block_content;
993  } else if (token->type == ATKEYWORD_TK) {
995  goto parse_block_content;
996  } else if (token->type == CBO_TK) {
997  cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
998  token = NULL;
999  status = cr_parser_parse_block_core (a_this);
1000  CHECK_PARSING_STATUS (status, FALSE);
1001  goto parse_block_content;
1002  } else {
1003  cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
1004  token = NULL;
1005  status = cr_parser_parse_any_core (a_this);
1006  CHECK_PARSING_STATUS (status, FALSE);
1007  goto parse_block_content;
1008  }
1009 
1010  done:
1011  if (token) {
1012  cr_token_destroy (token);
1013  token = NULL;
1014  }
1015 
1016  if (status == CR_OK)
1017  return CR_OK;
1018 
1019  error:
1020  if (token) {
1021  cr_token_destroy (token);
1022  token = NULL;
1023  }
1024 
1025  cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
1026 
1027  return status;
1028 }
1029 
1030 static enum CRStatus
1031 cr_parser_parse_declaration_core (CRParser * a_this)
1032 {
1033  CRToken *token = NULL;
1034  CRInputPos init_pos;
1035  enum CRStatus status = CR_ERROR;
1036  CRString *prop = NULL;
1037 
1038  g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
1039 
1040  RECORD_INITIAL_POS (a_this, &init_pos);
1041 
1042  status = cr_parser_parse_property (a_this, &prop);
1043  CHECK_PARSING_STATUS (status, FALSE);
1044  cr_parser_clear_errors (a_this);
1045  ENSURE_PARSING_COND (status == CR_OK && prop);
1046  cr_string_destroy (prop);
1047  prop = NULL;
1048 
1049  status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
1050  ENSURE_PARSING_COND (status == CR_OK
1051  && token
1052  && token->type == DELIM_TK
1053  && token->u.unichar == ':');
1054  cr_token_destroy (token);
1055  token = NULL;
1057  status = cr_parser_parse_value_core (a_this);
1058  CHECK_PARSING_STATUS (status, FALSE);
1059 
1060  return CR_OK;
1061 
1062  error:
1063 
1064  if (prop) {
1065  cr_string_destroy (prop);
1066  prop = NULL;
1067  }
1068 
1069  if (token) {
1070  cr_token_destroy (token);
1071  token = NULL;
1072  }
1073 
1074  cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
1075 
1076  return status;
1077 }
1078 
1079 /**
1080  *Parses a "value" production as defined by the css core grammar
1081  *in chapter 4.1.
1082  *value ::= [ any | block | ATKEYWORD S* ]+;
1083  *@param a_this the current instance of #CRParser.
1084  *@return CR_OK upon successfull completion, an error code otherwise.
1085  */
1086 static enum CRStatus
1087 cr_parser_parse_value_core (CRParser * a_this)
1088 {
1089  CRToken *token = NULL;
1090  CRInputPos init_pos;
1091  enum CRStatus status = CR_ERROR;
1092  glong ref = 0;
1093 
1094  g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
1095  RECORD_INITIAL_POS (a_this, &init_pos);
1096 
1097  continue_parsing:
1098 
1099  if (token) {
1100  cr_token_destroy (token);
1101  token = NULL;
1102  }
1103 
1104  status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
1105  ENSURE_PARSING_COND (status == CR_OK && token);
1106 
1107  switch (token->type) {
1108  case CBO_TK:
1109  status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
1110  token);
1111  token = NULL;
1112  status = cr_parser_parse_block_core (a_this);
1113  CHECK_PARSING_STATUS (status, FALSE);
1114  ref++;
1115  goto continue_parsing;
1116 
1117  case ATKEYWORD_TK:
1119  ref++;
1120  goto continue_parsing;
1121 
1122  default:
1123  status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
1124  token);
1125  token = NULL;
1126  status = cr_parser_parse_any_core (a_this);
1127  if (status == CR_OK) {
1128  ref++;
1129  goto continue_parsing;
1130  } else if (status == CR_PARSING_ERROR) {
1131  status = CR_OK;
1132  goto done;
1133  } else {
1134  goto error;
1135  }
1136  }
1137 
1138  done:
1139  if (token) {
1140  cr_token_destroy (token);
1141  token = NULL;
1142  }
1143 
1144  if (status == CR_OK && ref)
1145  return CR_OK;
1146  error:
1147  if (token) {
1148  cr_token_destroy (token);
1149  token = NULL;
1150  }
1151 
1152  cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
1153 
1154  return status;
1155 }
1156 
1157 /**
1158  *Parses an "any" as defined by the css core grammar in the
1159  *css2 spec in chapter 4.1.
1160  *any ::= [ IDENT | NUMBER | PERCENTAGE | DIMENSION | STRING
1161  * | DELIM | URI | HASH | UNICODE-RANGE | INCLUDES
1162  * | FUNCTION | DASHMATCH | '(' any* ')' | '[' any* ']' ] S*;
1163  *
1164  *@param a_this the current instance of #CRParser.
1165  *@return CR_OK upon successfull completion, an error code otherwise.
1166  */
1167 static enum CRStatus
1168 cr_parser_parse_any_core (CRParser * a_this)
1169 {
1170  CRToken *token1 = NULL,
1171  *token2 = NULL;
1172  CRInputPos init_pos;
1173  enum CRStatus status = CR_ERROR;
1174 
1175  g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
1176 
1177  RECORD_INITIAL_POS (a_this, &init_pos);
1178 
1179  status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token1);
1180 
1181  ENSURE_PARSING_COND (status == CR_OK && token1);
1182 
1183  switch (token1->type) {
1184  case IDENT_TK:
1185  case NUMBER_TK:
1186  case RGB_TK:
1187  case PERCENTAGE_TK:
1188  case DIMEN_TK:
1189  case EMS_TK:
1190  case EXS_TK:
1191  case LENGTH_TK:
1192  case ANGLE_TK:
1193  case FREQ_TK:
1194  case TIME_TK:
1195  case STRING_TK:
1196  case DELIM_TK:
1197  case URI_TK:
1198  case HASH_TK:
1199  case UNICODERANGE_TK:
1200  case INCLUDES_TK:
1201  case DASHMATCH_TK:
1202  case S_TK:
1203  case COMMENT_TK:
1204  case IMPORTANT_SYM_TK:
1205  status = CR_OK;
1206  break;
1207  case FUNCTION_TK:
1208  /*
1209  *this case isn't specified by the spec but it
1210  *does happen. So we have to handle it.
1211  *We must consider function with parameters.
1212  *We consider parameter as being an "any*" production.
1213  */
1214  do {
1215  status = cr_parser_parse_any_core (a_this);
1216  } while (status == CR_OK);
1217 
1219  status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
1220  &token2);
1221  ENSURE_PARSING_COND (status == CR_OK
1222  && token2 && token2->type == PC_TK);
1223  break;
1224  case PO_TK:
1225  status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
1226  &token2);
1227  ENSURE_PARSING_COND (status == CR_OK && token2);
1228 
1229  if (token2->type == PC_TK) {
1230  cr_token_destroy (token2);
1231  token2 = NULL;
1232  goto done;
1233  } else {
1234  status = cr_tknzr_unget_token
1235  (PRIVATE (a_this)->tknzr, token2);
1236  token2 = NULL;
1237  }
1238 
1239  do {
1240  status = cr_parser_parse_any_core (a_this);
1241  } while (status == CR_OK);
1242 
1244 
1245  status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
1246  &token2);
1247  ENSURE_PARSING_COND (status == CR_OK
1248  && token2 && token2->type == PC_TK);
1249  status = CR_OK;
1250  break;
1251 
1252  case BO_TK:
1253  status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
1254  &token2);
1255  ENSURE_PARSING_COND (status == CR_OK && token2);
1256 
1257  if (token2->type == BC_TK) {
1258  cr_token_destroy (token2);
1259  token2 = NULL;
1260  goto done;
1261  } else {
1262  status = cr_tknzr_unget_token
1263  (PRIVATE (a_this)->tknzr, token2);
1264  token2 = NULL;
1265  }
1266 
1267  do {
1268  status = cr_parser_parse_any_core (a_this);
1269  } while (status == CR_OK);
1270 
1272 
1273  status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
1274  &token2);
1275  ENSURE_PARSING_COND (status == CR_OK
1276  && token2 && token2->type == BC_TK);
1277  status = CR_OK;
1278  break;
1279  default:
1280  status = CR_PARSING_ERROR;
1281  goto error;
1282  }
1283 
1284  done:
1285  if (token1) {
1286  cr_token_destroy (token1);
1287  token1 = NULL;
1288  }
1289 
1290  if (token2) {
1291  cr_token_destroy (token2);
1292  token2 = NULL;
1293  }
1294 
1295  return CR_OK;
1296 
1297  error:
1298 
1299  if (token1) {
1300  cr_token_destroy (token1);
1301  token1 = NULL;
1302  }
1303 
1304  if (token2) {
1305  cr_token_destroy (token2);
1306  token2 = NULL;
1307  }
1308 
1309  cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
1310  return status;
1311 }
1312 
1313 /**
1314  *Parses an attribute selector as defined in the css2 spec in
1315  *appendix D.1:
1316  *attrib ::= '[' S* IDENT S* [ [ '=' | INCLUDES | DASHMATCH ] S*
1317  * [ IDENT | STRING ] S* ]? ']'
1318  *
1319  *@param a_this the "this pointer" of the current instance of
1320  *#CRParser .
1321  *@param a_sel out parameter. The successfully parsed attribute selector.
1322  *@return CR_OK upon successfull completion, an error code otherwise.
1323  */
1324 static enum CRStatus
1325 cr_parser_parse_attribute_selector (CRParser * a_this,
1326  CRAttrSel ** a_sel)
1327 {
1328  enum CRStatus status = CR_OK;
1329  CRInputPos init_pos;
1330  CRToken *token = NULL;
1331  CRAttrSel *result = NULL;
1332  CRParsingLocation location = {0} ;
1333 
1334  g_return_val_if_fail (a_this && a_sel, CR_BAD_PARAM_ERROR);
1335 
1336  RECORD_INITIAL_POS (a_this, &init_pos);
1337 
1338  status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
1339  ENSURE_PARSING_COND (status == CR_OK && token
1340  && token->type == BO_TK);
1342  (&location, &token->location) ;
1343  cr_token_destroy (token);
1344  token = NULL;
1345 
1347 
1348  result = cr_attr_sel_new ();
1349  if (!result) {
1350  cr_utils_trace_info ("result failed") ;
1351  status = CR_OUT_OF_MEMORY_ERROR ;
1352  goto error ;
1353  }
1355  &location) ;
1356  status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
1357  ENSURE_PARSING_COND (status == CR_OK
1358  && token && token->type == IDENT_TK);
1359 
1360  result->name = token->u.str;
1361  token->u.str = NULL;
1362  cr_token_destroy (token);
1363  token = NULL;
1364 
1366 
1367  status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
1368  ENSURE_PARSING_COND (status == CR_OK && token);
1369 
1370  if (token->type == INCLUDES_TK) {
1371  result->match_way = INCLUDES;
1372  goto parse_right_part;
1373  } else if (token->type == DASHMATCH_TK) {
1374  result->match_way = DASHMATCH;
1375  goto parse_right_part;
1376  } else if (token->type == DELIM_TK && token->u.unichar == '=') {
1377  result->match_way = EQUALS;
1378  goto parse_right_part;
1379  } else if (token->type == BC_TK) {
1380  result->match_way = SET;
1381  goto done;
1382  }
1383 
1384  parse_right_part:
1385 
1386  if (token) {
1387  cr_token_destroy (token);
1388  token = NULL;
1389  }
1390 
1392 
1393  status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
1394  ENSURE_PARSING_COND (status == CR_OK && token);
1395 
1396  if (token->type == IDENT_TK) {
1397  result->value = token->u.str;
1398  token->u.str = NULL;
1399  } else if (token->type == STRING_TK) {
1400  result->value = token->u.str;
1401  token->u.str = NULL;
1402  } else {
1403  status = CR_PARSING_ERROR;
1404  goto error;
1405  }
1406 
1407  if (token) {
1408  cr_token_destroy (token);
1409  token = NULL;
1410  }
1411 
1413 
1414  status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
1415 
1416  ENSURE_PARSING_COND (status == CR_OK && token
1417  && token->type == BC_TK);
1418  done:
1419  if (token) {
1420  cr_token_destroy (token);
1421  token = NULL;
1422  }
1423 
1424  if (*a_sel) {
1425  status = cr_attr_sel_append_attr_sel (*a_sel, result);
1426  CHECK_PARSING_STATUS (status, FALSE);
1427  } else {
1428  *a_sel = result;
1429  }
1430 
1431  cr_parser_clear_errors (a_this);
1432  return CR_OK;
1433 
1434  error:
1435 
1436  if (result) {
1437  cr_attr_sel_destroy (result);
1438  result = NULL;
1439  }
1440 
1441  if (token) {
1442  cr_token_destroy (token);
1443  token = NULL;
1444  }
1445 
1446  cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
1447 
1448  return status;
1449 }
1450 
1451 /**
1452  *Parses a "property" as specified by the css2 spec at [4.1.1]:
1453  *property : IDENT S*;
1454  *
1455  *@param a_this the "this pointer" of the current instance of #CRParser.
1456  *@param GString a_property out parameter. The parsed property without the
1457  *trailing spaces. If *a_property is NULL, this function allocates a
1458  *new instance of GString and set it content to the parsed property.
1459  *If not, the property is just appended to a_property's previous content.
1460  *In both cases, it is up to the caller to free a_property.
1461  *@return CR_OK upon successfull completion, CR_PARSING_ERROR if the
1462  *next construction was not a "property", or an error code.
1463  */
1464 static enum CRStatus
1465 cr_parser_parse_property (CRParser * a_this,
1466  CRString ** a_property)
1467 {
1468  enum CRStatus status = CR_OK;
1469  CRInputPos init_pos;
1470 
1471  g_return_val_if_fail (a_this && PRIVATE (a_this)
1472  && PRIVATE (a_this)->tknzr
1473  && a_property,
1475 
1476  RECORD_INITIAL_POS (a_this, &init_pos);
1477 
1478  status = cr_parser_parse_ident (a_this, a_property);
1479  CHECK_PARSING_STATUS (status, TRUE);
1480 
1482 
1483  cr_parser_clear_errors (a_this);
1484  return CR_OK;
1485 
1486  error:
1487 
1488  cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
1489 
1490  return status;
1491 }
1492 
1493 /**
1494  * cr_parser_parse_term:
1495  *@a_term: out parameter. The successfully parsed term.
1496  *
1497  *Parses a "term" as defined in the css2 spec, appendix D.1:
1498  *term ::= unary_operator? [NUMBER S* | PERCENTAGE S* | LENGTH S* |
1499  *EMS S* | EXS S* | ANGLE S* | TIME S* | FREQ S* | function ] |
1500  *STRING S* | IDENT S* | URI S* | RGB S* | UNICODERANGE S* | hexcolor
1501  *
1502  *TODO: handle parsing of 'RGB'
1503  *
1504  *Returns CR_OK upon successfull completion, an error code otherwise.
1505  */
1506 enum CRStatus
1507 cr_parser_parse_term (CRParser * a_this, CRTerm ** a_term)
1508 {
1509  enum CRStatus status = CR_PARSING_ERROR;
1510  CRInputPos init_pos;
1511  CRTerm *result = NULL;
1512  CRTerm *param = NULL;
1513  CRToken *token = NULL;
1514  CRString *func_name = NULL;
1515  CRParsingLocation location = {0} ;
1516 
1517  g_return_val_if_fail (a_this && a_term, CR_BAD_PARAM_ERROR);
1518 
1519  RECORD_INITIAL_POS (a_this, &init_pos);
1520 
1521  result = cr_term_new ();
1522 
1523  status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
1524  &token);
1525  if (status != CR_OK || !token)
1526  goto error;
1527 
1528  cr_parsing_location_copy (&location, &token->location) ;
1529  if (token->type == DELIM_TK && token->u.unichar == '+') {
1530  result->unary_op = PLUS_UOP;
1531  cr_token_destroy (token) ;
1532  token = NULL ;
1534  status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
1535  &token);
1536  if (status != CR_OK || !token)
1537  goto error;
1538  } else if (token->type == DELIM_TK && token->u.unichar == '-') {
1539  result->unary_op = MINUS_UOP;
1540  cr_token_destroy (token) ;
1541  token = NULL ;
1543  status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
1544  &token);
1545  if (status != CR_OK || !token)
1546  goto error;
1547  }
1548 
1549  if (token->type == EMS_TK
1550  || token->type == EXS_TK
1551  || token->type == LENGTH_TK
1552  || token->type == ANGLE_TK
1553  || token->type == TIME_TK
1554  || token->type == FREQ_TK
1555  || token->type == PERCENTAGE_TK
1556  || token->type == NUMBER_TK) {
1557  status = cr_term_set_number (result, token->u.num);
1558  CHECK_PARSING_STATUS (status, TRUE);
1559  token->u.num = NULL;
1560  status = CR_OK;
1561  } else if (token && token->type == FUNCTION_TK) {
1562  status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
1563  token);
1564  token = NULL;
1565  status = cr_parser_parse_function (a_this, &func_name,
1566  &param);
1567 
1568  if (status == CR_OK) {
1569  status = cr_term_set_function (result,
1570  func_name,
1571  param);
1572  CHECK_PARSING_STATUS (status, TRUE);
1573  }
1574  } else if (token && token->type == STRING_TK) {
1575  status = cr_term_set_string (result,
1576  token->u.str);
1577  CHECK_PARSING_STATUS (status, TRUE);
1578  token->u.str = NULL;
1579  } else if (token && token->type == IDENT_TK) {
1580  status = cr_term_set_ident (result, token->u.str);
1581  CHECK_PARSING_STATUS (status, TRUE);
1582  token->u.str = NULL;
1583  } else if (token && token->type == URI_TK) {
1584  status = cr_term_set_uri (result, token->u.str);
1585  CHECK_PARSING_STATUS (status, TRUE);
1586  token->u.str = NULL;
1587  } else if (token && token->type == RGB_TK) {
1588  status = cr_term_set_rgb (result, token->u.rgb);
1589  CHECK_PARSING_STATUS (status, TRUE);
1590  token->u.rgb = NULL;
1591  } else if (token && token->type == UNICODERANGE_TK) {
1592  result->type = TERM_UNICODERANGE;
1593  status = CR_PARSING_ERROR;
1594  } else if (token && token->type == HASH_TK) {
1595  status = cr_term_set_hash (result, token->u.str);
1596  CHECK_PARSING_STATUS (status, TRUE);
1597  token->u.str = NULL;
1598  } else {
1599  status = CR_PARSING_ERROR;
1600  }
1601 
1602  if (status != CR_OK) {
1603  goto error;
1604  }
1606  &location) ;
1607  *a_term = cr_term_append_term (*a_term, result);
1608 
1609  result = NULL;
1610 
1612 
1613  if (token) {
1614  cr_token_destroy (token);
1615  token = NULL;
1616  }
1617 
1618  cr_parser_clear_errors (a_this);
1619  return CR_OK;
1620 
1621  error:
1622 
1623  if (result) {
1624  cr_term_destroy (result);
1625  result = NULL;
1626  }
1627 
1628  if (token) {
1629  cr_token_destroy (token);
1630  token = NULL;
1631  }
1632 
1633  if (param) {
1634  cr_term_destroy (param);
1635  param = NULL;
1636  }
1637 
1638  if (func_name) {
1639  cr_string_destroy (func_name);
1640  func_name = NULL;
1641  }
1642 
1643  cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
1644 
1645  return status;
1646 }
1647 
1648 /**
1649  * cr_parser_parse_simple_selector:
1650  *@a_this: the "this pointer" of the current instance of #CRParser.
1651  *@a_sel: out parameter. Is set to the successfully parsed simple
1652  *selector.
1653  *
1654  *Parses a "simple_selector" as defined by the css2 spec in appendix D.1 :
1655  *element_name? [ HASH | class | attrib | pseudo ]* S*
1656  *and where pseudo is:
1657  *pseudo ::= ':' [ IDENT | FUNCTION S* IDENT S* ')' ]
1658  *
1659  *Returns CR_OK upon successfull completion, an error code otherwise.
1660  */
1661 static enum CRStatus
1662 cr_parser_parse_simple_selector (CRParser * a_this, CRSimpleSel ** a_sel)
1663 {
1664  enum CRStatus status = CR_ERROR;
1665  CRInputPos init_pos;
1666  CRToken *token = NULL;
1667  CRSimpleSel *sel = NULL;
1668  CRAdditionalSel *add_sel_list = NULL;
1669  gboolean found_sel = FALSE;
1670  guint32 cur_char = 0;
1671 
1672  g_return_val_if_fail (a_this && a_sel, CR_BAD_PARAM_ERROR);
1673 
1674  RECORD_INITIAL_POS (a_this, &init_pos);
1675 
1676  status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
1677  if (status != CR_OK)
1678  goto error;
1679 
1680  sel = cr_simple_sel_new ();
1681  ENSURE_PARSING_COND (sel);
1682 
1684  (&sel->location,
1685  &token->location) ;
1686 
1687  if (token && token->type == DELIM_TK
1688  && token->u.unichar == '*') {
1689  sel->type_mask |= UNIVERSAL_SELECTOR;
1690  sel->name = cr_string_new_from_string ("*");
1691  found_sel = TRUE;
1692  } else if (token && token->type == IDENT_TK) {
1693  sel->name = token->u.str;
1694  sel->type_mask |= TYPE_SELECTOR;
1695  token->u.str = NULL;
1696  found_sel = TRUE;
1697  } else {
1698  status = cr_tknzr_unget_token
1699  (PRIVATE (a_this)->tknzr,
1700  token);
1701  token = NULL;
1702  }
1703 
1704  if (token) {
1705  cr_token_destroy (token);
1706  token = NULL;
1707  }
1708 
1710 
1711  for (;;) {
1712  if (token) {
1713  cr_token_destroy (token);
1714  token = NULL;
1715  }
1716 
1717  status = cr_tknzr_get_next_token
1718  (PRIVATE (a_this)->tknzr,
1719  &token);
1720  if (status != CR_OK)
1721  goto error;
1722 
1723  if (token && token->type == HASH_TK) {
1724  /*we parsed an attribute id */
1725  CRAdditionalSel *add_sel = NULL;
1726 
1728  (ID_ADD_SELECTOR);
1729 
1730  add_sel->content.id_name = token->u.str;
1731  token->u.str = NULL;
1732 
1734  (&add_sel->location,
1735  &token->location) ;
1736  add_sel_list =
1738  (add_sel_list, add_sel);
1739  found_sel = TRUE;
1740  } else if (token && (token->type == DELIM_TK)
1741  && (token->u.unichar == '.')) {
1742  cr_token_destroy (token);
1743  token = NULL;
1744 
1745  status = cr_tknzr_get_next_token
1746  (PRIVATE (a_this)->tknzr, &token);
1747  if (status != CR_OK)
1748  goto error;
1749 
1750  if (token && token->type == IDENT_TK) {
1751  CRAdditionalSel *add_sel = NULL;
1752 
1755 
1756  add_sel->content.class_name = token->u.str;
1757  token->u.str = NULL;
1758 
1759  add_sel_list =
1761  (add_sel_list, add_sel);
1762  found_sel = TRUE;
1763 
1765  (&add_sel->location,
1766  & token->location) ;
1767  } else {
1768  status = CR_PARSING_ERROR;
1769  goto error;
1770  }
1771  } else if (token && token->type == BO_TK) {
1772  CRAttrSel *attr_sel = NULL;
1773  CRAdditionalSel *add_sel = NULL;
1774 
1775  status = cr_tknzr_unget_token
1776  (PRIVATE (a_this)->tknzr, token);
1777  if (status != CR_OK)
1778  goto error;
1779  token = NULL;
1780 
1781  status = cr_parser_parse_attribute_selector
1782  (a_this, &attr_sel);
1783  CHECK_PARSING_STATUS (status, FALSE);
1784 
1787 
1788  ENSURE_PARSING_COND (add_sel != NULL);
1789 
1790  add_sel->content.attr_sel = attr_sel;
1791 
1792  add_sel_list =
1794  (add_sel_list, add_sel);
1795  found_sel = TRUE;
1797  (&add_sel->location,
1798  &attr_sel->location) ;
1799  } else if (token && (token->type == DELIM_TK)
1800  && (token->u.unichar == ':')) {
1801  CRPseudo *pseudo = NULL;
1802 
1803  /*try to parse a pseudo */
1804 
1805  if (token) {
1806  cr_token_destroy (token);
1807  token = NULL;
1808  }
1809 
1810  pseudo = cr_pseudo_new ();
1811 
1812  status = cr_tknzr_get_next_token
1813  (PRIVATE (a_this)->tknzr, &token);
1814  ENSURE_PARSING_COND (status == CR_OK && token);
1815 
1817  (&pseudo->location,
1818  &token->location) ;
1819 
1820  if (token->type == IDENT_TK) {
1821  pseudo->type = IDENT_PSEUDO;
1822  pseudo->name = token->u.str;
1823  token->u.str = NULL;
1824  found_sel = TRUE;
1825  } else if (token->type == FUNCTION_TK) {
1826  pseudo->name = token->u.str;
1827  token->u.str = NULL;
1829  (a_this);
1830  status = cr_parser_parse_ident
1831  (a_this, &pseudo->extra);
1832 
1833  ENSURE_PARSING_COND (status == CR_OK);
1834  READ_NEXT_CHAR (a_this, &cur_char);
1835  ENSURE_PARSING_COND (cur_char == ')');
1836  pseudo->type = FUNCTION_PSEUDO;
1837  found_sel = TRUE;
1838  } else {
1839  status = CR_PARSING_ERROR;
1840  goto error;
1841  }
1842 
1843  if (status == CR_OK) {
1844  CRAdditionalSel *add_sel = NULL;
1845 
1848 
1849  add_sel->content.pseudo = pseudo;
1851  (&add_sel->location,
1852  &pseudo->location) ;
1853  add_sel_list =
1855  (add_sel_list, add_sel);
1856  status = CR_OK;
1857  }
1858  } else {
1859  status = cr_tknzr_unget_token
1860  (PRIVATE (a_this)->tknzr, token);
1861  token = NULL;
1862  break;
1863  }
1864  }
1865 
1866  if (status == CR_OK && found_sel == TRUE) {
1868 
1869  sel->add_sel = add_sel_list;
1870  add_sel_list = NULL;
1871 
1872  if (*a_sel == NULL) {
1873  *a_sel = sel;
1874  } else {
1875  cr_simple_sel_append_simple_sel (*a_sel, sel);
1876  }
1877 
1878  sel = NULL;
1879 
1880  if (token) {
1881  cr_token_destroy (token);
1882  token = NULL;
1883  }
1884 
1885  cr_parser_clear_errors (a_this);
1886  return CR_OK;
1887  } else {
1888  status = CR_PARSING_ERROR;
1889  }
1890 
1891  error:
1892 
1893  if (token) {
1894  cr_token_destroy (token);
1895  token = NULL;
1896  }
1897 
1898  if (add_sel_list) {
1899  cr_additional_sel_destroy (add_sel_list);
1900  add_sel_list = NULL;
1901  }
1902 
1903  if (sel) {
1904  cr_simple_sel_destroy (sel);
1905  sel = NULL;
1906  }
1907 
1908  cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
1909 
1910  return status;
1911 
1912 }
1913 
1914 /**
1915  * cr_parser_parse_simple_sels:
1916  *@a_this: the this pointer of the current instance of #CRParser.
1917  *@a_start: a pointer to the
1918  *first chararcter of the successfully parsed
1919  *string.
1920  *@a_end: a pointer to the last character of the successfully parsed
1921  *string.
1922  *
1923  *Parses a "selector" as defined by the css2 spec in appendix D.1:
1924  *selector ::= simple_selector [ combinator simple_selector ]*
1925  *
1926  *Returns CR_OK upon successfull completion, an error code otherwise.
1927  */
1928 static enum CRStatus
1929 cr_parser_parse_simple_sels (CRParser * a_this,
1930  CRSimpleSel ** a_sel)
1931 {
1932  enum CRStatus status = CR_ERROR;
1933  CRInputPos init_pos;
1934  CRSimpleSel *sel = NULL;
1935  guint32 cur_char = 0;
1936 
1937  g_return_val_if_fail (a_this
1938  && PRIVATE (a_this)
1939  && a_sel,
1941 
1942  RECORD_INITIAL_POS (a_this, &init_pos);
1943 
1944  status = cr_parser_parse_simple_selector (a_this, &sel);
1945  CHECK_PARSING_STATUS (status, FALSE);
1946 
1947  *a_sel = cr_simple_sel_append_simple_sel (*a_sel, sel);
1948 
1949  for (;;) {
1950  guint32 next_char = 0;
1951  enum Combinator comb = 0;
1952 
1953  sel = NULL;
1954 
1955  PEEK_NEXT_CHAR (a_this, &next_char);
1956 
1957  if (next_char == '+') {
1958  READ_NEXT_CHAR (a_this, &cur_char);
1959  comb = COMB_PLUS;
1961  } else if (next_char == '>') {
1962  READ_NEXT_CHAR (a_this, &cur_char);
1963  comb = COMB_GT;
1965  } else {
1966  comb = COMB_WS;
1967  }
1968 
1969  status = cr_parser_parse_simple_selector (a_this, &sel);
1970  if (status != CR_OK)
1971  break;
1972 
1973  if (comb && sel) {
1974  sel->combinator = comb;
1975  comb = 0;
1976  }
1977  if (sel) {
1978  *a_sel = cr_simple_sel_append_simple_sel (*a_sel,
1979  sel) ;
1980  }
1981  }
1982  cr_parser_clear_errors (a_this);
1983  return CR_OK;
1984 
1985  error:
1986 
1987  cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
1988 
1989  return status;
1990 }
1991 
1992 /**
1993  * cr_parser_parse_selector:
1994  *@a_this: the current instance of #CRParser.
1995  *@a_selector: the parsed list of comma separated
1996  *selectors.
1997  *
1998  *Parses a comma separated list of selectors.
1999  *
2000  *Returns CR_OK upon successful completion, an error
2001  *code otherwise.
2002  */
2003 static enum CRStatus
2004 cr_parser_parse_selector (CRParser * a_this,
2005  CRSelector ** a_selector)
2006 {
2007  enum CRStatus status = CR_OK;
2008  CRInputPos init_pos;
2009  guint32 cur_char = 0,
2010  next_char = 0;
2011  CRSimpleSel *simple_sels = NULL;
2012  CRSelector *selector = NULL;
2013 
2014  g_return_val_if_fail (a_this && a_selector, CR_BAD_PARAM_ERROR);
2015 
2016  RECORD_INITIAL_POS (a_this, &init_pos);
2017 
2018  status = cr_parser_parse_simple_sels (a_this, &simple_sels);
2019  CHECK_PARSING_STATUS (status, FALSE);
2020 
2021  if (simple_sels) {
2023  (selector, simple_sels);
2024  if (selector) {
2026  (&selector->location,
2027  &simple_sels->location) ;
2028  }
2029  simple_sels = NULL;
2030  } else {
2031  status = CR_PARSING_ERROR ;
2032  goto error ;
2033  }
2034 
2035  status = cr_tknzr_peek_char (PRIVATE (a_this)->tknzr,
2036  &next_char);
2037  if (status != CR_OK) {
2038  if (status == CR_END_OF_INPUT_ERROR) {
2039  status = CR_OK;
2040  goto okay;
2041  } else {
2042  goto error;
2043  }
2044  }
2045 
2046  if (next_char == ',') {
2047  for (;;) {
2048  simple_sels = NULL;
2049 
2050  status = cr_tknzr_peek_char (PRIVATE (a_this)->tknzr,
2051  &next_char);
2052  if (status != CR_OK) {
2053  if (status == CR_END_OF_INPUT_ERROR) {
2054  status = CR_OK;
2055  break;
2056  } else {
2057  goto error;
2058  }
2059  }
2060 
2061  if (next_char != ',')
2062  break;
2063 
2064  /*consume the ',' char */
2065  READ_NEXT_CHAR (a_this, &cur_char);
2066 
2068 
2069  status = cr_parser_parse_simple_sels
2070  (a_this, &simple_sels);
2071 
2072  CHECK_PARSING_STATUS (status, FALSE);
2073 
2074  if (simple_sels) {
2075  selector =
2077  (selector, simple_sels);
2078 
2079  simple_sels = NULL;
2080  }
2081  }
2082  }
2083 
2084  okay:
2086 
2087  if (!*a_selector) {
2088  *a_selector = selector;
2089  } else {
2090  *a_selector = cr_selector_append (*a_selector, selector);
2091  }
2092 
2093  selector = NULL;
2094  return CR_OK;
2095 
2096  error:
2097 
2098  if (simple_sels) {
2099  cr_simple_sel_destroy (simple_sels);
2100  simple_sels = NULL;
2101  }
2102 
2103  if (selector) {
2104  cr_selector_unref (selector);
2105  selector = NULL;
2106  }
2107 
2108  cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
2109 
2110  return status;
2111 }
2112 
2113 /**
2114  * cr_parser_parse_function:
2115  *@a_this: the "this pointer" of the current instance of #CRParser.
2116  *
2117  *@a_func_name: out parameter. The parsed function name
2118  *@a_expr: out parameter. The successfully parsed term.
2119  *
2120  *Parses a "function" as defined in css spec at appendix D.1:
2121  *function ::= FUNCTION S* expr ')' S*
2122  *FUNCTION ::= ident'('
2123  *
2124  *Returns CR_OK upon successfull completion, an error code otherwise.
2125  */
2126 static enum CRStatus
2127 cr_parser_parse_function (CRParser * a_this,
2128  CRString ** a_func_name,
2129  CRTerm ** a_expr)
2130 {
2131  CRInputPos init_pos;
2132  enum CRStatus status = CR_OK;
2133  CRToken *token = NULL;
2134  CRTerm *expr = NULL;
2135 
2136  g_return_val_if_fail (a_this && PRIVATE (a_this)
2137  && a_func_name,
2139 
2140  RECORD_INITIAL_POS (a_this, &init_pos);
2141 
2142  status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
2143  if (status != CR_OK)
2144  goto error;
2145 
2146  if (token && token->type == FUNCTION_TK) {
2147  *a_func_name = token->u.str;
2148  token->u.str = NULL;
2149  } else {
2150  status = CR_PARSING_ERROR;
2151  goto error;
2152  }
2153  cr_token_destroy (token);
2154  token = NULL;
2155 
2157 
2158  status = cr_parser_parse_expr (a_this, &expr);
2159 
2160  CHECK_PARSING_STATUS (status, FALSE);
2161 
2162  status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
2163  if (status != CR_OK)
2164  goto error;
2165 
2166  ENSURE_PARSING_COND (token && token->type == PC_TK);
2167 
2168  cr_token_destroy (token);
2169  token = NULL;
2170 
2171  if (expr) {
2172  *a_expr = cr_term_append_term (*a_expr, expr);
2173  expr = NULL;
2174  }
2175 
2176  cr_parser_clear_errors (a_this);
2177  return CR_OK;
2178 
2179  error:
2180 
2181  if (*a_func_name) {
2182  cr_string_destroy (*a_func_name);
2183  *a_func_name = NULL;
2184  }
2185 
2186  if (expr) {
2187  cr_term_destroy (expr);
2188  expr = NULL;
2189  }
2190 
2191  if (token) {
2192  cr_token_destroy (token);
2193 
2194  }
2195 
2196  cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
2197 
2198  return status;
2199 }
2200 
2201 /**
2202  * cr_parser_parse_uri:
2203  *@a_this: the current instance of #CRParser.
2204  *@a_str: the successfully parsed url.
2205  *
2206  *Parses an uri as defined by the css spec [4.1.1]:
2207  * URI ::= url\({w}{string}{w}\)
2208  * |url\({w}([!#$%&*-~]|{nonascii}|{escape})*{w}\)
2209  *
2210  *Returns CR_OK upon successfull completion, an error code otherwise.
2211  */
2212 static enum CRStatus
2213 cr_parser_parse_uri (CRParser * a_this, CRString ** a_str)
2214 {
2215 
2216  enum CRStatus status = CR_PARSING_ERROR;
2217 
2218  g_return_val_if_fail (a_this && PRIVATE (a_this)
2219  && PRIVATE (a_this)->tknzr, CR_BAD_PARAM_ERROR);
2220 
2221  status = cr_tknzr_parse_token (PRIVATE (a_this)->tknzr,
2222  URI_TK, NO_ET, a_str, NULL);
2223  return status;
2224 }
2225 
2226 /**
2227  * cr_parser_parse_string:
2228  *@a_this: the current instance of #CRParser.
2229  *@a_start: out parameter. Upon successfull completion,
2230  *points to the beginning of the string, points to an undefined value
2231  *otherwise.
2232  *@a_end: out parameter. Upon successfull completion, points to
2233  *the beginning of the string, points to an undefined value otherwise.
2234  *
2235  *Parses a string type as defined in css spec [4.1.1]:
2236  *
2237  *string ::= {string1}|{string2}
2238  *string1 ::= \"([\t !#$%&(-~]|\\{nl}|\'|{nonascii}|{escape})*\"
2239  *string2 ::= \'([\t !#$%&(-~]|\\{nl}|\"|{nonascii}|{escape})*\'
2240  *
2241  *Returns CR_OK upon successfull completion, an error code otherwise.
2242  */
2243 static enum CRStatus
2244 cr_parser_parse_string (CRParser * a_this, CRString ** a_str)
2245 {
2246  enum CRStatus status = CR_OK;
2247 
2248  g_return_val_if_fail (a_this && PRIVATE (a_this)
2249  && PRIVATE (a_this)->tknzr
2250  && a_str, CR_BAD_PARAM_ERROR);
2251 
2252  status = cr_tknzr_parse_token (PRIVATE (a_this)->tknzr,
2253  STRING_TK, NO_ET, a_str, NULL);
2254  return status;
2255 }
2256 
2257 /**
2258  *Parses an "ident" as defined in css spec [4.1.1]:
2259  *ident ::= {nmstart}{nmchar}*
2260  *
2261  *@param a_this the currens instance of #CRParser.
2262  *
2263  *@param a_str a pointer to parsed ident. If *a_str is NULL,
2264  *this function allocates a new instance of #CRString. If not,
2265  *the function just appends the parsed string to the one passed.
2266  *In both cases it is up to the caller to free *a_str.
2267  *
2268  *@return CR_OK upon successfull completion, an error code
2269  *otherwise.
2270  */
2271 static enum CRStatus
2272 cr_parser_parse_ident (CRParser * a_this, CRString ** a_str)
2273 {
2274  enum CRStatus status = CR_OK;
2275 
2276  g_return_val_if_fail (a_this && PRIVATE (a_this)
2277  && PRIVATE (a_this)->tknzr
2278  && a_str, CR_BAD_PARAM_ERROR);
2279 
2280  status = cr_tknzr_parse_token (PRIVATE (a_this)->tknzr,
2281  IDENT_TK, NO_ET, a_str, NULL);
2282  return status;
2283 }
2284 
2285 /**
2286  *the next rule is ignored as well. This seems to be a bug
2287  *Parses a stylesheet as defined in the css2 spec in appendix D.1:
2288  *stylesheet ::= [ CHARSET_SYM S* STRING S* ';' ]?
2289  * [S|CDO|CDC]* [ import [S|CDO|CDC]* ]*
2290  * [ [ ruleset | media | page | font_face ] [S|CDO|CDC]* ]*
2291  *
2292  *TODO: Finish the code of this function. Think about splitting it into
2293  *smaller functions.
2294  *
2295  *@param a_this the "this pointer" of the current instance of #CRParser.
2296  *@param a_start out parameter. A pointer to the first character of
2297  *the successfully parsed string.
2298  *@param a_end out parameter. A pointer to the first character of
2299  *the successfully parsed string.
2300  *
2301  *@return CR_OK upon successfull completion, an error code otherwise.
2302  */
2303 static enum CRStatus
2304 cr_parser_parse_stylesheet (CRParser * a_this)
2305 {
2306  enum CRStatus status = CR_OK;
2307  CRInputPos init_pos;
2308  CRToken *token = NULL;
2309  CRString *charset = NULL;
2310 
2311  g_return_val_if_fail (a_this && PRIVATE (a_this)
2312  && PRIVATE (a_this)->tknzr, CR_BAD_PARAM_ERROR);
2313 
2314  RECORD_INITIAL_POS (a_this, &init_pos);
2315 
2316  PRIVATE (a_this)->state = READY_STATE;
2317 
2318  if (PRIVATE (a_this)->sac_handler
2319  && PRIVATE (a_this)->sac_handler->start_document) {
2320  PRIVATE (a_this)->sac_handler->start_document
2321  (PRIVATE (a_this)->sac_handler);
2322  }
2323 
2324  parse_charset:
2325  status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
2326 
2327  if (status == CR_END_OF_INPUT_ERROR)
2328  goto done;
2329  CHECK_PARSING_STATUS (status, TRUE);
2330 
2331  if (token && token->type == CHARSET_SYM_TK) {
2332  CRParsingLocation location = {0} ;
2333  status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
2334  token);
2335  CHECK_PARSING_STATUS (status, TRUE);
2336  token = NULL;
2337 
2338  status = cr_parser_parse_charset (a_this,
2339  &charset,
2340  &location);
2341 
2342  if (status == CR_OK && charset) {
2343  if (PRIVATE (a_this)->sac_handler
2344  && PRIVATE (a_this)->sac_handler->charset) {
2345  PRIVATE (a_this)->sac_handler->charset
2346  (PRIVATE (a_this)->sac_handler,
2347  charset, &location);
2348  }
2349  } else if (status != CR_END_OF_INPUT_ERROR) {
2350  status = cr_parser_parse_atrule_core (a_this);
2351  CHECK_PARSING_STATUS (status, FALSE);
2352  }
2353 
2354  if (charset) {
2355  cr_string_destroy (charset);
2356  charset = NULL;
2357  }
2358  } else if (token
2359  && (token->type == S_TK
2360  || token->type == COMMENT_TK)) {
2361  status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
2362  token);
2363  token = NULL;
2364  CHECK_PARSING_STATUS (status, TRUE);
2365 
2367  goto parse_charset ;
2368  } else if (token) {
2369  status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
2370  token);
2371  token = NULL;
2372  CHECK_PARSING_STATUS (status, TRUE);
2373  }
2374 
2375 /* parse_imports:*/
2376  do {
2377  if (token) {
2378  cr_token_destroy (token);
2379  token = NULL;
2380  }
2382  status = cr_tknzr_get_next_token
2383  (PRIVATE (a_this)->tknzr, &token);
2384 
2385  if (status == CR_END_OF_INPUT_ERROR)
2386  goto done;
2387  CHECK_PARSING_STATUS (status, TRUE);
2388  } while (token
2389  && (token->type == S_TK
2390  || token->type == CDO_TK || token->type == CDC_TK));
2391 
2392  if (token) {
2393  status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
2394  token);
2395  token = NULL;
2396  }
2397 
2398  for (;;) {
2399  status = cr_tknzr_get_next_token
2400  (PRIVATE (a_this)->tknzr, &token);
2401  if (status == CR_END_OF_INPUT_ERROR)
2402  goto done;
2403  CHECK_PARSING_STATUS (status, TRUE);
2404 
2405  if (token && token->type == IMPORT_SYM_TK) {
2406  GList *media_list = NULL;
2407  CRString *import_string = NULL;
2408  CRParsingLocation location = {0} ;
2409 
2410  status = cr_tknzr_unget_token
2411  (PRIVATE (a_this)->tknzr, token);
2412  token = NULL;
2413  CHECK_PARSING_STATUS (status, TRUE);
2414 
2415  status = cr_parser_parse_import (a_this,
2416  &media_list,
2417  &import_string,
2418  &location);
2419  if (status == CR_OK) {
2420  if (import_string
2421  && PRIVATE (a_this)->sac_handler
2422  && PRIVATE (a_this)->sac_handler->import_style) {
2423  PRIVATE (a_this)->sac_handler->import_style
2424  (PRIVATE(a_this)->sac_handler,
2425  media_list,
2426  import_string,
2427  NULL, &location) ;
2428 
2429  if ((PRIVATE (a_this)->sac_handler->resolve_import == TRUE)) {
2430  /*
2431  *TODO: resolve the
2432  *import rule.
2433  */
2434  }
2435 
2436  if ((PRIVATE (a_this)->sac_handler->import_style_result)) {
2437  PRIVATE (a_this)->sac_handler->import_style_result
2438  (PRIVATE (a_this)->sac_handler,
2439  media_list, import_string,
2440  NULL, NULL);
2441  }
2442  }
2443  } else if (status != CR_END_OF_INPUT_ERROR) {
2444  if (PRIVATE (a_this)->sac_handler
2445  && PRIVATE (a_this)->sac_handler->error) {
2446  PRIVATE (a_this)->sac_handler->error
2447  (PRIVATE (a_this)->sac_handler);
2448  }
2449  status = cr_parser_parse_atrule_core (a_this);
2450  CHECK_PARSING_STATUS (status, TRUE) ;
2451  } else {
2452  goto error ;
2453  }
2454 
2455  /*
2456  *then, after calling the appropriate
2457  *SAC handler, free
2458  *the media_list and import_string.
2459  */
2460  if (media_list) {
2461  GList *cur = NULL;
2462 
2463  /*free the medium list */
2464  for (cur = media_list; cur; cur = cur->next) {
2465  if (cur->data) {
2466  cr_string_destroy (cur->data);
2467  }
2468  }
2469 
2470  g_list_free (media_list);
2471  media_list = NULL;
2472  }
2473 
2474  if (import_string) {
2475  cr_string_destroy (import_string);
2476  import_string = NULL;
2477  }
2478 
2480  } else if (token
2481  && (token->type == S_TK
2482  || token->type == CDO_TK
2483  || token->type == CDC_TK)) {
2484  status = cr_tknzr_unget_token
2485  (PRIVATE (a_this)->tknzr, token);
2486  token = NULL;
2487 
2488  do {
2489  if (token) {
2490  cr_token_destroy (token);
2491  token = NULL;
2492  }
2493 
2494  status = cr_tknzr_get_next_token
2495  (PRIVATE (a_this)->tknzr, &token);
2496 
2497  if (status == CR_END_OF_INPUT_ERROR)
2498  goto done;
2499  CHECK_PARSING_STATUS (status, TRUE);
2500  } while (token
2501  && (token->type == S_TK
2502  || token->type == CDO_TK
2503  || token->type == CDC_TK));
2504  } else {
2505  if (token) {
2506  status = cr_tknzr_unget_token
2507  (PRIVATE (a_this)->tknzr, token);
2508  token = NULL;
2509  }
2510  goto parse_ruleset_and_others;
2511  }
2512  }
2513 
2514  parse_ruleset_and_others:
2515 
2517 
2518  for (;;) {
2519  status = cr_tknzr_get_next_token
2520  (PRIVATE (a_this)->tknzr, &token);
2521  if (status == CR_END_OF_INPUT_ERROR)
2522  goto done;
2523  CHECK_PARSING_STATUS (status, TRUE);
2524 
2525  if (token
2526  && (token->type == S_TK
2527  || token->type == CDO_TK || token->type == CDC_TK)) {
2528  status = cr_tknzr_unget_token
2529  (PRIVATE (a_this)->tknzr, token);
2530  token = NULL;
2531 
2532  do {
2533  if (token) {
2534  cr_token_destroy (token);
2535  token = NULL;
2536  }
2537 
2539  (a_this);
2540  status = cr_tknzr_get_next_token
2541  (PRIVATE (a_this)->tknzr, &token);
2542  } while (token
2543  && (token->type == S_TK
2544  || token->type == COMMENT_TK
2545  || token->type == CDO_TK
2546  || token->type == CDC_TK));
2547  if (token) {
2549  (PRIVATE (a_this)->tknzr, token);
2550  token = NULL;
2551  }
2552  } else if (token
2553  && (token->type == HASH_TK
2554  || (token->type == DELIM_TK
2555  && token->u.unichar == '.')
2556  || (token->type == DELIM_TK
2557  && token->u.unichar == ':')
2558  || (token->type == DELIM_TK
2559  && token->u.unichar == '*')
2560  || (token->type == BO_TK)
2561  || token->type == IDENT_TK)) {
2562  /*
2563  *Try to parse a CSS2 ruleset.
2564  *if the parsing fails, try to parse
2565  *a css core ruleset.
2566  */
2567  status = cr_tknzr_unget_token
2568  (PRIVATE (a_this)->tknzr, token);
2569  CHECK_PARSING_STATUS (status, TRUE);
2570  token = NULL;
2571 
2572  status = cr_parser_parse_ruleset (a_this);
2573 
2574  if (status == CR_OK) {
2575  continue;
2576  } else {
2577  if (PRIVATE (a_this)->sac_handler
2578  && PRIVATE (a_this)->sac_handler->error) {
2579  PRIVATE (a_this)->sac_handler->
2580  error
2581  (PRIVATE (a_this)->
2582  sac_handler);
2583  }
2584 
2585  status = cr_parser_parse_ruleset_core
2586  (a_this);
2587 
2588  if (status == CR_OK) {
2589  continue;
2590  } else {
2591  break;
2592  }
2593  }
2594  } else if (token && token->type == MEDIA_SYM_TK) {
2595  status = cr_tknzr_unget_token
2596  (PRIVATE (a_this)->tknzr, token);
2597  CHECK_PARSING_STATUS (status, TRUE);
2598  token = NULL;
2599 
2600  status = cr_parser_parse_media (a_this);
2601  if (status == CR_OK) {
2602  continue;
2603  } else {
2604  if (PRIVATE (a_this)->sac_handler
2605  && PRIVATE (a_this)->sac_handler->error) {
2606  PRIVATE (a_this)->sac_handler->
2607  error
2608  (PRIVATE (a_this)->
2609  sac_handler);
2610  }
2611 
2612  status = cr_parser_parse_atrule_core (a_this);
2613 
2614  if (status == CR_OK) {
2615  continue;
2616  } else {
2617  break;
2618  }
2619  }
2620 
2621  } else if (token && token->type == PAGE_SYM_TK) {
2622  status = cr_tknzr_unget_token
2623  (PRIVATE (a_this)->tknzr, token);
2624  CHECK_PARSING_STATUS (status, TRUE);
2625  token = NULL;
2626  status = cr_parser_parse_page (a_this);
2627 
2628  if (status == CR_OK) {
2629  continue;
2630  } else {
2631  if (PRIVATE (a_this)->sac_handler
2632  && PRIVATE (a_this)->sac_handler->error) {
2633  PRIVATE (a_this)->sac_handler->
2634  error
2635  (PRIVATE (a_this)->
2636  sac_handler);
2637  }
2638 
2639  status = cr_parser_parse_atrule_core (a_this);
2640 
2641  if (status == CR_OK) {
2642  continue;
2643  } else {
2644  break;
2645  }
2646  }
2647  } else if (token && token->type == FONT_FACE_SYM_TK) {
2648  status = cr_tknzr_unget_token
2649  (PRIVATE (a_this)->tknzr, token);
2650  CHECK_PARSING_STATUS (status, TRUE);
2651  token = NULL;
2652  status = cr_parser_parse_font_face (a_this);
2653 
2654  if (status == CR_OK) {
2655  continue;
2656  } else {
2657  if (PRIVATE (a_this)->sac_handler
2658  && PRIVATE (a_this)->sac_handler->error) {
2659  PRIVATE (a_this)->sac_handler->
2660  error
2661  (PRIVATE (a_this)->
2662  sac_handler);
2663  }
2664 
2665  status = cr_parser_parse_atrule_core (a_this);
2666 
2667  if (status == CR_OK) {
2668  continue;
2669  } else {
2670  break;
2671  }
2672  }
2673  } else {
2674  status = cr_tknzr_unget_token
2675  (PRIVATE (a_this)->tknzr, token);
2676  CHECK_PARSING_STATUS (status, TRUE);
2677  token = NULL;
2678  status = cr_parser_parse_statement_core (a_this);
2679 
2680  if (status == CR_OK) {
2681  continue;
2682  } else {
2683  break;
2684  }
2685  }
2686  }
2687 
2688  done:
2689  if (token) {
2690  cr_token_destroy (token);
2691  token = NULL;
2692  }
2693 
2694  if (status == CR_END_OF_INPUT_ERROR || status == CR_OK) {
2695 
2696  if (PRIVATE (a_this)->sac_handler
2697  && PRIVATE (a_this)->sac_handler->end_document) {
2698  PRIVATE (a_this)->sac_handler->end_document
2699  (PRIVATE (a_this)->sac_handler);
2700  }
2701 
2702  return CR_OK;
2703  }
2704 
2705  cr_parser_push_error
2706  (a_this, (const guchar *) "could not recognize next production", CR_ERROR);
2707 
2708  if (PRIVATE (a_this)->sac_handler
2709  && PRIVATE (a_this)->sac_handler->unrecoverable_error) {
2710  PRIVATE (a_this)->sac_handler->
2711  unrecoverable_error (PRIVATE (a_this)->sac_handler);
2712  }
2713 
2714  cr_parser_dump_err_stack (a_this, TRUE);
2715 
2716  return status;
2717 
2718  error:
2719 
2720  if (token) {
2721  cr_token_destroy (token);
2722  token = NULL;
2723  }
2724 
2725  if (PRIVATE (a_this)->sac_handler
2726  && PRIVATE (a_this)->sac_handler->unrecoverable_error) {
2727  PRIVATE (a_this)->sac_handler->
2728  unrecoverable_error (PRIVATE (a_this)->sac_handler);
2729  }
2730 
2731  cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
2732 
2733  return status;
2734 }
2735 
2736 /****************************************
2737  *Public CRParser Methods
2738  ****************************************/
2739 
2740 /**
2741  * cr_parser_new:
2742  * @a_tknzr: the tokenizer to use for the parsing.
2743  *
2744  *Creates a new parser to parse data
2745  *coming the input stream given in parameter.
2746  *
2747  *Returns the newly created instance of #CRParser,
2748  *or NULL if an error occurred.
2749  */
2750 CRParser *
2752 {
2753  CRParser *result = NULL;
2754  enum CRStatus status = CR_OK;
2755 
2756  result = g_malloc0 (sizeof (CRParser));
2757 
2758  PRIVATE (result) = g_malloc0 (sizeof (CRParserPriv));
2759 
2760  if (a_tknzr) {
2761  status = cr_parser_set_tknzr (result, a_tknzr);
2762  }
2763 
2764  g_return_val_if_fail (status == CR_OK, NULL);
2765 
2766  return result;
2767 }
2768 
2769 /**
2770  * cr_parser_new_from_buf:
2771  *@a_buf: the buffer to parse.
2772  *@a_len: the length of the data in the buffer.
2773  *@a_enc: the encoding of the input buffer a_buf.
2774  *@a_free_buf: if set to TRUE, a_buf will be freed
2775  *during the destruction of the newly built instance
2776  *of #CRParser. If set to FALSE, it is up to the caller to
2777  *eventually free it.
2778  *
2779  *Instanciates a new parser from a memory buffer.
2780  *
2781  *Returns the newly built parser, or NULL if an error arises.
2782  */
2783 CRParser *
2784 cr_parser_new_from_buf (guchar * a_buf,
2785  gulong a_len,
2786  enum CREncoding a_enc,
2787  gboolean a_free_buf)
2788 {
2789  CRParser *result = NULL;
2790  CRInput *input = NULL;
2791 
2792  g_return_val_if_fail (a_buf && a_len, NULL);
2793 
2794  input = cr_input_new_from_buf (a_buf, a_len, a_enc, a_free_buf);
2795  g_return_val_if_fail (input, NULL);
2796 
2797  result = cr_parser_new_from_input (input);
2798  if (!result) {
2799  cr_input_destroy (input);
2800  input = NULL;
2801  return NULL;
2802  }
2803  return result;
2804 }
2805 
2806 /**
2807  * cr_parser_new_from_input:
2808  * @a_input: the parser input stream to use.
2809  *
2810  * Returns a newly built parser input.
2811  */
2812 CRParser *
2814 {
2815  CRParser *result = NULL;
2816  CRTknzr *tokenizer = NULL;
2817 
2818  if (a_input) {
2819  tokenizer = cr_tknzr_new (a_input);
2820  g_return_val_if_fail (tokenizer, NULL);
2821  }
2822 
2823  result = cr_parser_new (tokenizer);
2824  g_return_val_if_fail (result, NULL);
2825 
2826  return result;
2827 }
2828 
2829 /**
2830  * cr_parser_new_from_file:
2831  * @a_file_uri: the uri of the file to parse.
2832  * @a_enc: the file encoding to use.
2833  *
2834  * Returns the newly built parser.
2835  */
2836 CRParser *
2837 cr_parser_new_from_file (const guchar * a_file_uri, enum CREncoding a_enc)
2838 {
2839  CRParser *result = NULL;
2840  CRTknzr *tokenizer = NULL;
2841 
2842  tokenizer = cr_tknzr_new_from_uri (a_file_uri, a_enc);
2843  if (!tokenizer) {
2844  cr_utils_trace_info ("Could not open input file");
2845  return NULL;
2846  }
2847 
2848  result = cr_parser_new (tokenizer);
2849  g_return_val_if_fail (result, NULL);
2850  return result;
2851 }
2852 
2853 /**
2854  * cr_parser_set_sac_handler:
2855  *@a_this: the "this pointer" of the current instance of #CRParser.
2856  *@a_handler: the handler to set.
2857  *
2858  *Sets a SAC document handler to the parser.
2859  *
2860  *Returns CR_OK upon successfull completion, an error code otherwise.
2861  */
2862 enum CRStatus
2864 {
2865  g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
2866 
2867  if (PRIVATE (a_this)->sac_handler) {
2868  cr_doc_handler_unref (PRIVATE (a_this)->sac_handler);
2869  }
2870 
2871  PRIVATE (a_this)->sac_handler = a_handler;
2872  cr_doc_handler_ref (a_handler);
2873 
2874  return CR_OK;
2875 }
2876 
2877 /**
2878  * cr_parser_get_sac_handler:
2879  *@a_this: the "this pointer" of the current instance of
2880  *#CRParser.
2881  *@a_handler: out parameter. The returned handler.
2882  *
2883  *Gets the SAC document handler.
2884  *
2885  *Returns CR_OK upon successfull completion, an error code
2886  *otherwise.
2887  */
2888 enum CRStatus
2890 {
2891  g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
2892 
2893  *a_handler = PRIVATE (a_this)->sac_handler;
2894 
2895  return CR_OK;
2896 }
2897 
2898 /**
2899  * cr_parser_set_default_sac_handler:
2900  *@a_this: a pointer to the current instance of #CRParser.
2901  *
2902  *Sets the SAC handler associated to the current instance
2903  *of #CRParser to the default SAC handler.
2904  *
2905  *Returns CR_OK upon successfull completion, an error code otherwise.
2906  */
2907 enum CRStatus
2909 {
2910  CRDocHandler *default_sac_handler = NULL;
2911  enum CRStatus status = CR_ERROR;
2912 
2913  g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
2914 
2915  default_sac_handler = cr_doc_handler_new ();
2916 
2917  cr_doc_handler_set_default_sac_handler (default_sac_handler);
2918 
2919  status = cr_parser_set_sac_handler (a_this, default_sac_handler);
2920 
2921  if (status != CR_OK) {
2922  cr_doc_handler_destroy (default_sac_handler);
2923  default_sac_handler = NULL;
2924  }
2925 
2926  return status;
2927 }
2928 
2929 /**
2930  * cr_parser_set_use_core_grammar:
2931  * @a_this: the current instance of #CRParser.
2932  * @a_use_core_grammar: where to parse against the css core grammar.
2933  *
2934  * Returns CR_OK upon succesful completion, an error code otherwise.
2935  */
2936 enum CRStatus
2938  gboolean a_use_core_grammar)
2939 {
2940  g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
2941 
2942  PRIVATE (a_this)->use_core_grammar = a_use_core_grammar;
2943 
2944  return CR_OK;
2945 }
2946 
2947 /**
2948  * cr_parser_get_use_core_grammar:
2949  * @a_this: the current instance of #CRParser.
2950  * @a_use_core_grammar: wether to use the core grammar or not.
2951  *
2952  * Returns CR_OK upon succesful completion, an error code otherwise.
2953  */
2954 enum CRStatus
2956  gboolean * a_use_core_grammar)
2957 {
2958  g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
2959 
2960  *a_use_core_grammar = PRIVATE (a_this)->use_core_grammar;
2961 
2962  return CR_OK;
2963 }
2964 
2965 /**
2966  * cr_parser_parse_file:
2967  *@a_this: a pointer to the current instance of #CRParser.
2968  *@a_file_uri: the uri to the file to load. For the time being,
2969  *@a_enc: the encoding of the file to parse.
2970  *only local files are supported.
2971  *
2972  *Parses a the given in parameter.
2973  *
2974  *Returns CR_OK upon successfull completion, an error code otherwise.
2975  */
2976 enum CRStatus
2978  const guchar * a_file_uri, enum CREncoding a_enc)
2979 {
2980  enum CRStatus status = CR_ERROR;
2981  CRTknzr *tknzr = NULL;
2982 
2983  g_return_val_if_fail (a_this && PRIVATE (a_this)
2984  && a_file_uri, CR_BAD_PARAM_ERROR);
2985 
2986  tknzr = cr_tknzr_new_from_uri (a_file_uri, a_enc);
2987 
2988  g_return_val_if_fail (tknzr != NULL, CR_ERROR);
2989 
2990  status = cr_parser_set_tknzr (a_this, tknzr);
2991  g_return_val_if_fail (status == CR_OK, CR_ERROR);
2992 
2993  status = cr_parser_parse (a_this);
2994 
2995  return status;
2996 }
2997 
2998 /**
2999  * cr_parser_parse_expr:
3000  * @a_this: the current instance of #CRParser.
3001  * @a_expr: out parameter. the parsed expression.
3002  *
3003  *Parses an expression as defined by the css2 spec in appendix
3004  *D.1:
3005  *expr: term [ operator term ]*
3006  *
3007  *
3008  * Returns CR_OK upon successful completion, an error code otherwise.
3009  */
3010 enum CRStatus
3011 cr_parser_parse_expr (CRParser * a_this, CRTerm ** a_expr)
3012 {
3013  enum CRStatus status = CR_ERROR;
3014  CRInputPos init_pos;
3015  CRTerm *expr = NULL,
3016  *expr2 = NULL;
3017  guchar next_byte = 0;
3018  gulong nb_terms = 0;
3019 
3020  g_return_val_if_fail (a_this && PRIVATE (a_this)
3021  && a_expr, CR_BAD_PARAM_ERROR);
3022 
3023  RECORD_INITIAL_POS (a_this, &init_pos);
3024 
3025  status = cr_parser_parse_term (a_this, &expr);
3026 
3027  CHECK_PARSING_STATUS (status, FALSE);
3028 
3029  for (;;) {
3030  guchar operator = 0;
3031 
3032  status = cr_tknzr_peek_byte (PRIVATE (a_this)->tknzr,
3033  1, &next_byte);
3034  if (status != CR_OK) {
3035  if (status == CR_END_OF_INPUT_ERROR) {
3036  /*
3037  if (!nb_terms)
3038  {
3039  goto error ;
3040  }
3041  */
3042  status = CR_OK;
3043  break;
3044  } else {
3045  goto error;
3046  }
3047  }
3048 
3049  if (next_byte == '/' || next_byte == ',') {
3050  READ_NEXT_BYTE (a_this, &operator);
3051  }
3052 
3054 
3055  status = cr_parser_parse_term (a_this, &expr2);
3056 
3057  if (status != CR_OK || expr2 == NULL) {
3058  status = CR_OK;
3059  break;
3060  }
3061 
3062  switch (operator) {
3063  case '/':
3064  expr2->the_operator = DIVIDE;
3065  break;
3066  case ',':
3067  expr2->the_operator = COMMA;
3068 
3069  default:
3070  break;
3071  }
3072 
3073  expr = cr_term_append_term (expr, expr2);
3074  expr2 = NULL;
3075  operator = 0;
3076  nb_terms++;
3077  }
3078 
3079  if (status == CR_OK) {
3080  *a_expr = cr_term_append_term (*a_expr, expr);
3081  expr = NULL;
3082 
3083  cr_parser_clear_errors (a_this);
3084  return CR_OK;
3085  }
3086 
3087  error:
3088 
3089  if (expr) {
3090  cr_term_destroy (expr);
3091  expr = NULL;
3092  }
3093 
3094  if (expr2) {
3095  cr_term_destroy (expr2);
3096  expr2 = NULL;
3097  }
3098 
3099  cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
3100 
3101  return status;
3102 }
3103 
3104 /**
3105  * cr_parser_parse_prio:
3106  *@a_this: the current instance of #CRParser.
3107  *@a_prio: a string representing the priority.
3108  *Today, only "!important" is returned as only this
3109  *priority is defined by css2.
3110  *
3111  *Parses a declaration priority as defined by
3112  *the css2 grammar in appendix C:
3113  *prio: IMPORTANT_SYM S*
3114  *
3115  * Returns CR_OK upon successful completion, an error code otherwise.
3116  */
3117 enum CRStatus
3119 {
3120  enum CRStatus status = CR_ERROR;
3121  CRInputPos init_pos;
3122  CRToken *token = NULL;
3123 
3124  g_return_val_if_fail (a_this && PRIVATE (a_this)
3125  && a_prio
3126  && *a_prio == NULL, CR_BAD_PARAM_ERROR);
3127 
3128  RECORD_INITIAL_POS (a_this, &init_pos);
3129 
3130  status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
3131  if (status == CR_END_OF_INPUT_ERROR) {
3132  goto error;
3133  }
3134  ENSURE_PARSING_COND (status == CR_OK
3135  && token && token->type == IMPORTANT_SYM_TK);
3136 
3138  *a_prio = cr_string_new_from_string ("!important");
3139  cr_token_destroy (token);
3140  token = NULL;
3141  return CR_OK;
3142 
3143  error:
3144  if (token) {
3145  cr_token_destroy (token);
3146  token = NULL;
3147  }
3148  cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
3149 
3150  return status;
3151 }
3152 
3153 /**
3154  * cr_parser_parse_declaration:
3155  *@a_this: the "this pointer" of the current instance of #CRParser.
3156  *@a_property: the successfully parsed property. The caller
3157  * *must* free the returned pointer.
3158  *@a_expr: the expression that represents the attribute value.
3159  *The caller *must* free the returned pointer.
3160  *
3161  *TODO: return the parsed priority, so that
3162  *upper layers can take benefit from it.
3163  *Parses a "declaration" as defined by the css2 spec in appendix D.1:
3164  *declaration ::= [property ':' S* expr prio?]?
3165  *
3166  *Returns CR_OK upon successfull completion, an error code otherwise.
3167  */
3168 enum CRStatus
3170  CRString ** a_property,
3171  CRTerm ** a_expr, gboolean * a_important)
3172 {
3173  enum CRStatus status = CR_ERROR;
3174  CRInputPos init_pos;
3175  guint32 cur_char = 0;
3176  CRTerm *expr = NULL;
3177  CRString *prio = NULL;
3178 
3179  g_return_val_if_fail (a_this && PRIVATE (a_this)
3180  && a_property && a_expr
3181  && a_important, CR_BAD_PARAM_ERROR);
3182 
3183  RECORD_INITIAL_POS (a_this, &init_pos);
3184 
3185  status = cr_parser_parse_property (a_this, a_property);
3186 
3187  if (status == CR_END_OF_INPUT_ERROR)
3188  goto error;
3189 
3191  (a_this, status, FALSE,
3192  (const guchar *) "while parsing declaration: next property is malformed",
3193  CR_SYNTAX_ERROR);
3194 
3195  READ_NEXT_CHAR (a_this, &cur_char);
3196 
3197  if (cur_char != ':') {
3198  status = CR_PARSING_ERROR;
3199  cr_parser_push_error
3200  (a_this,
3201  (const guchar *) "while parsing declaration: this char must be ':'",
3202  CR_SYNTAX_ERROR);
3203  goto error;
3204  }
3205 
3207 
3208  status = cr_parser_parse_expr (a_this, &expr);
3209 
3211  (a_this, status, FALSE,
3212  (const guchar *) "while parsing declaration: next expression is malformed",
3213  CR_SYNTAX_ERROR);
3214 
3216  status = cr_parser_parse_prio (a_this, &prio);
3217  if (prio) {
3218  cr_string_destroy (prio);
3219  prio = NULL;
3220  *a_important = TRUE;
3221  } else {
3222  *a_important = FALSE;
3223  }
3224  if (*a_expr) {
3225  cr_term_append_term (*a_expr, expr);
3226  expr = NULL;
3227  } else {
3228  *a_expr = expr;
3229  expr = NULL;
3230  }
3231 
3232  cr_parser_clear_errors (a_this);
3233  return CR_OK;
3234 
3235  error:
3236 
3237  if (expr) {
3238  cr_term_destroy (expr);
3239  expr = NULL;
3240  }
3241 
3242  if (*a_property) {
3243  cr_string_destroy (*a_property);
3244  *a_property = NULL;
3245  }
3246 
3247  cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
3248 
3249  return status;
3250 }
3251 
3252 /**
3253  * cr_parser_parse_statement_core:
3254  *@a_this: the current instance of #CRParser.
3255  *
3256  *Parses a statement as defined by the css core grammar in
3257  *chapter 4.1 of the css2 spec.
3258  *statement : ruleset | at-rule;
3259  *
3260  *Returns CR_OK upon successfull completion, an error code otherwise.
3261  */
3262 enum CRStatus
3264 {
3265  CRToken *token = NULL;
3266  CRInputPos init_pos;
3267  enum CRStatus status = CR_ERROR;
3268 
3269  g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
3270 
3271  RECORD_INITIAL_POS (a_this, &init_pos);
3272 
3273  status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
3274 
3275  ENSURE_PARSING_COND (status == CR_OK && token);
3276 
3277  switch (token->type) {
3278  case ATKEYWORD_TK:
3279  case IMPORT_SYM_TK:
3280  case PAGE_SYM_TK:
3281  case MEDIA_SYM_TK:
3282  case FONT_FACE_SYM_TK:
3283  case CHARSET_SYM_TK:
3284  cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
3285  token = NULL;
3286  status = cr_parser_parse_atrule_core (a_this);
3287  CHECK_PARSING_STATUS (status, TRUE);
3288  break;
3289 
3290  default:
3291  cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
3292  token = NULL;
3293  status = cr_parser_parse_ruleset_core (a_this);
3294  cr_parser_clear_errors (a_this);
3295  CHECK_PARSING_STATUS (status, TRUE);
3296  }
3297 
3298  return CR_OK;
3299 
3300  error:
3301  if (token) {
3302  cr_token_destroy (token);
3303  token = NULL;
3304  }
3305 
3306  cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
3307 
3308  return status;
3309 }
3310 
3311 /**
3312  * cr_parser_parse_ruleset:
3313  *@a_this: the "this pointer" of the current instance of #CRParser.
3314  *
3315  *Parses a "ruleset" as defined in the css2 spec at appendix D.1.
3316  *ruleset ::= selector [ ',' S* selector ]*
3317  *'{' S* declaration? [ ';' S* declaration? ]* '}' S*;
3318  *
3319  *This methods calls the the SAC handler on the relevant SAC handler
3320  *callbacks whenever it encounters some specific constructions.
3321  *See the documentation of #CRDocHandler (the SAC handler) to know
3322  *when which SAC handler is called.
3323  *
3324  *Returns CR_OK upon successfull completion, an error code otherwise.
3325  */
3326 enum CRStatus
3328 {
3329  enum CRStatus status = CR_OK;
3330  CRInputPos init_pos;
3331  guint32 cur_char = 0,
3332  next_char = 0;
3333  CRString *property = NULL;
3334  CRTerm *expr = NULL;
3335  CRSimpleSel *simple_sels = NULL;
3336  CRSelector *selector = NULL;
3337  gboolean start_selector = FALSE,
3338  is_important = FALSE;
3339  CRParsingLocation end_parsing_location;
3340 
3341  g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
3342 
3343  RECORD_INITIAL_POS (a_this, &init_pos);
3344 
3345  status = cr_parser_parse_selector (a_this, &selector);
3346  CHECK_PARSING_STATUS (status, FALSE);
3347 
3348  READ_NEXT_CHAR (a_this, &cur_char);
3349 
3351  (a_this, cur_char == '{',
3352  (const guchar *) "while parsing rulset: current char should be '{'",
3353  CR_SYNTAX_ERROR);
3354 
3355  if (PRIVATE (a_this)->sac_handler
3356  && PRIVATE (a_this)->sac_handler->start_selector) {
3357  /*
3358  *the selector is ref counted so that the parser's user
3359  *can choose to keep it.
3360  */
3361  if (selector) {
3362  cr_selector_ref (selector);
3363  }
3364 
3365  PRIVATE (a_this)->sac_handler->start_selector
3366  (PRIVATE (a_this)->sac_handler, selector);
3367  start_selector = TRUE;
3368  }
3369 
3371 
3372  PRIVATE (a_this)->state = TRY_PARSE_RULESET_STATE;
3373 
3374  status = cr_parser_parse_declaration (a_this, &property,
3375  &expr,
3376  &is_important);
3377  if (expr) {
3378  cr_term_ref (expr);
3379  }
3380  if (status == CR_OK
3381  && PRIVATE (a_this)->sac_handler
3382  && PRIVATE (a_this)->sac_handler->property) {
3383  PRIVATE (a_this)->sac_handler->property
3384  (PRIVATE (a_this)->sac_handler, property, expr,
3385  is_important);
3386  }
3387  if (status == CR_OK) {
3388  /*
3389  *free the allocated
3390  *'property' and 'term' before parsing
3391  *next declarations.
3392  */
3393  if (property) {
3394  cr_string_destroy (property);
3395  property = NULL;
3396  }
3397  if (expr) {
3398  cr_term_unref (expr);
3399  expr = NULL;
3400  }
3401  } else {/*status != CR_OK*/
3402  guint32 c = 0 ;
3403  /*
3404  *test if we have reached '}', which
3405  *would mean that we are parsing an empty ruleset (eg. x{ })
3406  *In that case, goto end_of_ruleset.
3407  */
3408  status = cr_tknzr_peek_char (PRIVATE (a_this)->tknzr, &c) ;
3409  if (status == CR_OK && c == '}') {
3410  status = CR_OK ;
3411  goto end_of_ruleset ;
3412  }
3413  }
3415  (a_this, status, FALSE,
3416  (const guchar *) "while parsing ruleset: next construction should be a declaration",
3417  CR_SYNTAX_ERROR);
3418 
3419  for (;;) {
3420  PEEK_NEXT_CHAR (a_this, &next_char);
3421  if (next_char != ';')
3422  break;
3423 
3424  /*consume the ';' char */
3425  READ_NEXT_CHAR (a_this, &cur_char);
3426 
3428 
3429  status = cr_parser_parse_declaration (a_this, &property,
3430  &expr, &is_important);
3431 
3432  if (expr) {
3433  cr_term_ref (expr);
3434  }
3435  if (status == CR_OK
3436  && PRIVATE (a_this)->sac_handler
3437  && PRIVATE (a_this)->sac_handler->property) {
3438  PRIVATE (a_this)->sac_handler->property
3439  (PRIVATE (a_this)->sac_handler,
3440  property, expr, is_important);
3441  }
3442  if (property) {
3443  cr_string_destroy (property);
3444  property = NULL;
3445  }
3446  if (expr) {
3447  cr_term_unref (expr);
3448  expr = NULL;
3449  }
3450  }
3451 
3452  end_of_ruleset:
3454  cr_parser_get_parsing_location (a_this, &end_parsing_location);
3455  READ_NEXT_CHAR (a_this, &cur_char);
3457  (a_this, cur_char == '}',
3458  (const guchar *) "while parsing rulset: current char must be a '}'",
3459  CR_SYNTAX_ERROR);
3460 
3461  selector->location = end_parsing_location;
3462  if (PRIVATE (a_this)->sac_handler
3463  && PRIVATE (a_this)->sac_handler->end_selector) {
3464  PRIVATE (a_this)->sac_handler->end_selector
3465  (PRIVATE (a_this)->sac_handler, selector);
3466  start_selector = FALSE;
3467  }
3468 
3469  if (expr) {
3470  cr_term_unref (expr);
3471  expr = NULL;
3472  }
3473 
3474  if (simple_sels) {
3475  cr_simple_sel_destroy (simple_sels);
3476  simple_sels = NULL;
3477  }
3478 
3479  if (selector) {
3480  cr_selector_unref (selector);
3481  selector = NULL;
3482  }
3483 
3484  cr_parser_clear_errors (a_this);
3485  PRIVATE (a_this)->state = RULESET_PARSED_STATE;
3486 
3487  return CR_OK;
3488 
3489  error:
3490  if (start_selector == TRUE
3491  && PRIVATE (a_this)->sac_handler
3492  && PRIVATE (a_this)->sac_handler->error) {
3493  PRIVATE (a_this)->sac_handler->error
3494  (PRIVATE (a_this)->sac_handler);
3495  }
3496  if (expr) {
3497  cr_term_unref (expr);
3498  expr = NULL;
3499  }
3500  if (simple_sels) {
3501  cr_simple_sel_destroy (simple_sels);
3502  simple_sels = NULL;
3503  }
3504  if (property) {
3505  cr_string_destroy (property);
3506  }
3507  if (selector) {
3508  cr_selector_unref (selector);
3509  selector = NULL;
3510  }
3511 
3512  cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
3513 
3514  return status;
3515 }
3516 
3517 /**
3518  * cr_parser_parse_import:
3519  *@a_this: the "this pointer" of the current instance
3520  *of #CRParser.
3521  *@a_media_list: out parameter. A linked list of
3522  *#CRString
3523  *Each CRString is a string that contains
3524  *a 'medium' declaration part of the successfully
3525  *parsed 'import' declaration.
3526  *@a_import_string: out parameter.
3527  *A string that contains the 'import
3528  *string". The import string can be either an uri (if it starts with
3529  *the substring "uri(") or a any other css2 string. Note that
3530  * *a_import_string must be initially set to NULL or else, this function
3531  *will return CR_BAD_PARAM_ERROR.
3532  *@a_location: the location (line, column) where the import has been parsed
3533  *
3534  *Parses an 'import' declaration as defined in the css2 spec
3535  *in appendix D.1:
3536  *
3537  *import ::=
3538  *\@import [STRING|URI] S* [ medium [ ',' S* medium]* ]? ';' S*
3539  *
3540  *Returns CR_OK upon sucessfull completion, an error code otherwise.
3541  */
3542 enum CRStatus
3544  GList ** a_media_list,
3545  CRString ** a_import_string,
3546  CRParsingLocation *a_location)
3547 {
3548  enum CRStatus status = CR_OK;
3549  CRInputPos init_pos;
3550  guint32 cur_char = 0,
3551  next_char = 0;
3552  CRString *medium = NULL;
3553 
3554  g_return_val_if_fail (a_this
3555  && a_import_string
3556  && (*a_import_string == NULL),
3558 
3559  RECORD_INITIAL_POS (a_this, &init_pos);
3560 
3561  if (BYTE (a_this, 1, NULL) == '@'
3562  && BYTE (a_this, 2, NULL) == 'i'
3563  && BYTE (a_this, 3, NULL) == 'm'
3564  && BYTE (a_this, 4, NULL) == 'p'
3565  && BYTE (a_this, 5, NULL) == 'o'
3566  && BYTE (a_this, 6, NULL) == 'r'
3567  && BYTE (a_this, 7, NULL) == 't') {
3568  SKIP_CHARS (a_this, 1);
3569  if (a_location) {
3571  (a_this, a_location) ;
3572  }
3573  SKIP_CHARS (a_this, 6);
3574  status = CR_OK;
3575  } else {
3576  status = CR_PARSING_ERROR;
3577  goto error;
3578  }
3579 
3581 
3582  PRIVATE (a_this)->state = TRY_PARSE_IMPORT_STATE;
3583 
3584  PEEK_NEXT_CHAR (a_this, &next_char);
3585 
3586  if (next_char == '"' || next_char == '\'') {
3587  status = cr_parser_parse_string (a_this, a_import_string);
3588 
3589  CHECK_PARSING_STATUS (status, FALSE);
3590  } else {
3591  status = cr_parser_parse_uri (a_this, a_import_string);
3592 
3593  CHECK_PARSING_STATUS (status, FALSE);
3594  }
3595 
3597 
3598  status = cr_parser_parse_ident (a_this, &medium);
3599 
3600  if (status == CR_OK && medium) {
3601  *a_media_list = g_list_append (*a_media_list, medium);
3602  medium = NULL;
3603  }
3604 
3606 
3607  for (; status == CR_OK;) {
3608  if ((status = cr_tknzr_peek_char (PRIVATE (a_this)->tknzr,
3609  &next_char)) != CR_OK) {
3610  if (status == CR_END_OF_INPUT_ERROR) {
3611  status = CR_OK;
3612  goto okay;
3613  }
3614  goto error;
3615  }
3616 
3617  if (next_char == ',') {
3618  READ_NEXT_CHAR (a_this, &cur_char);
3619  } else {
3620  break;
3621  }
3622 
3624 
3625  status = cr_parser_parse_ident (a_this, &medium);
3626 
3628 
3629  if ((status == CR_OK) && medium) {
3630  *a_media_list = g_list_append (*a_media_list, medium);
3631 
3632  medium = NULL;
3633  }
3634 
3635  CHECK_PARSING_STATUS (status, FALSE);
3637  }
3639  READ_NEXT_CHAR (a_this, &cur_char);
3640  ENSURE_PARSING_COND (cur_char == ';');
3642  okay:
3643  cr_parser_clear_errors (a_this);
3644  PRIVATE (a_this)->state = IMPORT_PARSED_STATE;
3645 
3646  return CR_OK;
3647 
3648  error:
3649 
3650  if (*a_media_list) {
3651  GList *cur = NULL;
3652 
3653  /*
3654  *free each element of *a_media_list.
3655  *Note that each element of *a_medium list *must*
3656  *be a GString* or else, the code that is coming next
3657  *will corrupt the memory and lead to hard to debug
3658  *random crashes.
3659  *This is where C++ and its compile time
3660  *type checking mecanism (through STL containers) would
3661  *have prevented us to go through this hassle.
3662  */
3663  for (cur = *a_media_list; cur; cur = cur->next) {
3664  if (cur->data) {
3665  cr_string_destroy (cur->data);
3666  }
3667  }
3668 
3669  g_list_free (*a_media_list);
3670  *a_media_list = NULL;
3671  }
3672 
3673  if (*a_import_string) {
3674  cr_string_destroy (*a_import_string);
3675  *a_import_string = NULL;
3676  }
3677 
3678  if (medium) {
3679  cr_string_destroy (medium);
3680  medium = NULL;
3681  }
3682 
3683  cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
3684 
3685  return status;
3686 }
3687 
3688 /**
3689  * cr_parser_parse_media:
3690  *@a_this: the "this pointer" of the current instance of #CRParser.
3691  *
3692  *Parses a 'media' declaration as specified in the css2 spec at
3693  *appendix D.1:
3694  *
3695  *media ::= \@media S* medium [ ',' S* medium ]* '{' S* ruleset* '}' S*
3696  *
3697  *Note that this function calls the required sac handlers during the parsing
3698  *to notify media productions. See #CRDocHandler to know the callback called
3699  *during \@media parsing.
3700  *
3701  *Returns CR_OK upon successfull completion, an error code otherwise.
3702  */
3703 enum CRStatus
3705 {
3706  enum CRStatus status = CR_OK;
3707  CRInputPos init_pos;
3708  CRToken *token = NULL;
3709  guint32 next_char = 0,
3710  cur_char = 0;
3711  CRString *medium = NULL;
3712  GList *media_list = NULL;
3713  CRParsingLocation location = {0} ;
3714 
3715  g_return_val_if_fail (a_this
3716  && PRIVATE (a_this),
3718 
3719  RECORD_INITIAL_POS (a_this, &init_pos);
3720 
3721  status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
3722  &token);
3723  ENSURE_PARSING_COND (status == CR_OK
3724  && token
3725  && token->type == MEDIA_SYM_TK);
3726  cr_parsing_location_copy (&location, &token->location) ;
3727  cr_token_destroy (token);
3728  token = NULL;
3729 
3731 
3732  status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
3733  ENSURE_PARSING_COND (status == CR_OK
3734  && token && token->type == IDENT_TK);
3735 
3736  medium = token->u.str;
3737  token->u.str = NULL;
3738  cr_token_destroy (token);
3739  token = NULL;
3740 
3741  if (medium) {
3742  media_list = g_list_append (media_list, medium);
3743  medium = NULL;
3744  }
3745 
3746  for (; status == CR_OK;) {
3748  PEEK_NEXT_CHAR (a_this, &next_char);
3749 
3750  if (next_char == ',') {
3751  READ_NEXT_CHAR (a_this, &cur_char);
3752  } else {
3753  break;
3754  }
3755 
3757 
3758  status = cr_parser_parse_ident (a_this, &medium);
3759 
3760  CHECK_PARSING_STATUS (status, FALSE);
3761 
3762  if (medium) {
3763  media_list = g_list_append (media_list, medium);
3764  medium = NULL;
3765  }
3766  }
3767 
3768  READ_NEXT_CHAR (a_this, &cur_char);
3769 
3770  ENSURE_PARSING_COND (cur_char == '{');
3771 
3772  /*
3773  *call the SAC handler api here.
3774  */
3775  if (PRIVATE (a_this)->sac_handler
3776  && PRIVATE (a_this)->sac_handler->start_media) {
3777  PRIVATE (a_this)->sac_handler->start_media
3778  (PRIVATE (a_this)->sac_handler, media_list,
3779  &location);
3780  }
3781 
3783 
3784  PRIVATE (a_this)->state = TRY_PARSE_MEDIA_STATE;
3785 
3786  for (; status == CR_OK;) {
3787  status = cr_parser_parse_ruleset (a_this);
3789  }
3790 
3791  READ_NEXT_CHAR (a_this, &cur_char);
3792 
3793  ENSURE_PARSING_COND (cur_char == '}');
3794 
3795  /*
3796  *call the right SAC handler api here.
3797  */
3798  if (PRIVATE (a_this)->sac_handler
3799  && PRIVATE (a_this)->sac_handler->end_media) {
3800  PRIVATE (a_this)->sac_handler->end_media
3801  (PRIVATE (a_this)->sac_handler, media_list);
3802  }
3803 
3805 
3806  /*
3807  *Then, free the data structures passed to
3808  *the last call to the SAC handler.
3809  */
3810  if (medium) {
3811  cr_string_destroy (medium);
3812  medium = NULL;
3813  }
3814 
3815  if (media_list) {
3816  GList *cur = NULL;
3817 
3818  for (cur = media_list; cur; cur = cur->next) {
3819  cr_string_destroy (cur->data);
3820  }
3821 
3822  g_list_free (media_list);
3823  media_list = NULL;
3824  }
3825 
3826  cr_parser_clear_errors (a_this);
3827  PRIVATE (a_this)->state = MEDIA_PARSED_STATE;
3828 
3829  return CR_OK;
3830 
3831  error:
3832 
3833  if (token) {
3834  cr_token_destroy (token);
3835  token = NULL;
3836  }
3837 
3838  if (medium) {
3839  cr_string_destroy (medium);
3840  medium = NULL;
3841  }
3842 
3843  if (media_list) {
3844  GList *cur = NULL;
3845 
3846  for (cur = media_list; cur; cur = cur->next) {
3847  cr_string_destroy (cur->data);
3848  }
3849 
3850  g_list_free (media_list);
3851  media_list = NULL;
3852  }
3853 
3854  cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
3855 
3856  return status;
3857 }
3858 
3859 /**
3860  * cr_parser_parse_page:
3861  *@a_this: the "this pointer" of the current instance of #CRParser.
3862  *
3863  *Parses '\@page' rule as specified in the css2 spec in appendix D.1:
3864  *page ::= PAGE_SYM S* IDENT? pseudo_page? S*
3865  *'{' S* declaration [ ';' S* declaration ]* '}' S*
3866  *
3867  *This function also calls the relevant SAC handlers whenever it
3868  *encounters a construction that must
3869  *be reported to the calling application.
3870  *
3871  *Returns CR_OK upon successfull completion, an error code otherwise.
3872  */
3873 enum CRStatus
3875 {
3876  enum CRStatus status = CR_OK;
3877  CRInputPos init_pos;
3878  CRToken *token = NULL;
3879  CRTerm *css_expression = NULL;
3880  CRString *page_selector = NULL,
3881  *page_pseudo_class = NULL,
3882  *property = NULL;
3883  gboolean important = TRUE;
3884  CRParsingLocation location = {0} ;
3885 
3886  g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
3887 
3888  RECORD_INITIAL_POS (a_this, &init_pos);
3889 
3890  status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
3891  &token) ;
3892  ENSURE_PARSING_COND (status == CR_OK
3893  && token
3894  && token->type == PAGE_SYM_TK);
3895 
3896  cr_parsing_location_copy (&location, &token->location) ;
3897  cr_token_destroy (token);
3898  token = NULL;
3899 
3901 
3902  status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
3903  ENSURE_PARSING_COND (status == CR_OK && token);
3904 
3905  if (token->type == IDENT_TK) {
3906  page_selector = token->u.str;
3907  token->u.str = NULL;
3908  cr_token_destroy (token);
3909  token = NULL;
3910  } else {
3911  cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
3912  token = NULL;
3913  }
3914 
3915  /*
3916  *try to parse pseudo_page
3917  */
3919  status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
3920  ENSURE_PARSING_COND (status == CR_OK && token);
3921 
3922  if (token->type == DELIM_TK && token->u.unichar == ':') {
3923  cr_token_destroy (token);
3924  token = NULL;
3925  status = cr_parser_parse_ident (a_this, &page_pseudo_class);
3926  CHECK_PARSING_STATUS (status, FALSE);
3927  } else {
3928  cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
3929  token = NULL;
3930  }
3931 
3932  /*
3933  *parse_block
3934  *
3935  */
3937 
3938  status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
3939 
3940  ENSURE_PARSING_COND (status == CR_OK && token
3941  && token->type == CBO_TK);
3942 
3943  cr_token_destroy (token);
3944  token = NULL;
3945 
3946  /*
3947  *Call the appropriate SAC handler here.
3948  */
3949  if (PRIVATE (a_this)->sac_handler
3950  && PRIVATE (a_this)->sac_handler->start_page) {
3951  PRIVATE (a_this)->sac_handler->start_page
3952  (PRIVATE (a_this)->sac_handler,
3953  page_selector, page_pseudo_class,
3954  &location);
3955  }
3957 
3958  PRIVATE (a_this)->state = TRY_PARSE_PAGE_STATE;
3959 
3960  status = cr_parser_parse_declaration (a_this, &property,
3961  &css_expression,
3962  &important);
3963  ENSURE_PARSING_COND (status == CR_OK);
3964 
3965  /*
3966  *call the relevant SAC handler here...
3967  */
3968  if (PRIVATE (a_this)->sac_handler
3969  && PRIVATE (a_this)->sac_handler->property) {
3970  if (css_expression)
3971  cr_term_ref (css_expression);
3972 
3973  PRIVATE (a_this)->sac_handler->property
3974  (PRIVATE (a_this)->sac_handler,
3975  property, css_expression, important);
3976  }
3977  /*
3978  *... and free the data structure passed to that last
3979  *SAC handler.
3980  */
3981  if (property) {
3982  cr_string_destroy (property);
3983  property = NULL;
3984  }
3985  if (css_expression) {
3986  cr_term_unref (css_expression);
3987  css_expression = NULL;
3988  }
3989 
3990  for (;;) {
3991  /*parse the other ';' separated declarations */
3992  if (token) {
3993  cr_token_destroy (token);
3994  token = NULL;
3995  }
3996  status = cr_tknzr_get_next_token
3997  (PRIVATE (a_this)->tknzr, &token);
3998 
3999  ENSURE_PARSING_COND (status == CR_OK && token);
4000 
4001  if (token->type != SEMICOLON_TK) {
4003  (PRIVATE (a_this)->tknzr,
4004  token);
4005  token = NULL ;
4006  break;
4007  }
4008 
4009  cr_token_destroy (token);
4010  token = NULL;
4012 
4013  status = cr_parser_parse_declaration (a_this, &property,
4014  &css_expression,
4015  &important);
4016  if (status != CR_OK)
4017  break ;
4018 
4019  /*
4020  *call the relevant SAC handler here...
4021  */
4022  if (PRIVATE (a_this)->sac_handler
4023  && PRIVATE (a_this)->sac_handler->property) {
4024  cr_term_ref (css_expression);
4025  PRIVATE (a_this)->sac_handler->property
4026  (PRIVATE (a_this)->sac_handler,
4027  property, css_expression, important);
4028  }
4029  /*
4030  *... and free the data structure passed to that last
4031  *SAC handler.
4032  */
4033  if (property) {
4034  cr_string_destroy (property);
4035  property = NULL;
4036  }
4037  if (css_expression) {
4038  cr_term_unref (css_expression);
4039  css_expression = NULL;
4040  }
4041  }
4043  (a_this) ;
4044  if (token) {
4045  cr_token_destroy (token) ;
4046  token = NULL ;
4047  }
4048 
4049  status = cr_tknzr_get_next_token
4050  (PRIVATE (a_this)->tknzr, &token);
4051  ENSURE_PARSING_COND (status == CR_OK
4052  && token
4053  && token->type == CBC_TK) ;
4054  cr_token_destroy (token) ;
4055  token = NULL ;
4056  /*
4057  *call the relevant SAC handler here.
4058  */
4059  if (PRIVATE (a_this)->sac_handler
4060  && PRIVATE (a_this)->sac_handler->end_page) {
4061  PRIVATE (a_this)->sac_handler->end_page
4062  (PRIVATE (a_this)->sac_handler,
4063  page_selector, page_pseudo_class);
4064  }
4065 
4066  if (page_selector) {
4067  cr_string_destroy (page_selector);
4068  page_selector = NULL;
4069  }
4070 
4071  if (page_pseudo_class) {
4072  cr_string_destroy (page_pseudo_class);
4073  page_pseudo_class = NULL;
4074  }
4075 
4077 
4078  /*here goes the former implem of this function ... */
4079 
4080  cr_parser_clear_errors (a_this);
4081  PRIVATE (a_this)->state = PAGE_PARSED_STATE;
4082 
4083  return CR_OK;
4084 
4085  error:
4086  if (token) {
4087  cr_token_destroy (token);
4088  token = NULL;
4089  }
4090  if (page_selector) {
4091  cr_string_destroy (page_selector);
4092  page_selector = NULL;
4093  }
4094  if (page_pseudo_class) {
4095  cr_string_destroy (page_pseudo_class);
4096  page_pseudo_class = NULL;
4097  }
4098  if (property) {
4099  cr_string_destroy (property);
4100  property = NULL;
4101  }
4102  if (css_expression) {
4103  cr_term_destroy (css_expression);
4104  css_expression = NULL;
4105  }
4106  cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
4107  return status;
4108 }
4109 
4110 /**
4111  * cr_parser_parse_charset:
4112  *@a_this: the "this pointer" of the current instance of #CRParser.
4113  *@a_value: out parameter. The actual parsed value of the charset
4114  *declararation. Note that for safety check reasons, *a_value must be
4115  *set to NULL.
4116  *@a_charset_sym_location: the parsing location of the charset rule
4117  *
4118  *Parses a charset declaration as defined implictly by the css2 spec in
4119  *appendix D.1:
4120  *charset ::= CHARSET_SYM S* STRING S* ';'
4121  *
4122  *Returns CR_OK upon successfull completion, an error code otherwise.
4123  */
4124 enum CRStatus
4126  CRParsingLocation *a_charset_sym_location)
4127 {
4128  enum CRStatus status = CR_OK;
4129  CRInputPos init_pos;
4130  CRToken *token = NULL;
4131  CRString *charset_str = NULL;
4132 
4133  g_return_val_if_fail (a_this && a_value
4134  && (*a_value == NULL),
4136 
4137  RECORD_INITIAL_POS (a_this, &init_pos);
4138 
4139  status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
4140 
4141  ENSURE_PARSING_COND (status == CR_OK
4142  && token && token->type == CHARSET_SYM_TK);
4143  if (a_charset_sym_location) {
4144  cr_parsing_location_copy (a_charset_sym_location,
4145  &token->location) ;
4146  }
4147  cr_token_destroy (token);
4148  token = NULL;
4149 
4150  PRIVATE (a_this)->state = TRY_PARSE_CHARSET_STATE;
4151 
4153 
4154  status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
4155  ENSURE_PARSING_COND (status == CR_OK
4156  && token && token->type == STRING_TK);
4157  charset_str = token->u.str;
4158  token->u.str = NULL;
4159  cr_token_destroy (token);
4160  token = NULL;
4161 
4163 
4164  status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
4165 
4166  ENSURE_PARSING_COND (status == CR_OK
4167  && token && token->type == SEMICOLON_TK);
4168  cr_token_destroy (token);
4169  token = NULL;
4170 
4171  if (charset_str) {
4172  *a_value = charset_str;
4173  charset_str = NULL;
4174  }
4175 
4176  PRIVATE (a_this)->state = CHARSET_PARSED_STATE;
4177  return CR_OK;
4178 
4179  error:
4180 
4181  if (token) {
4182  cr_token_destroy (token);
4183  token = NULL;
4184  }
4185 
4186  if (*a_value) {
4187  cr_string_destroy (*a_value);
4188  *a_value = NULL;
4189  }
4190 
4191  if (charset_str) {
4192  cr_string_destroy (charset_str);
4193  charset_str = NULL;
4194  }
4195 
4196  cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
4197 
4198  return status;
4199 }
4200 
4201 /**
4202  * cr_parser_parse_font_face:
4203  *@a_this: the current instance of #CRParser.
4204  *
4205  *Parses the "\@font-face" rule specified in the css1 spec in
4206  *appendix D.1:
4207  *
4208  *font_face ::= FONT_FACE_SYM S*
4209  *'{' S* declaration [ ';' S* declaration ]* '}' S*
4210  *
4211  *This function will call SAC handlers whenever it is necessary.
4212  *
4213  *Returns CR_OK upon successfull completion, an error code otherwise.
4214  */
4215 enum CRStatus
4217 {
4218  enum CRStatus status = CR_ERROR;
4219  CRInputPos init_pos;
4220  CRString *property = NULL;
4221  CRTerm *css_expression = NULL;
4222  CRToken *token = NULL;
4223  gboolean important = FALSE;
4224  guint32 next_char = 0,
4225  cur_char = 0;
4226  CRParsingLocation location = {0} ;
4227 
4228  g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
4229 
4230  RECORD_INITIAL_POS (a_this, &init_pos);
4231 
4232  status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
4233  ENSURE_PARSING_COND (status == CR_OK
4234  && token
4235  && token->type == FONT_FACE_SYM_TK);
4236 
4238  if (token) {
4239  cr_parsing_location_copy (&location,
4240  &token->location) ;
4241  cr_token_destroy (token);
4242  token = NULL;
4243  }
4244  status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
4245  &token);
4246  ENSURE_PARSING_COND (status == CR_OK && token
4247  && token->type == CBO_TK);
4248  if (token) {
4249  cr_token_destroy (token);
4250  token = NULL;
4251  }
4252  /*
4253  *here, call the relevant SAC handler.
4254  */
4255  if (PRIVATE (a_this)->sac_handler
4256  && PRIVATE (a_this)->sac_handler->start_font_face) {
4257  PRIVATE (a_this)->sac_handler->start_font_face
4258  (PRIVATE (a_this)->sac_handler, &location);
4259  }
4260  PRIVATE (a_this)->state = TRY_PARSE_FONT_FACE_STATE;
4261  /*
4262  *and resume the parsing.
4263  */
4265  status = cr_parser_parse_declaration (a_this, &property,
4266  &css_expression, &important);
4267  if (status == CR_OK) {
4268  /*
4269  *here, call the relevant SAC handler.
4270  */
4271  cr_term_ref (css_expression);
4272  if (PRIVATE (a_this)->sac_handler &&
4273  PRIVATE (a_this)->sac_handler->property) {
4274  PRIVATE (a_this)->sac_handler->property
4275  (PRIVATE (a_this)->sac_handler,
4276  property, css_expression, important);
4277  }
4278  ENSURE_PARSING_COND (css_expression && property);
4279  }
4280  /*free the data structures allocated during last parsing. */
4281  if (property) {
4282  cr_string_destroy (property);
4283  property = NULL;
4284  }
4285  if (css_expression) {
4286  cr_term_unref (css_expression);
4287  css_expression = NULL;
4288  }
4289  for (;;) {
4290  PEEK_NEXT_CHAR (a_this, &next_char);
4291  if (next_char == ';') {
4292  READ_NEXT_CHAR (a_this, &cur_char);
4293  } else {
4294  break;
4295  }
4297  status = cr_parser_parse_declaration (a_this,
4298  &property,
4299  &css_expression,
4300  &important);
4301  if (status != CR_OK)
4302  break;
4303  /*
4304  *here, call the relevant SAC handler.
4305  */
4306  cr_term_ref (css_expression);
4307  if (PRIVATE (a_this)->sac_handler->property) {
4308  PRIVATE (a_this)->sac_handler->property
4309  (PRIVATE (a_this)->sac_handler,
4310  property, css_expression, important);
4311  }
4312  /*
4313  *Then, free the data structures allocated during
4314  *last parsing.
4315  */
4316  if (property) {
4317  cr_string_destroy (property);
4318  property = NULL;
4319  }
4320  if (css_expression) {
4321  cr_term_unref (css_expression);
4322  css_expression = NULL;
4323  }
4324  }
4326  READ_NEXT_CHAR (a_this, &cur_char);
4327  ENSURE_PARSING_COND (cur_char == '}');
4328  /*
4329  *here, call the relevant SAC handler.
4330  */
4331  if (PRIVATE (a_this)->sac_handler->end_font_face) {
4332  PRIVATE (a_this)->sac_handler->end_font_face
4333  (PRIVATE (a_this)->sac_handler);
4334  }
4336 
4337  if (token) {
4338  cr_token_destroy (token);
4339  token = NULL;
4340  }
4341  cr_parser_clear_errors (a_this);
4342  PRIVATE (a_this)->state = FONT_FACE_PARSED_STATE;
4343  return CR_OK;
4344 
4345  error:
4346  if (token) {
4347  cr_token_destroy (token);
4348  token = NULL;
4349  }
4350  if (property) {
4351  cr_string_destroy (property);
4352  property = NULL;
4353  }
4354  if (css_expression) {
4355  cr_term_destroy (css_expression);
4356  css_expression = NULL;
4357  }
4358  cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
4359  return status;
4360 }
4361 
4362 /**
4363  * cr_parser_parse:
4364  *@a_this: the current instance of #CRParser.
4365  *
4366  *Parses the data that comes from the
4367  *input previously associated to the current instance of
4368  *#CRParser.
4369  *
4370  *Returns CR_OK upon succesful completion, an error code otherwise.
4371  */
4372 enum CRStatus
4374 {
4375  enum CRStatus status = CR_ERROR;
4376 
4377  g_return_val_if_fail (a_this && PRIVATE (a_this)
4378  && PRIVATE (a_this)->tknzr, CR_BAD_PARAM_ERROR);
4379 
4380  if (PRIVATE (a_this)->use_core_grammar == FALSE) {
4381  status = cr_parser_parse_stylesheet (a_this);
4382  } else {
4383  status = cr_parser_parse_stylesheet_core (a_this);
4384  }
4385 
4386  return status;
4387 }
4388 
4389 /**
4390  * cr_parser_set_tknzr:
4391  * @a_this: the current instance of #CRParser;
4392  * @a_tknzr: the new tokenizer.
4393  *
4394  * Returns CR_OK upon successful completion, an error code otherwise.
4395  */
4396 enum CRStatus
4397 cr_parser_set_tknzr (CRParser * a_this, CRTknzr * a_tknzr)
4398 {
4399  g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
4400 
4401  if (PRIVATE (a_this)->tknzr) {
4402  cr_tknzr_unref (PRIVATE (a_this)->tknzr);
4403  }
4404 
4405  PRIVATE (a_this)->tknzr = a_tknzr;
4406 
4407  if (a_tknzr)
4408  cr_tknzr_ref (a_tknzr);
4409 
4410  return CR_OK;
4411 }
4412 
4413 /**
4414  * cr_parser_get_tknzr:
4415  *@a_this: the current instance of #CRParser
4416  *@a_tknzr: out parameter. The returned tokenizer
4417  *
4418  *Getter of the parser's underlying tokenizer
4419  *
4420  *Returns CR_OK upon succesful completion, an error code
4421  *otherwise
4422  */
4423 enum CRStatus
4424 cr_parser_get_tknzr (CRParser * a_this, CRTknzr ** a_tknzr)
4425 {
4426  g_return_val_if_fail (a_this && PRIVATE (a_this)
4427  && a_tknzr, CR_BAD_PARAM_ERROR);
4428 
4429  *a_tknzr = PRIVATE (a_this)->tknzr;
4430  return CR_OK;
4431 }
4432 
4433 /**
4434  * cr_parser_get_parsing_location:
4435  *@a_this: the current instance of #CRParser
4436  *@a_loc: the parsing location to get.
4437  *
4438  *Gets the current parsing location.
4439  *
4440  *Returns CR_OK upon succesful completion, an error code
4441  *otherwise.
4442  */
4443 enum CRStatus
4445  CRParsingLocation *a_loc)
4446 {
4447  g_return_val_if_fail (a_this
4448  && PRIVATE (a_this)
4449  && a_loc, CR_BAD_PARAM_ERROR) ;
4450 
4452  (PRIVATE (a_this)->tknzr, a_loc) ;
4453 }
4454 
4455 /**
4456  * cr_parser_parse_buf:
4457  *@a_this: the current instance of #CRparser
4458  *@a_buf: the input buffer
4459  *@a_len: the length of the input buffer
4460  *@a_enc: the encoding of the buffer
4461  *
4462  *Parses a stylesheet from a buffer
4463  *
4464  *Returns CR_OK upon successful completion, an error code otherwise.
4465  */
4466 enum CRStatus
4468  const guchar * a_buf,
4469  gulong a_len, enum CREncoding a_enc)
4470 {
4471  enum CRStatus status = CR_ERROR;
4472  CRTknzr *tknzr = NULL;
4473 
4474  g_return_val_if_fail (a_this && PRIVATE (a_this)
4475  && a_buf, CR_BAD_PARAM_ERROR);
4476 
4477  tknzr = cr_tknzr_new_from_buf ((guchar*)a_buf, a_len, a_enc, FALSE);
4478 
4479  g_return_val_if_fail (tknzr != NULL, CR_ERROR);
4480 
4481  status = cr_parser_set_tknzr (a_this, tknzr);
4482  g_return_val_if_fail (status == CR_OK, CR_ERROR);
4483 
4484  status = cr_parser_parse (a_this);
4485 
4486  return status;
4487 }
4488 
4489 /**
4490  * cr_parser_destroy:
4491  *@a_this: the current instance of #CRParser to
4492  *destroy.
4493  *
4494  *Destroys the current instance
4495  *of #CRParser.
4496  */
4497 void
4499 {
4500  g_return_if_fail (a_this && PRIVATE (a_this));
4501 
4502  if (PRIVATE (a_this)->tknzr) {
4503  if (cr_tknzr_unref (PRIVATE (a_this)->tknzr) == TRUE)
4504  PRIVATE (a_this)->tknzr = NULL;
4505  }
4506 
4507  if (PRIVATE (a_this)->sac_handler) {
4508  cr_doc_handler_unref (PRIVATE (a_this)->sac_handler);
4509  PRIVATE (a_this)->sac_handler = NULL;
4510  }
4511 
4512  if (PRIVATE (a_this)->err_stack) {
4513  cr_parser_clear_errors (a_this);
4514  PRIVATE (a_this)->err_stack = NULL;
4515  }
4516 
4517  if (PRIVATE (a_this)) {
4518  g_free (PRIVATE (a_this));
4519  PRIVATE (a_this) = NULL;
4520  }
4521 
4522  if (a_this) {
4523  g_free (a_this);
4524  a_this = NULL; /*useless. Just for the sake of coherence */
4525  }
4526 }
cr_parser_parse_buf
enum CRStatus cr_parser_parse_buf(CRParser *a_this, const guchar *a_buf, gulong a_len, enum CREncoding a_enc)
cr_parser_parse_buf: @a_this: the current instance of #CRparser @a_buf: the input buffer @a_len: the ...
Definition: cr-parser.c:4467
PERCENTAGE_TK
@ PERCENTAGE_TK
Definition: cr-token.h:62
_CRSimpleSel::name
CRString * name
Definition: cr-simple-sel.h:78
TIME_TK
@ TIME_TK
Definition: cr-token.h:59
TYPE_SELECTOR
@ TYPE_SELECTOR
Definition: cr-simple-sel.h:52
_CRAttrSel::name
CRString * name
Definition: cr-attr-sel.h:50
cr_parser_new_from_file
CRParser * cr_parser_new_from_file(const guchar *a_file_uri, enum CREncoding a_enc)
cr_parser_new_from_file: @a_file_uri: the uri of the file to parse.
Definition: cr-parser.c:2837
cr_tknzr_unref
gboolean cr_tknzr_unref(CRTknzr *a_this)
Definition: cr-tknzr.c:1668
cr_tknzr_unget_token
enum CRStatus cr_tknzr_unget_token(CRTknzr *a_this, CRToken *a_token)
Definition: cr-tknzr.c:1946
_CRParserError::byte_num
glong byte_num
Definition: cr-parser.c:85
_CRToken::unichar
guint32 unichar
Definition: cr-token.h:112
cr_parser_parse_expr
enum CRStatus cr_parser_parse_expr(CRParser *a_this, CRTerm **a_expr)
cr_parser_parse_expr: @a_this: the current instance of CRParser.
Definition: cr-parser.c:3011
_CRAttrSel::value
CRString * value
Definition: cr-attr-sel.h:51
_CRParserPriv::is_case_sensitive
gboolean is_case_sensitive
Definition: cr-parser.c:131
cr_parser_get_parsing_location
enum CRStatus cr_parser_get_parsing_location(CRParser const *a_this, CRParsingLocation *a_loc)
cr_parser_get_parsing_location: @a_this: the current instance of CRParser @a_loc: the parsing locatio...
Definition: cr-parser.c:4444
READ_NEXT_BYTE
#define READ_NEXT_BYTE(a_this, a_byte_ptr)
Reads a byte from the topmost parser input steam.
Definition: cr-parser.c:271
_CRInputPos::next_byte_index
glong next_byte_index
Definition: cr-input.h:60
cr_attr_sel_append_attr_sel
enum CRStatus cr_attr_sel_append_attr_sel(CRAttrSel *a_this, CRAttrSel *a_attr_sel)
cr_attr_sel_append_attr_sel: @a_this: the this pointer of the current instance of CRAttrSel.
Definition: cr-attr-sel.c:61
_CRAdditionalSel
Definition: cr-additional-sel.h:56
cr_parser_set_default_sac_handler
enum CRStatus cr_parser_set_default_sac_handler(CRParser *a_this)
cr_parser_set_default_sac_handler: @a_this: a pointer to the current instance of CRParser.
Definition: cr-parser.c:2908
cr_term_set_hash
enum CRStatus cr_term_set_hash(CRTerm *a_this, CRString *a_str)
Definition: cr-term.c:215
cr_parser_set_tknzr
enum CRStatus cr_parser_set_tknzr(CRParser *a_this, CRTknzr *a_tknzr)
cr_parser_set_tknzr: @a_this: the current instance of CRParser; @a_tknzr: the new tokenizer.
Definition: cr-parser.c:4397
ANGLE_TK
@ ANGLE_TK
Definition: cr-token.h:58
DELIM_TK
@ DELIM_TK
Definition: cr-token.h:75
DASHMATCH_TK
@ DASHMATCH_TK
Definition: cr-token.h:43
cr_term_set_function
enum CRStatus cr_term_set_function(CRTerm *a_this, CRString *a_func_name, CRTerm *a_func_param)
Definition: cr-term.c:153
CBC_TK
@ CBC_TK
Definition: cr-token.h:70
CBO_TK
@ CBO_TK
Definition: cr-token.h:69
cr_token_destroy
void cr_token_destroy(CRToken *a_this)
The destructor of the CRToken class.
Definition: cr-token.c:629
BC_TK
@ BC_TK
Definition: cr-token.h:74
cr_tknzr_set_cur_pos
enum CRStatus cr_tknzr_set_cur_pos(CRTknzr *a_this, CRInputPos *a_pos)
Definition: cr-tknzr.c:1932
cr_parser_parse_term
enum CRStatus cr_parser_parse_term(CRParser *a_this, CRTerm **a_term)
cr_parser_parse_term: @a_term: out parameter.
Definition: cr-parser.c:1507
cr_parser_new_from_buf
CRParser * cr_parser_new_from_buf(guchar *a_buf, gulong a_len, enum CREncoding a_enc, gboolean a_free_buf)
cr_parser_new_from_buf: @a_buf: the buffer to parse.
Definition: cr-parser.c:2784
cr_term_destroy
void cr_term_destroy(CRTerm *a_this)
The destructor of the the CRTerm class.
Definition: cr-term.c:775
COMMA
@ COMMA
Definition: cr-term.h:67
cr_parser_parse_statement_core
enum CRStatus cr_parser_parse_statement_core(CRParser *a_this)
cr_parser_parse_statement_core: @a_this: the current instance of CRParser.
Definition: cr-parser.c:3263
_CRTerm::type
enum CRTermType type
The type of the term.
Definition: cr-term.h:87
HASH_TK
@ HASH_TK
Definition: cr-token.h:47
cr_tknzr_new
CRTknzr * cr_tknzr_new(CRInput *a_input)
Definition: cr-tknzr.c:1595
_CRParserPriv
The private attributes of CRParser.
Definition: cr-parser.c:108
_CRParser
The implementation of the SAC parser.
Definition: cr-parser.h:51
_CRSimpleSel::combinator
enum Combinator combinator
The combinator that separates this simple selector from the previous one.
Definition: cr-simple-sel.h:84
BYTE
#define BYTE(a_parser, a_offset, a_eof)
Definition: cr-parser.c:261
cr_parser_parse_media
enum CRStatus cr_parser_parse_media(CRParser *a_this)
cr_parser_parse_media: @a_this: the "this pointer" of the current instance of CRParser.
Definition: cr-parser.c:3704
_CRAttrSel::location
CRParsingLocation location
Definition: cr-attr-sel.h:55
_CRToken::rgb
CRRgb * rgb
Definition: cr-token.h:110
cr_parser_parse_file
enum CRStatus cr_parser_parse_file(CRParser *a_this, const guchar *a_file_uri, enum CREncoding a_enc)
cr_parser_parse_file: @a_this: a pointer to the current instance of CRParser.
Definition: cr-parser.c:2977
cr_parser_parse_page
enum CRStatus cr_parser_parse_page(CRParser *a_this)
cr_parser_parse_page: @a_this: the "this pointer" of the current instance of CRParser.
Definition: cr-parser.c:3874
CRAdditionalSelectorContent::class_name
CRString * class_name
Definition: cr-additional-sel.h:48
cr_simple_sel_destroy
void cr_simple_sel_destroy(CRSimpleSel *a_this)
cr_simple_sel_destroy:
Definition: cr-simple-sel.c:304
_CRToken::location
CRParsingLocation location
Definition: cr-token.h:116
PSEUDO_CLASS_ADD_SELECTOR
@ PSEUDO_CLASS_ADD_SELECTOR
Definition: cr-additional-sel.h:41
CRTknzr
typedefG_BEGIN_DECLS struct _CRTknzr CRTknzr
Definition: cr-tknzr.h:40
NUMBER_TK
@ NUMBER_TK
Definition: cr-token.h:63
cr_additional_sel_new_with_type
CRAdditionalSel * cr_additional_sel_new_with_type(enum AddSelectorType a_sel_type)
cr_additional_sel_new_with_type: @a_sel_type: the type of the newly built instance of CRAdditionalSel...
Definition: cr-additional-sel.c:71
CRAdditionalSelectorContent::attr_sel
CRAttrSel * attr_sel
Definition: cr-additional-sel.h:51
_CRPseudo
The CRPseudo Class.
Definition: cr-pseudo.h:46
cr_parser_parse
enum CRStatus cr_parser_parse(CRParser *a_this)
cr_parser_parse: @a_this: the current instance of CRParser.
Definition: cr-parser.c:4373
LENGTH_TK
@ LENGTH_TK
Definition: cr-token.h:57
cr-simple-sel.h
CHECK_PARSING_STATUS_ERR
#define CHECK_PARSING_STATUS_ERR(a_this, a_status, a_is_exception, a_err_msg, a_err_status)
CHECK_PARSING_STATUS_ERR: @a_this: the current instance of CRParser .
Definition: cr-parser.c:179
cr_simple_sel_append_simple_sel
CRSimpleSel * cr_simple_sel_append_simple_sel(CRSimpleSel *a_this, CRSimpleSel *a_sel)
cr_simple_sel_append_simple_sel:
Definition: cr-simple-sel.c:61
cr_parser_parse_import
enum CRStatus cr_parser_parse_import(CRParser *a_this, GList **a_media_list, CRString **a_import_string, CRParsingLocation *a_location)
cr_parser_parse_import: @a_this: the "this pointer" of the current instance of CRParser.
Definition: cr-parser.c:3543
PLUS_UOP
@ PLUS_UOP
Definition: cr-term.h:58
CR_SYNTAX_ERROR
@ CR_SYNTAX_ERROR
Definition: cr-utils.h:60
cr_parser_try_to_skip_spaces_and_comments
enum CRStatus cr_parser_try_to_skip_spaces_and_comments(CRParser *a_this)
cr_parser_try_to_skip_spaces_and_comments: @a_this: the current instance of CRParser.
Definition: cr-parser.c:621
cr_parser_parse_ruleset
enum CRStatus cr_parser_parse_ruleset(CRParser *a_this)
cr_parser_parse_ruleset: @a_this: the "this pointer" of the current instance of CRParser.
Definition: cr-parser.c:3327
CR_BAD_PARAM_ERROR
@ CR_BAD_PARAM_ERROR
Definition: cr-utils.h:45
cr_parser_get_tknzr
enum CRStatus cr_parser_get_tknzr(CRParser *a_this, CRTknzr **a_tknzr)
cr_parser_get_tknzr: @a_this: the current instance of CRParser @a_tknzr: out parameter.
Definition: cr-parser.c:4424
cr_tknzr_parse_token
enum CRStatus cr_tknzr_parse_token(CRTknzr *a_this, enum CRTokenType a_type, enum CRTokenExtraType a_et, gpointer a_res, gpointer a_extra_res)
Definition: cr-tknzr.c:2629
RECORD_INITIAL_POS
#define RECORD_INITIAL_POS(a_this, a_pos)
Gets information about the current position in the input of the parser.
Definition: cr-parser.c:227
cr_tknzr_get_parsing_location
enum CRStatus cr_tknzr_get_parsing_location(CRTknzr *a_this, CRParsingLocation *a_loc)
Definition: cr-tknzr.c:1867
_CRPseudo::location
CRParsingLocation location
Definition: cr-pseudo.h:51
_CRPseudo::type
enum CRPseudoType type
Definition: cr-pseudo.h:48
cr-parser.h
FUNCTION_PSEUDO
@ FUNCTION_PSEUDO
Definition: cr-pseudo.h:36
Combinator
Combinator
Definition: cr-simple-sel.h:40
FONT_FACE_SYM_TK
@ FONT_FACE_SYM_TK
Definition: cr-token.h:51
FREQ_TK
@ FREQ_TK
Definition: cr-token.h:60
TRY_PARSE_FONT_FACE_STATE
@ TRY_PARSE_FONT_FACE_STATE
Definition: cr-parser.c:100
EQUALS
@ EQUALS
Definition: cr-attr-sel.h:43
cr_parser_set_use_core_grammar
enum CRStatus cr_parser_set_use_core_grammar(CRParser *a_this, gboolean a_use_core_grammar)
cr_parser_set_use_core_grammar: @a_this: the current instance of CRParser.
Definition: cr-parser.c:2937
INCLUDES_TK
@ INCLUDES_TK
Definition: cr-token.h:42
CRString
typedefG_BEGIN_DECLS struct _CRString CRString
Definition: cr-string.h:37
_CRParserError::line
glong line
Definition: cr-parser.c:83
_CRInputPos::line
glong line
Definition: cr-input.h:56
S_TK
@ S_TK
Definition: cr-token.h:39
CRDocHandler
typedefG_BEGIN_DECLS struct _CRDocHandler CRDocHandler
Definition: cr-doc-handler.h:40
cr_selector_unref
gboolean cr_selector_unref(CRSelector *a_this)
cr_selector_unref:
Definition: cr-selector.c:235
_CRSimpleSel::location
CRParsingLocation location
Definition: cr-simple-sel.h:104
cr_doc_handler_ref
void cr_doc_handler_ref(CRDocHandler *a_this)
cr_doc_handler_ref: @a_this: the current instance of CRDocHandler.
Definition: cr-doc-handler.c:210
ATKEYWORD_TK
@ ATKEYWORD_TK
Definition: cr-token.h:53
cr_parser_new_from_input
CRParser * cr_parser_new_from_input(CRInput *a_input)
cr_parser_new_from_input: @a_input: the parser input stream to use.
Definition: cr-parser.c:2813
_CRAdditionalSel::content
union CRAdditionalSelectorContent content
Definition: cr-additional-sel.h:59
RGB_TK
@ RGB_TK
Definition: cr-token.h:64
cr_selector_ref
void cr_selector_ref(CRSelector *a_this)
cr_selector_ref:
Definition: cr-selector.c:214
_CRInputPos
Definition: cr-input.h:54
PO_TK
@ PO_TK
Definition: cr-token.h:71
_CRParserError::status
enum CRStatus status
Definition: cr-parser.c:82
TRY_PARSE_PAGE_STATE
@ TRY_PARSE_PAGE_STATE
Definition: cr-parser.c:98
COMB_GT
@ COMB_GT
Definition: cr-simple-sel.h:45
cr_attr_sel_new
CRAttrSel * cr_attr_sel_new(void)
CRAttrSel:
Definition: cr-attr-sel.c:42
cr_parser_parse_font_face
enum CRStatus cr_parser_parse_font_face(CRParser *a_this)
cr_parser_parse_font_face: @a_this: the current instance of CRParser.
Definition: cr-parser.c:4216
MEDIA_PARSED_STATE
@ MEDIA_PARSED_STATE
Definition: cr-parser.c:97
_CRAdditionalSel::location
CRParsingLocation location
Definition: cr-additional-sel.h:63
INCLUDES
@ INCLUDES
Definition: cr-attr-sel.h:44
ENSURE_PARSING_COND_ERR
#define ENSURE_PARSING_COND_ERR(a_this, a_condition, a_err_msg, a_err_status)
Definition: cr-parser.c:312
TRY_PARSE_MEDIA_STATE
@ TRY_PARSE_MEDIA_STATE
Definition: cr-parser.c:96
CLASS_ADD_SELECTOR
@ CLASS_ADD_SELECTOR
Definition: cr-additional-sel.h:40
PEEK_NEXT_CHAR
#define PEEK_NEXT_CHAR(a_this, a_to_char)
Peeks the next char from the input stream of the current parser by invoking cr_tknzr_input_peek_char(...
Definition: cr-parser.c:198
CHARSET_PARSED_STATE
@ CHARSET_PARSED_STATE
Definition: cr-parser.c:91
cr_term_set_rgb
enum CRStatus cr_term_set_rgb(CRTerm *a_this, CRRgb *a_rgb)
Definition: cr-term.c:203
cr_string_destroy
void cr_string_destroy(CRString *a_this)
Definition: cr-string.c:159
_CRTerm::location
CRParsingLocation location
Definition: cr-term.h:145
CR_OK
@ CR_OK
Definition: cr-utils.h:44
cr_term_append_term
CRTerm * cr_term_append_term(CRTerm *a_this, CRTerm *a_new_term)
Appends a new term to the current list of CRTerm.
Definition: cr-term.c:235
UNIVERSAL_SELECTOR
@ UNIVERSAL_SELECTOR
Definition: cr-simple-sel.h:51
_CRPseudo::name
CRString * name
Definition: cr-pseudo.h:49
COMMENT_TK
@ COMMENT_TK
Definition: cr-token.h:44
cr_tknzr_new_from_uri
CRTknzr * cr_tknzr_new_from_uri(const guchar *a_file_uri, enum CREncoding a_enc)
Definition: cr-tknzr.c:1645
DASHMATCH
@ DASHMATCH
Definition: cr-attr-sel.h:45
_CRInput
The CRInput class provides the abstraction of an utf8-encoded character stream.
Definition: cr-input.h:47
_CRToken::type
enum CRTokenType type
Definition: cr-token.h:103
cr_tknzr_get_next_token
enum CRStatus cr_tknzr_get_next_token(CRTknzr *a_this, CRToken **a_tk)
Returns the next token of the input stream.
Definition: cr-tknzr.c:1969
cr_input_new_from_buf
CRInput * cr_input_new_from_buf(guchar *a_buf, gulong a_len, enum CREncoding a_enc, gboolean a_free_buf)
cr_input_new_from_buf: @a_buf: the memory buffer to create the input stream from.
Definition: cr-input.c:129
IMPORT_SYM_TK
@ IMPORT_SYM_TK
Definition: cr-token.h:48
cr_tknzr_peek_char
enum CRStatus cr_tknzr_peek_char(CRTknzr *a_this, guint32 *a_char)
Peeks a char from the parser input stream.
Definition: cr-tknzr.c:1765
cr_term_new
CRTerm * cr_term_new(void)
Instanciate a CRTerm.
Definition: cr-term.c:85
cr_additional_sel_destroy
void cr_additional_sel_destroy(CRAdditionalSel *a_this)
cr_additional_sel_destroy: @a_this: the "this pointer" of the current instance of CRAdditionalSel .
Definition: cr-additional-sel.c:466
_CRParserPriv::state
enum CRParserState state
Definition: cr-parser.c:129
CHECK_PARSING_STATUS
#define CHECK_PARSING_STATUS(status, is_exception)
Checks if 'status' equals CR_OK.
Definition: cr-parser.c:155
URI_TK
@ URI_TK
Definition: cr-token.h:65
PAGE_SYM_TK
@ PAGE_SYM_TK
Definition: cr-token.h:49
_CRToken::str
CRString * str
Definition: cr-token.h:109
cr_doc_handler_destroy
void cr_doc_handler_destroy(CRDocHandler *a_this)
cr_doc_handler_destroy: @a_this: the instance of CRDocHandler to destroy.
Definition: cr-doc-handler.c:250
IMPORTANT_SYM_TK
@ IMPORTANT_SYM_TK
Definition: cr-token.h:54
_CRParsingLocation
Definition: cr-parsing-location.h:39
DIVIDE
@ DIVIDE
Definition: cr-term.h:66
cr_string_new_from_string
CRString * cr_string_new_from_string(const gchar *a_string)
Instanciate a string and initialise it to a_string.
Definition: cr-string.c:54
CRAdditionalSelectorContent::id_name
CRString * id_name
Definition: cr-additional-sel.h:49
CRParserState
CRParserState
Definition: cr-parser.c:88
cr_term_ref
void cr_term_ref(CRTerm *a_this)
Increments the reference counter of the current instance of CRTerm.
Definition: cr-term.c:738
TRY_PARSE_RULESET_STATE
@ TRY_PARSE_RULESET_STATE
Definition: cr-parser.c:94
PC_TK
@ PC_TK
Definition: cr-token.h:72
_CRParserPriv::tknzr
CRTknzr * tknzr
The tokenizer.
Definition: cr-parser.c:112
_CRAttrSel::match_way
enum AttrMatchWay match_way
Definition: cr-attr-sel.h:52
cr-num.h
_CRPseudo::extra
CRString * extra
Definition: cr-pseudo.h:50
CRAdditionalSelectorContent::pseudo
CRPseudo * pseudo
Definition: cr-additional-sel.h:50
cr_term_set_string
enum CRStatus cr_term_set_string(CRTerm *a_this, CRString *a_str)
Definition: cr-term.c:167
cr_parser_parse_prio
enum CRStatus cr_parser_parse_prio(CRParser *a_this, CRString **a_prio)
cr_parser_parse_prio: @a_this: the current instance of CRParser.
Definition: cr-parser.c:3118
_CRTerm::unary_op
enum UnaryOperator unary_op
The unary operator associated to the current term.
Definition: cr-term.h:93
READ_NEXT_CHAR
#define READ_NEXT_CHAR(a_this, a_to_char)
Reads the next char from the input stream of the current parser.
Definition: cr-parser.c:213
_CRToken::num
CRNum * num
Definition: cr-token.h:111
READY_STATE
@ READY_STATE
Definition: cr-parser.c:89
_CRParserError
An abstraction of an error reported by by the parsing routines.
Definition: cr-parser.c:80
_CRParserPriv::resolve_import
gboolean resolve_import
Definition: cr-parser.c:130
cr_simple_sel_new
CRSimpleSel * cr_simple_sel_new(void)
cr_simple_sel_new:
Definition: cr-simple-sel.c:36
COMB_PLUS
@ COMB_PLUS
Definition: cr-simple-sel.h:44
_CRParserError::column
glong column
Definition: cr-parser.c:84
_CRParserError::msg
guchar * msg
Definition: cr-parser.c:81
EXS_TK
@ EXS_TK
Definition: cr-token.h:56
SET
@ SET
Definition: cr-attr-sel.h:42
_CRSimpleSel
The abstraction of a css2 simple selection list as defined by the right part of the "selector" produc...
Definition: cr-simple-sel.h:74
TRY_PARSE_CHARSET_STATE
@ TRY_PARSE_CHARSET_STATE
Definition: cr-parser.c:90
_CRSimpleSel::add_sel
CRAdditionalSel * add_sel
The additional selector list of the current simple selector.
Definition: cr-simple-sel.h:94
cr-term.h
CR_ERROR
@ CR_ERROR
Definition: cr-utils.h:66
cr-attr-sel.h
cr_parser_parse_charset
enum CRStatus cr_parser_parse_charset(CRParser *a_this, CRString **a_value, CRParsingLocation *a_charset_sym_location)
cr_parser_parse_charset: @a_this: the "this pointer" of the current instance of CRParser.
Definition: cr-parser.c:4125
cr_input_destroy
void cr_input_destroy(CRInput *a_this)
cr_input_destroy: @a_this: the current instance of CRInput.
Definition: cr-input.c:283
CREncoding
CREncoding
Encoding values.
Definition: cr-utils.h:84
_CRParserPriv::use_core_grammar
gboolean use_core_grammar
Definition: cr-parser.c:132
SEMICOLON_TK
@ SEMICOLON_TK
Definition: cr-token.h:68
IMPORT_PARSED_STATE
@ IMPORT_PARSED_STATE
Definition: cr-parser.c:93
IDENT_PSEUDO
@ IDENT_PSEUDO
Definition: cr-pseudo.h:35
cr_tknzr_ref
void cr_tknzr_ref(CRTknzr *a_this)
Definition: cr-tknzr.c:1660
cr_parser_get_sac_handler
enum CRStatus cr_parser_get_sac_handler(CRParser *a_this, CRDocHandler **a_handler)
cr_parser_get_sac_handler: @a_this: the "this pointer" of the current instance of CRParser.
Definition: cr-parser.c:2889
EMS_TK
@ EMS_TK
Definition: cr-token.h:55
MEDIA_SYM_TK
@ MEDIA_SYM_TK
Definition: cr-token.h:50
cr_parser_parse_declaration
enum CRStatus cr_parser_parse_declaration(CRParser *a_this, CRString **a_property, CRTerm **a_expr, gboolean *a_important)
cr_parser_parse_declaration: @a_this: the "this pointer" of the current instance of CRParser.
Definition: cr-parser.c:3169
ENSURE_PARSING_COND
#define ENSURE_PARSING_COND(condition)
Tests the condition and if it is false, sets status to "CR_PARSING_ERROR" and goto the 'error' label.
Definition: cr-parser.c:309
cr_additional_sel_append
CRAdditionalSel * cr_additional_sel_append(CRAdditionalSel *a_this, CRAdditionalSel *a_sel)
cr_additional_sel_append: @a_this: the "this pointer" of the current instance of CRAdditionalSel .
Definition: cr-additional-sel.c:182
_CRTerm
An abstraction of a css2 term as defined in the CSS2 spec in appendix D.1: term ::= [ NUMBER S* | PER...
Definition: cr-term.h:82
CR_OUT_OF_MEMORY_ERROR
@ CR_OUT_OF_MEMORY_ERROR
Definition: cr-utils.h:63
STRING_TK
@ STRING_TK
Definition: cr-token.h:45
cr_term_set_ident
enum CRStatus cr_term_set_ident(CRTerm *a_this, CRString *a_str)
Definition: cr-term.c:179
_CRAttrSel
Definition: cr-attr-sel.h:48
CRStatus
CRStatus
The status type returned by the methods of the croco library.
Definition: cr-utils.h:43
MINUS_UOP
@ MINUS_UOP
Definition: cr-term.h:59
PRIVATE
#define PRIVATE(obj)
Definition: cr-parser.c:135
TRY_PARSE_IMPORT_STATE
@ TRY_PARSE_IMPORT_STATE
Definition: cr-parser.c:92
ATTRIBUTE_ADD_SELECTOR
@ ATTRIBUTE_ADD_SELECTOR
Definition: cr-additional-sel.h:43
NO_ET
@ NO_ET
Definition: cr-token.h:80
RULESET_PARSED_STATE
@ RULESET_PARSED_STATE
Definition: cr-parser.c:95
cr_parser_set_sac_handler
enum CRStatus cr_parser_set_sac_handler(CRParser *a_this, CRDocHandler *a_handler)
cr_parser_set_sac_handler: @a_this: the "this pointer" of the current instance of CRParser.
Definition: cr-parser.c:2863
cr_attr_sel_destroy
void cr_attr_sel_destroy(CRAttrSel *a_this)
cr_attr_sel_destroy: @a_this: the "this pointer" of the current instance of CRAttrSel.
Definition: cr-attr-sel.c:211
CRSelector
typedefG_BEGIN_DECLS struct _CRSelector CRSelector
Definition: cr-selector.h:40
cr_parser_new
CRParser * cr_parser_new(CRTknzr *a_tknzr)
cr_parser_new: @a_tknzr: the tokenizer to use for the parsing.
Definition: cr-parser.c:2751
_CRToken
This class abstracts a css2 token.
Definition: cr-token.h:101
_CRParserPriv::err_stack
GList * err_stack
A stack of errors reported by the parsing routines.
Definition: cr-parser.c:127
DIMEN_TK
@ DIMEN_TK
Definition: cr-token.h:61
cr_parser_destroy
void cr_parser_destroy(CRParser *a_this)
cr_parser_destroy: @a_this: the current instance of CRParser to destroy.
Definition: cr-parser.c:4498
cr_parser_get_use_core_grammar
enum CRStatus cr_parser_get_use_core_grammar(CRParser const *a_this, gboolean *a_use_core_grammar)
cr_parser_get_use_core_grammar: @a_this: the current instance of CRParser.
Definition: cr-parser.c:2955
cr_doc_handler_unref
gboolean cr_doc_handler_unref(CRDocHandler *a_this)
cr_doc_handler_unref: @a_this: the currrent instance of CRDocHandler.
Definition: cr-doc-handler.c:227
UNICODERANGE_TK
@ UNICODERANGE_TK
Definition: cr-token.h:67
cr_term_set_uri
enum CRStatus cr_term_set_uri(CRTerm *a_this, CRString *a_str)
Definition: cr-term.c:191
cr_selector_append
CRSelector * cr_selector_append(CRSelector *a_this, CRSelector *a_new)
cr_selector_append:
Definition: cr-selector.c:78
cr_term_unref
gboolean cr_term_unref(CRTerm *a_this)
Decrements the ref count of the current instance of CRTerm.
Definition: cr-term.c:753
_CRToken::u
union _CRToken::@4 u
CDC_TK
@ CDC_TK
Definition: cr-token.h:41
FUNCTION_TK
@ FUNCTION_TK
Definition: cr-token.h:66
FONT_FACE_PARSED_STATE
@ FONT_FACE_PARSED_STATE
Definition: cr-parser.c:101
CDO_TK
@ CDO_TK
Definition: cr-token.h:40
cr_utils_trace_info
#define cr_utils_trace_info(a_msg)
Traces an info message.
Definition: cr-utils.h:127
SKIP_CHARS
#define SKIP_CHARS(a_parser, a_nb_chars)
Skip utf8 encoded characters.
Definition: cr-parser.c:295
CHARSET_SYM_TK
@ CHARSET_SYM_TK
Definition: cr-token.h:52
IDENT_TK
@ IDENT_TK
Definition: cr-token.h:46
cr_term_set_number
enum CRStatus cr_term_set_number(CRTerm *a_this, CRNum *a_num)
Definition: cr-term.c:141
cr_doc_handler_new
CRDocHandler * cr_doc_handler_new(void)
cr_doc_handler_new: Constructor of CRDocHandler.
Definition: cr-doc-handler.c:70
cr_tknzr_new_from_buf
CRTknzr * cr_tknzr_new_from_buf(guchar *a_buf, gulong a_len, enum CREncoding a_enc, gboolean a_free_at_destroy)
Definition: cr-tknzr.c:1627
BO_TK
@ BO_TK
Definition: cr-token.h:73
_CRSimpleSel::type_mask
enum SimpleSelectorType type_mask
Definition: cr-simple-sel.h:76
TERM_UNICODERANGE
@ TERM_UNICODERANGE
Definition: cr-term.h:50
cr_doc_handler_set_default_sac_handler
enum CRStatus cr_doc_handler_set_default_sac_handler(CRDocHandler *a_this)
cr_doc_handler_set_default_sac_handler: @a_this: a pointer to the current instance of CRDocHandler.
Definition: cr-doc-handler.c:181
cr_parsing_location_copy
enum CRStatus cr_parsing_location_copy(CRParsingLocation *a_to, CRParsingLocation const *a_from)
cr_parsing_location_copy: @a_to: the destination of the copy.
Definition: cr-parsing-location.c:84
cr_selector_append_simple_sel
CRSelector * cr_selector_append_simple_sel(CRSelector *a_this, CRSimpleSel *a_simple_sel)
cr_selector_append_simple_sel:
Definition: cr-selector.c:129
CR_PARSING_ERROR
@ CR_PARSING_ERROR
Definition: cr-utils.h:59
CR_END_OF_INPUT_ERROR
@ CR_END_OF_INPUT_ERROR
Definition: cr-utils.h:52
_CRInputPos::col
glong col
Definition: cr-input.h:57
cr_tknzr_peek_byte
enum CRStatus cr_tknzr_peek_byte(CRTknzr *a_this, gulong a_offset, guchar *a_byte)
Peeks a byte ahead at a given postion in the parser input stream.
Definition: cr-tknzr.c:1791
cr_pseudo_new
CRPseudo * cr_pseudo_new(void)
@CRPseudo: The definition of the CRPseudo class.
Definition: cr-pseudo.c:38
_CRParserPriv::sac_handler
CRDocHandler * sac_handler
The sac handlers to call to notify the parsing of the css2 constructions.
Definition: cr-parser.c:119
PAGE_PARSED_STATE
@ PAGE_PARSED_STATE
Definition: cr-parser.c:99
ID_ADD_SELECTOR
@ ID_ADD_SELECTOR
Definition: cr-additional-sel.h:42
COMB_WS
@ COMB_WS
Definition: cr-simple-sel.h:43