00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "string.h"
00035 #include "cr-parser.h"
00036 #include "cr-num.h"
00037 #include "cr-term.h"
00038 #include "cr-simple-sel.h"
00039 #include "cr-attr-sel.h"
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076 typedef struct _CRParserError CRParserError;
00077
00078
00079
00080
00081
00082 struct _CRParserError {
00083 guchar *msg;
00084 enum CRStatus status;
00085 glong line;
00086 glong column;
00087 glong byte_num;
00088 };
00089
00090 enum CRParserState {
00091 READY_STATE = 0,
00092 TRY_PARSE_CHARSET_STATE,
00093 CHARSET_PARSED_STATE,
00094 TRY_PARSE_IMPORT_STATE,
00095 IMPORT_PARSED_STATE,
00096 TRY_PARSE_RULESET_STATE,
00097 RULESET_PARSED_STATE,
00098 TRY_PARSE_MEDIA_STATE,
00099 MEDIA_PARSED_STATE,
00100 TRY_PARSE_PAGE_STATE,
00101 PAGE_PARSED_STATE,
00102 TRY_PARSE_FONT_FACE_STATE,
00103 FONT_FACE_PARSED_STATE
00104 };
00105
00106
00107
00108
00109
00110 struct _CRParserPriv {
00111
00112
00113
00114 CRTknzr *tknzr;
00115
00116
00117
00118
00119
00120
00121 CRDocHandler *sac_handler;
00122
00123
00124
00125
00126
00127
00128
00129 GList *err_stack;
00130
00131 enum CRParserState state;
00132 gboolean resolve_import;
00133 gboolean is_case_sensitive;
00134 gboolean use_core_grammar;
00135 };
00136
00137 #define PRIVATE(obj) ((obj)->priv)
00138
00139 #define CHARS_TAB_SIZE 12
00140
00141
00142
00143
00144
00145 #define IS_NUM(a_char) (((a_char) >= '0' && (a_char) <= '9')?TRUE:FALSE)
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156 #define CHECK_PARSING_STATUS(status, is_exception) \
00157 if ((status) != CR_OK) \
00158 { \
00159 if (is_exception == FALSE) \
00160 { \
00161 status = CR_PARSING_ERROR ; \
00162 } \
00163 goto error ; \
00164 }
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178 #define CHECK_PARSING_STATUS_ERR(a_this, a_status, a_is_exception,\
00179 a_err_msg, a_err_status) \
00180 if ((a_status) != CR_OK) \
00181 { \
00182 if (a_is_exception == FALSE) a_status = CR_PARSING_ERROR ; \
00183 cr_parser_push_error (a_this, a_err_msg, a_err_status) ; \
00184 goto error ; \
00185 }
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197 #define PEEK_NEXT_CHAR(a_this, a_to_char) \
00198 {\
00199 enum CRStatus status ; \
00200 status = cr_tknzr_peek_char (PRIVATE (a_this)->tknzr, a_to_char) ; \
00201 CHECK_PARSING_STATUS (status, TRUE) \
00202 }
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212 #define READ_NEXT_CHAR(a_this, a_to_char) \
00213 status = cr_tknzr_read_char (PRIVATE (a_this)->tknzr, a_to_char) ; \
00214 CHECK_PARSING_STATUS (status, TRUE)
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226 #define RECORD_INITIAL_POS(a_this, a_pos) \
00227 status = cr_tknzr_get_cur_pos (PRIVATE \
00228 (a_this)->tknzr, a_pos) ; \
00229 g_return_val_if_fail (status == CR_OK, status)
00230
00231
00232
00233
00234
00235
00236
00237
00238 #define RECORD_CUR_BYTE_ADDR(a_this, a_addr) \
00239 status = cr_tknzr_get_cur_byte_addr \
00240 (PRIVATE (a_this)->tknzr, a_addr) ; \
00241 CHECK_PARSING_STATUS (status, TRUE)
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254 #define PEEK_BYTE(a_parser, a_offset, a_byte_ptr) \
00255 status = cr_tknzr_peek_byte (PRIVATE (a_this)->tknzr, \
00256 a_offset, \
00257 a_byte_ptr) ; \
00258 CHECK_PARSING_STATUS (status, TRUE) ;
00259
00260 #define BYTE(a_parser, a_offset, a_eof) \
00261 cr_tknzr_peek_byte2 (PRIVATE (a_this)->tknzr, a_offset, a_eof)
00262
00263
00264
00265
00266
00267
00268
00269
00270 #define READ_NEXT_BYTE(a_this, a_byte_ptr) \
00271 status = cr_tknzr_read_byte (PRIVATE (a_this)->tknzr, a_byte_ptr) ; \
00272 CHECK_PARSING_STATUS (status, TRUE) ;
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282 #define SKIP_BYTES(a_this, a_nb_bytes) \
00283 status = cr_tknzr_seek_index (PRIVATE (a_this)->tknzr, \
00284 CR_SEEK_CUR, a_nb_bytes) ; \
00285 CHECK_PARSING_STATUS (status, TRUE) ;
00286
00287
00288
00289
00290
00291
00292
00293
00294 #define SKIP_CHARS(a_parser, a_nb_chars) \
00295 { \
00296 glong nb_chars = a_nb_chars ; \
00297 status = cr_tknzr_consume_chars \
00298 (PRIVATE (a_parser)->tknzr,0, &nb_chars) ; \
00299 CHECK_PARSING_STATUS (status, TRUE) ; \
00300 }
00301
00302
00303
00304
00305
00306
00307
00308 #define ENSURE_PARSING_COND(condition) \
00309 if (! (condition)) {status = CR_PARSING_ERROR; goto error ;}
00310
00311 #define ENSURE_PARSING_COND_ERR(a_this, a_condition, \
00312 a_err_msg, a_err_status) \
00313 if (! (a_condition)) \
00314 { \
00315 status = CR_PARSING_ERROR; \
00316 cr_parser_push_error (a_this, a_err_msg, a_err_status) ; \
00317 goto error ; \
00318 }
00319
00320 #define GET_NEXT_TOKEN(a_this, a_token_ptr) \
00321 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, \
00322 a_token_ptr) ; \
00323 ENSURE_PARSING_COND (status == CR_OK) ;
00324
00325 #ifdef WITH_UNICODE_ESCAPE_AND_RANGE
00326 static enum CRStatus cr_parser_parse_unicode_escape (CRParser * a_this,
00327 guint32 * a_unicode);
00328 static enum CRStatus cr_parser_parse_escape (CRParser * a_this,
00329 guint32 * a_esc_code);
00330
00331 static enum CRStatus cr_parser_parse_unicode_range (CRParser * a_this,
00332 GString ** a_inf,
00333 GString ** a_sup);
00334 #endif
00335
00336 static enum CRStatus cr_parser_parse_stylesheet_core (CRParser * a_this);
00337
00338 static enum CRStatus cr_parser_parse_atrule_core (CRParser * a_this);
00339
00340 static enum CRStatus cr_parser_parse_ruleset_core (CRParser * a_this);
00341
00342 static enum CRStatus cr_parser_parse_selector_core (CRParser * a_this);
00343
00344 static enum CRStatus cr_parser_parse_declaration_core (CRParser * a_this);
00345
00346 static enum CRStatus cr_parser_parse_any_core (CRParser * a_this);
00347
00348 static enum CRStatus cr_parser_parse_block_core (CRParser * a_this);
00349
00350 static enum CRStatus cr_parser_parse_value_core (CRParser * a_this);
00351
00352 static enum CRStatus cr_parser_parse_string (CRParser * a_this,
00353 GString ** a_str);
00354
00355 static enum CRStatus cr_parser_parse_ident (CRParser * a_this,
00356 GString ** a_str);
00357
00358 static enum CRStatus cr_parser_parse_uri (CRParser * a_this,
00359 GString ** a_str);
00360
00361 static enum CRStatus cr_parser_parse_function (CRParser * a_this,
00362 GString ** a_func_name,
00363 CRTerm ** a_expr);
00364 static enum CRStatus cr_parser_parse_property (CRParser * a_this,
00365 GString ** a_property);
00366
00367 static enum CRStatus cr_parser_parse_attribute_selector (CRParser * a_this,
00368 CRAttrSel ** a_sel);
00369
00370 static enum CRStatus cr_parser_parse_simple_selector (CRParser * a_this,
00371 CRSimpleSel ** a_sel);
00372
00373 static enum CRStatus cr_parser_parse_simple_sels (CRParser * a_this,
00374 CRSimpleSel ** a_sel);
00375
00376 static CRParserError *cr_parser_error_new (const guchar * a_msg,
00377 enum CRStatus);
00378
00379 static void cr_parser_error_set_msg (CRParserError * a_this,
00380 const guchar * a_msg);
00381
00382 static void cr_parser_error_dump (CRParserError * a_this);
00383
00384 static void cr_parser_error_set_status (CRParserError * a_this,
00385 enum CRStatus a_status);
00386
00387 static void cr_parser_error_set_pos (CRParserError * a_this,
00388 glong a_line,
00389 glong a_column, glong a_byte_num);
00390 static void
00391 cr_parser_error_destroy (CRParserError * a_this);
00392
00393 static enum CRStatus cr_parser_push_error (CRParser * a_this,
00394 const guchar * a_msg,
00395 enum CRStatus a_status);
00396
00397 static enum CRStatus cr_parser_dump_err_stack (CRParser * a_this,
00398 gboolean a_clear_errs);
00399 static enum CRStatus
00400 cr_parser_clear_errors (CRParser * a_this);
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412 static CRParserError *
00413 cr_parser_error_new (const guchar * a_msg, enum CRStatus a_status)
00414 {
00415 CRParserError *result = NULL;
00416
00417 result = g_try_malloc (sizeof (CRParserError));
00418
00419 if (result == NULL) {
00420 cr_utils_trace_info ("Out of memory");
00421 return NULL;
00422 }
00423
00424 memset (result, 0, sizeof (CRParserError));
00425
00426 cr_parser_error_set_msg (result, a_msg);
00427 cr_parser_error_set_status (result, a_status);
00428
00429 return result;
00430 }
00431
00432
00433
00434
00435
00436
00437 static void
00438 cr_parser_error_set_msg (CRParserError * a_this, const guchar * a_msg)
00439 {
00440 g_return_if_fail (a_this);
00441
00442 if (a_this->msg) {
00443 g_free (a_this->msg);
00444 }
00445
00446 a_this->msg = g_strdup (a_msg);
00447 }
00448
00449
00450
00451
00452
00453
00454
00455 static void
00456 cr_parser_error_set_status (CRParserError * a_this, enum CRStatus a_status)
00457 {
00458 g_return_if_fail (a_this);
00459
00460 a_this->status = a_status;
00461 }
00462
00463
00464
00465
00466
00467
00468
00469
00470 static void
00471 cr_parser_error_set_pos (CRParserError * a_this,
00472 glong a_line, glong a_column, glong a_byte_num)
00473 {
00474 g_return_if_fail (a_this);
00475
00476 a_this->line = a_line;
00477 a_this->column = a_column;
00478 a_this->byte_num = a_byte_num;
00479 }
00480
00481 static void
00482 cr_parser_error_dump (CRParserError * a_this)
00483 {
00484 g_return_if_fail (a_this);
00485
00486 g_printerr ("parsing error: %ld:%ld:", a_this->line, a_this->column);
00487
00488 g_printerr ("%s\n", a_this->msg);
00489 }
00490
00491
00492
00493
00494
00495 static void
00496 cr_parser_error_destroy (CRParserError * a_this)
00497 {
00498 g_return_if_fail (a_this);
00499
00500 if (a_this->msg) {
00501 g_free (a_this->msg);
00502 a_this->msg = NULL;
00503 }
00504
00505 g_free (a_this);
00506 }
00507
00508
00509
00510
00511
00512
00513
00514
00515 static enum CRStatus
00516 cr_parser_push_error (CRParser * a_this,
00517 const guchar * a_msg, enum CRStatus a_status)
00518 {
00519 enum CRStatus status = CR_OK;
00520
00521 CRParserError *error = NULL;
00522 CRInputPos pos;
00523
00524 g_return_val_if_fail (a_this && PRIVATE (a_this)
00525 && a_msg, CR_BAD_PARAM_ERROR);
00526
00527 error = cr_parser_error_new (a_msg, a_status);
00528
00529 g_return_val_if_fail (error, CR_ERROR);
00530
00531 RECORD_INITIAL_POS (a_this, &pos);
00532
00533 cr_parser_error_set_pos
00534 (error, pos.line, pos.col, pos.next_byte_index - 1);
00535
00536 PRIVATE (a_this)->err_stack =
00537 g_list_prepend (PRIVATE (a_this)->err_stack, error);
00538
00539 if (PRIVATE (a_this)->err_stack == NULL)
00540 goto error;
00541
00542 return CR_OK;
00543
00544 error:
00545
00546 if (error) {
00547 cr_parser_error_destroy (error);
00548 error = NULL;
00549 }
00550
00551 return status;
00552 }
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562 static enum CRStatus
00563 cr_parser_dump_err_stack (CRParser * a_this, gboolean a_clear_errs)
00564 {
00565 GList *cur = NULL;
00566
00567 g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
00568
00569 if (PRIVATE (a_this)->err_stack == NULL)
00570 return CR_OK;
00571
00572 for (cur = PRIVATE (a_this)->err_stack; cur; cur = cur->next) {
00573 cr_parser_error_dump ((CRParserError *) cur->data);
00574 }
00575
00576 if (a_clear_errs == TRUE) {
00577 cr_parser_clear_errors (a_this);
00578 }
00579
00580 return CR_OK;
00581 }
00582
00583
00584
00585
00586
00587
00588 static enum CRStatus
00589 cr_parser_clear_errors (CRParser * a_this)
00590 {
00591 GList *cur = NULL;
00592
00593 g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
00594
00595 for (cur = PRIVATE (a_this)->err_stack; cur; cur = cur->next) {
00596 if (cur->data) {
00597 cr_parser_error_destroy ((CRParserError *)
00598 cur->data);
00599 }
00600 }
00601
00602 if (PRIVATE (a_this)->err_stack) {
00603 g_list_free (PRIVATE (a_this)->err_stack);
00604 PRIVATE (a_this)->err_stack = NULL;
00605 }
00606
00607 return CR_OK;
00608 }
00609
00610
00611
00612
00613
00614
00615
00616
00617 enum CRStatus
00618 cr_parser_try_to_skip_spaces_and_comments (CRParser * a_this)
00619 {
00620 enum CRStatus status = CR_ERROR;
00621 CRToken *token = NULL;
00622
00623 g_return_val_if_fail (a_this && PRIVATE (a_this)
00624 && PRIVATE (a_this)->tknzr, CR_BAD_PARAM_ERROR);
00625 do {
00626 if (token) {
00627 cr_token_destroy (token);
00628 token = NULL;
00629 }
00630
00631 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
00632 &token);
00633 if (status != CR_OK)
00634 goto error;
00635 }
00636 while ((token != NULL)
00637 && (token->type == COMMENT_TK || token->type == S_TK));
00638
00639 cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
00640
00641 return status;
00642
00643 error:
00644
00645 if (token) {
00646 cr_token_destroy (token);
00647 token = NULL;
00648 }
00649
00650 return status;
00651 }
00652
00653
00654
00655
00656
00657 #ifdef WITH_UNICODE_ESCAPE_AND_RANGE
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667 static enum CRStatus
00668 cr_parser_parse_unicode_range (CRParser * a_this,
00669 GString ** a_inf, GString ** a_sup)
00670 {
00671 enum CRStatus status = CR_OK;
00672 CRInputPos init_pos;
00673 glong i = 0;
00674 gboolean min_str_needs_free = FALSE,
00675 sup_str_needs_free = FALSE;
00676 guint32 cur_char = 0,
00677 next_char = 0;
00678
00679 g_return_val_if_fail (a_this && PRIVATE (a_this)
00680 && PRIVATE (a_this)->tknzr
00681 && a_inf && a_sup, CR_BAD_PARAM_ERROR);
00682
00683 RECORD_INITIAL_POS (a_this, &init_pos);
00684
00685 READ_NEXT_CHAR (a_this, &cur_char);
00686
00687 ENSURE_PARSING_COND_ERR
00688 (a_this, cur_char == 'U',
00689 "while parsing an unicode range: unicode range must start with an U",
00690 CR_SYNTAX_ERROR);
00691
00692 READ_NEXT_CHAR (a_this, &cur_char);
00693
00694 ENSURE_PARSING_COND_ERR
00695 (a_this, cur_char == '+',
00696 "while parsing an unicode range: there must be a + after the U",
00697 CR_SYNTAX_ERROR);
00698
00699 if (*a_inf == NULL) {
00700 *a_inf = g_string_new (NULL);
00701 min_str_needs_free = TRUE;
00702 }
00703
00704 for (i = 0; i < 6; i++) {
00705 PEEK_NEXT_CHAR (a_this, &next_char);
00706
00707 if (cr_utils_is_hexa_char (next_char) == TRUE
00708 || next_char == '?') {
00709 READ_NEXT_CHAR (a_this, &cur_char);
00710 g_string_append_unichar (*a_inf, cur_char);
00711 } else {
00712 break;
00713 }
00714 }
00715
00716 if (i < 1) {
00717 status = CR_PARSING_ERROR;
00718 cr_parser_push_error (a_this,
00719 "No unicode range expressed",
00720 CR_SYNTAX_ERROR);
00721 goto error;
00722 }
00723
00724 if (next_char != '-') {
00725 return CR_OK;
00726 }
00727
00728 READ_NEXT_CHAR (a_this, &cur_char);
00729
00730
00731 if (*a_sup == NULL) {
00732 *a_sup = g_string_new (NULL);
00733 sup_str_needs_free = TRUE;
00734 }
00735
00736 for (i = 0; i < 6; i++) {
00737 PEEK_NEXT_CHAR (a_this, &next_char);
00738
00739 if (cr_utils_is_hexa_char (next_char) == TRUE) {
00740 READ_NEXT_CHAR (a_this, &cur_char);
00741 if (*a_sup == NULL) {
00742 *a_sup = g_string_new (NULL);
00743 sup_str_needs_free = TRUE;
00744 }
00745 g_string_append_unichar (*a_sup, cur_char);
00746 } else {
00747 break;
00748 }
00749 }
00750
00751 cr_parser_clear_errors (a_this);
00752 return CR_OK;
00753
00754 error:
00755
00756 if (min_str_needs_free == TRUE && *a_inf) {
00757 g_free (*a_inf);
00758 *a_inf = NULL;
00759 }
00760
00761 if (sup_str_needs_free == TRUE && *a_sup) {
00762 g_free (*a_sup);
00763 *a_sup = NULL;
00764 }
00765
00766 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
00767
00768 return status;
00769 }
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787 static enum CRStatus
00788 cr_parser_parse_unicode_escape (CRParser * a_this, guint32 * a_unicode)
00789 {
00790 guint32 cur_char;
00791 CRInputPos init_pos;
00792 glong occur = 0;
00793 guint32 unicode = 0;
00794 guchar *tmp_char_ptr1 = NULL,
00795 *tmp_char_ptr2 = NULL;
00796 enum CRStatus status = CR_OK;
00797
00798 g_return_val_if_fail (a_this && PRIVATE (a_this)
00799 && a_unicode, CR_BAD_PARAM_ERROR);
00800
00801
00802 RECORD_INITIAL_POS (a_this, &init_pos);
00803
00804 READ_NEXT_CHAR (a_this, &cur_char);
00805
00806 if (cur_char != '\\') {
00807 status = CR_PARSING_ERROR;
00808 goto error;
00809 }
00810
00811 READ_NEXT_CHAR (a_this, &cur_char);
00812
00813 for (occur = 0, unicode = 0; ((cur_char >= '0' && cur_char <= '9')
00814 || (cur_char >= 'a' && cur_char <= 'f')
00815 || (cur_char >= 'A' && cur_char <= 'F'))
00816 && occur < 6; occur++) {
00817 gint cur_char_val = 0;
00818
00819 if ((cur_char >= '0' && cur_char <= '9')) {
00820 cur_char_val = (cur_char - '0');
00821 } else if ((cur_char >= 'a' && cur_char <= 'f')) {
00822 cur_char_val = 10 + (cur_char - 'a');
00823 } else if ((cur_char >= 'A' && cur_char <= 'F')) {
00824 cur_char_val = 10 + (cur_char - 'A');
00825 }
00826
00827 unicode = unicode * 10 + cur_char_val;
00828
00829 READ_NEXT_CHAR (a_this, &cur_char);
00830 }
00831
00832 if (occur == 5) {
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842 cr_parser_parse_w (a_this, &tmp_char_ptr1, &tmp_char_ptr2);
00843 status = CR_OK;
00844 } else {
00845
00846
00847
00848
00849
00850
00851 status = cr_parser_parse_w (a_this, &tmp_char_ptr1,
00852 &tmp_char_ptr2);
00853
00854 CHECK_PARSING_STATUS_ERR
00855 (a_this, status, FALSE,
00856 "next char expected to be a space", CR_SYNTAX_ERROR);
00857 }
00858
00859 if (status == CR_OK) {
00860 *a_unicode = unicode;
00861 cr_parser_clear_errors (a_this);
00862 return CR_OK;
00863 }
00864
00865 error:
00866
00867
00868
00869
00870 cr_tknzr_set_cur_pos (PRIVATE (a_this) tknzr, &init_pos);
00871
00872 return status;
00873 }
00874
00875
00876
00877
00878
00879
00880 static enum CRStatus
00881 cr_parser_parse_escape (CRParser * a_this, guint32 * a_esc_code)
00882 {
00883 enum CRStatus status = CR_OK;
00884 guint32 cur_char = 0;
00885 CRInputPos init_pos;
00886 guchar next_chars[2];
00887
00888 g_return_val_if_fail (a_this && PRIVATE (a_this)
00889 && a_esc_code, CR_BAD_PARAM_ERROR);
00890
00891 RECORD_INITIAL_POS (a_this, &init_pos);
00892
00893 PEEK_BYTE (a_this, 1, &next_chars[0]);
00894 PEEK_BYTE (a_this, 2, &next_chars[1]);
00895
00896 if (next_chars[0] != '\\') {
00897 status = CR_PARSING_ERROR;
00898 cr_parser_push_error
00899 (a_this,
00900 "next char expected to be a '\\'", CR_SYNTAX_ERROR);
00901
00902 goto error;
00903 }
00904
00905 if ((next_chars[1] >= '0' && next_chars[1] <= '9')
00906 || (next_chars[1] >= 'a' && next_chars[1] <= 'z')
00907 || (next_chars[1] >= 'A' && next_chars[1] <= 'Z')) {
00908 status = cr_parser_parse_unicode_escape (a_this, a_esc_code);
00909 if (status != CR_OK
00910 && cr_parser_errors_exist (a_this) == TRUE) {
00911 cr_parser_clear_errors (a_this);
00912 }
00913 } else {
00914
00915 READ_NEXT_CHAR (a_this, &cur_char);
00916
00917
00918 READ_NEXT_CHAR (a_this, &cur_char);
00919
00920 if (cur_char != ' ' && (cur_char < 200 || cur_char > 4177777)) {
00921 status = CR_PARSING_ERROR;
00922
00923 cr_parser_push_error
00924 (a_this,
00925 "next char expected to be a space",
00926 CR_SYNTAX_ERROR);
00927
00928 goto error;
00929 }
00930
00931 *a_esc_code = cur_char;
00932
00933 }
00934
00935 if (status == CR_OK) {
00936 cr_parser_clear_errors (a_this);
00937 return CR_OK;
00938 }
00939
00940 error:
00941
00942 cr_tknzr_set_cur_pos (PRIVATE (a_this) tknzr, &init_pos);
00943
00944 return status;
00945 }
00946 #endif
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963 static enum CRStatus
00964 cr_parser_parse_stylesheet_core (CRParser * a_this)
00965 {
00966 CRToken *token = NULL;
00967 CRInputPos init_pos;
00968 enum CRStatus status = CR_ERROR;
00969
00970 g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
00971
00972 RECORD_INITIAL_POS (a_this, &init_pos);
00973
00974 continue_parsing:
00975
00976 if (token) {
00977 cr_token_destroy (token);
00978 token = NULL;
00979 }
00980
00981 cr_parser_try_to_skip_spaces_and_comments (a_this);
00982 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
00983 if (status == CR_END_OF_INPUT_ERROR) {
00984 status = CR_OK;
00985 goto done;
00986 } else if (status != CR_OK) {
00987 goto error;
00988 }
00989
00990 switch (token->type) {
00991
00992 case CDO_TK:
00993 case CDC_TK:
00994 goto continue_parsing;
00995 break;
00996 default:
00997 status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
00998 token);
00999 CHECK_PARSING_STATUS (status, TRUE);
01000 token = NULL;
01001 status = cr_parser_parse_statement_core (a_this);
01002 cr_parser_clear_errors (a_this);
01003 if (status == CR_OK) {
01004 goto continue_parsing;
01005 } else if (status == CR_END_OF_INPUT_ERROR) {
01006 goto done;
01007 } else {
01008 goto error;
01009 }
01010 }
01011
01012 done:
01013 if (token) {
01014 cr_token_destroy (token);
01015 token = NULL;
01016 }
01017
01018 cr_parser_clear_errors (a_this);
01019 return CR_OK;
01020 error:
01021
01022 cr_parser_push_error
01023 (a_this, "could not recognize next production", CR_ERROR);
01024
01025 cr_parser_dump_err_stack (a_this, TRUE);
01026
01027 if (token) {
01028 cr_token_destroy (token);
01029 token = NULL;
01030 }
01031
01032 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
01033
01034 return status;
01035 }
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045 static enum CRStatus
01046 cr_parser_parse_atrule_core (CRParser * a_this)
01047 {
01048 CRToken *token = NULL;
01049 CRInputPos init_pos;
01050 enum CRStatus status = CR_ERROR;
01051
01052 g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
01053
01054 RECORD_INITIAL_POS (a_this, &init_pos);
01055
01056 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
01057 ENSURE_PARSING_COND (status == CR_OK
01058 && token
01059 &&
01060 (token->type == ATKEYWORD_TK
01061 || token->type == IMPORT_SYM_TK
01062 || token->type == PAGE_SYM_TK
01063 || token->type == MEDIA_SYM_TK
01064 || token->type == FONT_FACE_SYM_TK
01065 || token->type == CHARSET_SYM_TK));
01066
01067 cr_token_destroy (token);
01068 token = NULL;
01069
01070 cr_parser_try_to_skip_spaces_and_comments (a_this);
01071
01072 do {
01073 status = cr_parser_parse_any_core (a_this);
01074 } while (status == CR_OK);
01075
01076 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
01077 ENSURE_PARSING_COND (status == CR_OK && token);
01078
01079 if (token->type == CBO_TK) {
01080 cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
01081 token = NULL;
01082 status = cr_parser_parse_block_core (a_this);
01083 CHECK_PARSING_STATUS (status, FALSE);
01084 goto done;
01085 } else if (token->type == SEMICOLON_TK) {
01086 goto done;
01087 } else {
01088 status = CR_PARSING_ERROR ;
01089 goto error;
01090 }
01091
01092 done:
01093 if (token) {
01094 cr_token_destroy (token);
01095 token = NULL;
01096 }
01097
01098 return CR_OK;
01099
01100 error:
01101 if (token) {
01102 cr_token_destroy (token);
01103 token = NULL;
01104 }
01105
01106 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
01107
01108 return status;
01109 }
01110
01111
01112
01113
01114
01115
01116
01117
01118 static enum CRStatus
01119 cr_parser_parse_ruleset_core (CRParser * a_this)
01120 {
01121 CRToken *token = NULL;
01122 CRInputPos init_pos;
01123 enum CRStatus status = CR_ERROR;
01124
01125 g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
01126 RECORD_INITIAL_POS (a_this, &init_pos);
01127
01128 status = cr_parser_parse_selector_core (a_this);
01129
01130 ENSURE_PARSING_COND (status == CR_OK
01131 || status == CR_PARSING_ERROR
01132 || status == CR_END_OF_INPUT_ERROR);
01133
01134 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
01135 ENSURE_PARSING_COND (status == CR_OK && token
01136 && token->type == CBO_TK);
01137 cr_token_destroy (token);
01138 token = NULL;
01139
01140 cr_parser_try_to_skip_spaces_and_comments (a_this);
01141 status = cr_parser_parse_declaration_core (a_this);
01142
01143 parse_declaration_list:
01144 if (token) {
01145 cr_token_destroy (token);
01146 token = NULL;
01147 }
01148
01149 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
01150 ENSURE_PARSING_COND (status == CR_OK && token);
01151 if (token->type == CBC_TK) {
01152 goto done;
01153 }
01154
01155 ENSURE_PARSING_COND (status == CR_OK
01156 && token && token->type == SEMICOLON_TK);
01157
01158 cr_token_destroy (token);
01159 token = NULL;
01160 cr_parser_try_to_skip_spaces_and_comments (a_this);
01161 status = cr_parser_parse_declaration_core (a_this);
01162 cr_parser_clear_errors (a_this);
01163 ENSURE_PARSING_COND (status == CR_OK || status == CR_PARSING_ERROR);
01164 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
01165 ENSURE_PARSING_COND (status == CR_OK && token);
01166 if (token->type == CBC_TK) {
01167 cr_token_destroy (token);
01168 token = NULL;
01169 cr_parser_try_to_skip_spaces_and_comments (a_this);
01170 goto done;
01171 } else {
01172 status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
01173 token);
01174 token = NULL;
01175 goto parse_declaration_list;
01176 }
01177
01178 done:
01179 if (token) {
01180 cr_token_destroy (token);
01181 token = NULL;
01182 }
01183
01184 if (status == CR_OK) {
01185 return CR_OK;
01186 }
01187
01188 error:
01189 if (token) {
01190 cr_token_destroy (token);
01191 token = NULL;
01192 }
01193
01194 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
01195
01196 return status;
01197 }
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207 static enum CRStatus
01208 cr_parser_parse_selector_core (CRParser * a_this)
01209 {
01210 CRToken *token = NULL;
01211 CRInputPos init_pos;
01212 enum CRStatus status = CR_ERROR;
01213
01214 g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
01215
01216 RECORD_INITIAL_POS (a_this, &init_pos);
01217
01218 status = cr_parser_parse_any_core (a_this);
01219 CHECK_PARSING_STATUS (status, FALSE);
01220
01221 do {
01222 status = cr_parser_parse_any_core (a_this);
01223
01224 } while (status == CR_OK);
01225
01226 return CR_OK;
01227
01228 error:
01229 if (token) {
01230 cr_token_destroy (token);
01231 token = NULL;
01232 }
01233
01234 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
01235
01236 return status;
01237 }
01238
01239
01240
01241
01242
01243
01244
01245
01246 static enum CRStatus
01247 cr_parser_parse_block_core (CRParser * a_this)
01248 {
01249 CRToken *token = NULL;
01250 CRInputPos init_pos;
01251 enum CRStatus status = CR_ERROR;
01252
01253 g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
01254
01255 RECORD_INITIAL_POS (a_this, &init_pos);
01256
01257 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
01258 ENSURE_PARSING_COND (status == CR_OK && token
01259 && token->type == CBO_TK);
01260
01261 parse_block_content:
01262
01263 if (token) {
01264 cr_token_destroy (token);
01265 token = NULL;
01266 }
01267
01268 cr_parser_try_to_skip_spaces_and_comments (a_this);
01269
01270 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
01271 ENSURE_PARSING_COND (status == CR_OK && token);
01272
01273 if (token->type == CBC_TK) {
01274 cr_parser_try_to_skip_spaces_and_comments (a_this);
01275 goto done;
01276 } else if (token->type == SEMICOLON_TK) {
01277 goto parse_block_content;
01278 } else if (token->type == ATKEYWORD_TK) {
01279 cr_parser_try_to_skip_spaces_and_comments (a_this);
01280 goto parse_block_content;
01281 } else if (token->type == CBO_TK) {
01282 cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
01283 token = NULL;
01284 status = cr_parser_parse_block_core (a_this);
01285 CHECK_PARSING_STATUS (status, FALSE);
01286 goto parse_block_content;
01287 } else {
01288 cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
01289 token = NULL;
01290 status = cr_parser_parse_any_core (a_this);
01291 CHECK_PARSING_STATUS (status, FALSE);
01292 goto parse_block_content;
01293 }
01294
01295 done:
01296 if (token) {
01297 cr_token_destroy (token);
01298 token = NULL;
01299 }
01300
01301 if (status == CR_OK)
01302 return CR_OK;
01303
01304 error:
01305 if (token) {
01306 cr_token_destroy (token);
01307 token = NULL;
01308 }
01309
01310 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
01311
01312 return status;
01313 }
01314
01315 static enum CRStatus
01316 cr_parser_parse_declaration_core (CRParser * a_this)
01317 {
01318 CRToken *token = NULL;
01319 CRInputPos init_pos;
01320 enum CRStatus status = CR_ERROR;
01321 GString *prop = NULL;
01322
01323 g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
01324
01325 RECORD_INITIAL_POS (a_this, &init_pos);
01326
01327 status = cr_parser_parse_property (a_this, &prop);
01328 CHECK_PARSING_STATUS (status, FALSE);
01329 cr_parser_clear_errors (a_this);
01330 ENSURE_PARSING_COND (status == CR_OK && prop);
01331 g_string_free (prop, TRUE);
01332 prop = NULL;
01333
01334 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
01335 ENSURE_PARSING_COND (status == CR_OK
01336 && token
01337 && token->type == DELIM_TK
01338 && token->u.unichar == ':');
01339 cr_token_destroy (token);
01340 token = NULL;
01341 cr_parser_try_to_skip_spaces_and_comments (a_this);
01342 status = cr_parser_parse_value_core (a_this);
01343 CHECK_PARSING_STATUS (status, FALSE);
01344
01345 return CR_OK;
01346
01347 error:
01348
01349 if (prop) {
01350 g_string_free (prop, TRUE);
01351 prop = NULL;
01352 }
01353
01354 if (token) {
01355 cr_token_destroy (token);
01356 token = NULL;
01357 }
01358
01359 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
01360
01361 return status;
01362 }
01363
01364
01365
01366
01367
01368
01369
01370
01371 static enum CRStatus
01372 cr_parser_parse_value_core (CRParser * a_this)
01373 {
01374 CRToken *token = NULL;
01375 CRInputPos init_pos;
01376 enum CRStatus status = CR_ERROR;
01377 glong ref = 0;
01378
01379 g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
01380 RECORD_INITIAL_POS (a_this, &init_pos);
01381
01382 continue_parsing:
01383
01384 if (token) {
01385 cr_token_destroy (token);
01386 token = NULL;
01387 }
01388
01389 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
01390 ENSURE_PARSING_COND (status == CR_OK && token);
01391
01392 switch (token->type) {
01393 case CBO_TK:
01394 status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
01395 token);
01396 token = NULL;
01397 status = cr_parser_parse_block_core (a_this);
01398 CHECK_PARSING_STATUS (status, FALSE);
01399 ref++;
01400 goto continue_parsing;
01401
01402 case ATKEYWORD_TK:
01403 cr_parser_try_to_skip_spaces_and_comments (a_this);
01404 ref++;
01405 goto continue_parsing;
01406
01407 default:
01408 status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
01409 token);
01410 token = NULL;
01411 status = cr_parser_parse_any_core (a_this);
01412 if (status == CR_OK) {
01413 ref++;
01414 goto continue_parsing;
01415 } else if (status == CR_PARSING_ERROR) {
01416 status = CR_OK;
01417 goto done;
01418 } else {
01419 goto error;
01420 }
01421 }
01422
01423 done:
01424 if (token) {
01425 cr_token_destroy (token);
01426 token = NULL;
01427 }
01428
01429 if (status == CR_OK && ref)
01430 return CR_OK;
01431 error:
01432 if (token) {
01433 cr_token_destroy (token);
01434 token = NULL;
01435 }
01436
01437 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
01438
01439 return status;
01440 }
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452 static enum CRStatus
01453 cr_parser_parse_any_core (CRParser * a_this)
01454 {
01455 CRToken *token1 = NULL,
01456 *token2 = NULL;
01457 CRInputPos init_pos;
01458 enum CRStatus status = CR_ERROR;
01459
01460 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
01461
01462 RECORD_INITIAL_POS (a_this, &init_pos);
01463
01464 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token1);
01465
01466 ENSURE_PARSING_COND (status == CR_OK && token1);
01467
01468 switch (token1->type) {
01469 case IDENT_TK:
01470 case NUMBER_TK:
01471 case RGB_TK:
01472 case PERCENTAGE_TK:
01473 case DIMEN_TK:
01474 case EMS_TK:
01475 case EXS_TK:
01476 case LENGTH_TK:
01477 case ANGLE_TK:
01478 case FREQ_TK:
01479 case TIME_TK:
01480 case STRING_TK:
01481 case DELIM_TK:
01482 case URI_TK:
01483 case HASH_TK:
01484 case UNICODERANGE_TK:
01485 case INCLUDES_TK:
01486 case DASHMATCH_TK:
01487 case S_TK:
01488 case IMPORTANT_SYM_TK:
01489 status = CR_OK;
01490 break;
01491 case FUNCTION_TK:
01492
01493
01494
01495
01496
01497
01498 do {
01499 status = cr_parser_parse_any_core (a_this);
01500 } while (status == CR_OK);
01501
01502 ENSURE_PARSING_COND (status == CR_PARSING_ERROR);
01503 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
01504 &token2);
01505 ENSURE_PARSING_COND (status == CR_OK
01506 && token2 && token2->type == PC_TK);
01507 break;
01508 case PO_TK:
01509 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
01510 &token2);
01511 ENSURE_PARSING_COND (status == CR_OK && token2);
01512
01513 if (token2->type == PC_TK) {
01514 cr_token_destroy (token2);
01515 token2 = NULL;
01516 goto done;
01517 } else {
01518 status = cr_tknzr_unget_token
01519 (PRIVATE (a_this)->tknzr, token2);
01520 token2 = NULL;
01521 }
01522
01523 do {
01524 status = cr_parser_parse_any_core (a_this);
01525 } while (status == CR_OK);
01526
01527 ENSURE_PARSING_COND (status == CR_PARSING_ERROR);
01528
01529 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
01530 &token2);
01531 ENSURE_PARSING_COND (status == CR_OK
01532 && token2 && token2->type == PC_TK);
01533 status = CR_OK;
01534 break;
01535
01536 case BO_TK:
01537 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
01538 &token2);
01539 ENSURE_PARSING_COND (status == CR_OK && token2);
01540
01541 if (token2->type == BC_TK) {
01542 cr_token_destroy (token2);
01543 token2 = NULL;
01544 goto done;
01545 } else {
01546 status = cr_tknzr_unget_token
01547 (PRIVATE (a_this)->tknzr, token2);
01548 token2 = NULL;
01549 }
01550
01551 do {
01552 status = cr_parser_parse_any_core (a_this);
01553 } while (status == CR_OK);
01554
01555 ENSURE_PARSING_COND (status == CR_PARSING_ERROR);
01556
01557 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
01558 &token2);
01559 ENSURE_PARSING_COND (status == CR_OK
01560 && token2 && token2->type == BC_TK);
01561 status = CR_OK;
01562 break;
01563 default:
01564 status = CR_PARSING_ERROR;
01565 goto error;
01566 }
01567
01568 done:
01569 if (token1) {
01570 cr_token_destroy (token1);
01571 token1 = NULL;
01572 }
01573
01574 if (token2) {
01575 cr_token_destroy (token2);
01576 token2 = NULL;
01577 }
01578
01579 return CR_OK;
01580
01581 error:
01582
01583 if (token1) {
01584 cr_token_destroy (token1);
01585 token1 = NULL;
01586 }
01587
01588 if (token2) {
01589 cr_token_destroy (token2);
01590 token2 = NULL;
01591 }
01592
01593 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
01594 return status;
01595 }
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608 static enum CRStatus
01609 cr_parser_parse_attribute_selector (CRParser * a_this, CRAttrSel ** a_sel)
01610 {
01611 enum CRStatus status = CR_OK;
01612 CRInputPos init_pos;
01613 CRToken *token = NULL;
01614 CRAttrSel *result = NULL;
01615
01616 g_return_val_if_fail (a_this && a_sel, CR_BAD_PARAM_ERROR);
01617
01618 RECORD_INITIAL_POS (a_this, &init_pos);
01619
01620 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
01621 ENSURE_PARSING_COND (status == CR_OK && token
01622 && token->type == BO_TK);
01623
01624 cr_token_destroy (token);
01625 token = NULL;
01626
01627 cr_parser_try_to_skip_spaces_and_comments (a_this);
01628
01629 result = cr_attr_sel_new ();
01630
01631 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
01632 ENSURE_PARSING_COND (status == CR_OK
01633 && token && token->type == IDENT_TK);
01634
01635 result->name = token->u.str;
01636 token->u.str = NULL;
01637 cr_token_destroy (token);
01638 token = NULL;
01639
01640 cr_parser_try_to_skip_spaces_and_comments (a_this);
01641
01642 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
01643 ENSURE_PARSING_COND (status == CR_OK && token);
01644
01645 if (token->type == INCLUDES_TK) {
01646 result->match_way = INCLUDES;
01647 goto parse_right_part;
01648 } else if (token->type == DASHMATCH_TK) {
01649 result->match_way = DASHMATCH;
01650 goto parse_right_part;
01651 } else if (token->type == DELIM_TK && token->u.unichar == '=') {
01652 result->match_way = EQUALS;
01653 goto parse_right_part;
01654 } else if (token->type == BC_TK) {
01655 result->match_way = SET;
01656 goto done;
01657 }
01658
01659 parse_right_part:
01660
01661 if (token) {
01662 cr_token_destroy (token);
01663 token = NULL;
01664 }
01665
01666 cr_parser_try_to_skip_spaces_and_comments (a_this);
01667
01668 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
01669
01670 ENSURE_PARSING_COND (status == CR_OK && token);
01671
01672 if (token->type == IDENT_TK) {
01673 result->value = token->u.str;
01674 token->u.str = NULL;
01675 } else if (token->type == STRING_TK) {
01676 result->value = token->u.str;
01677 token->u.str = NULL;
01678 } else {
01679 status = CR_PARSING_ERROR;
01680 goto error;
01681 }
01682
01683 if (token) {
01684 cr_token_destroy (token);
01685 token = NULL;
01686 }
01687
01688 cr_parser_try_to_skip_spaces_and_comments (a_this);
01689
01690 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
01691
01692 ENSURE_PARSING_COND (status == CR_OK && token
01693 && token->type == BC_TK);
01694 done:
01695 if (token) {
01696 cr_token_destroy (token);
01697 token = NULL;
01698 }
01699
01700 if (*a_sel) {
01701 status = cr_attr_sel_append_attr_sel (*a_sel, result);
01702 CHECK_PARSING_STATUS (status, FALSE);
01703 } else {
01704 *a_sel = result;
01705 }
01706
01707 cr_parser_clear_errors (a_this);
01708 return CR_OK;
01709
01710 error:
01711
01712 if (result) {
01713 cr_attr_sel_destroy (result);
01714 result = NULL;
01715 }
01716
01717 if (token) {
01718 cr_token_destroy (token);
01719 token = NULL;
01720 }
01721
01722 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
01723
01724 return status;
01725 }
01726
01727
01728
01729
01730
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740 static enum CRStatus
01741 cr_parser_parse_property (CRParser * a_this, GString ** a_property)
01742 {
01743 enum CRStatus status = CR_OK;
01744 CRInputPos init_pos;
01745
01746 g_return_val_if_fail (a_this && PRIVATE (a_this)
01747 && PRIVATE (a_this)->tknzr
01748 && a_property, CR_BAD_PARAM_ERROR);
01749
01750 RECORD_INITIAL_POS (a_this, &init_pos);
01751
01752 status = cr_parser_parse_ident (a_this, a_property);
01753 CHECK_PARSING_STATUS (status, TRUE);
01754
01755 cr_parser_try_to_skip_spaces_and_comments (a_this);
01756
01757 cr_parser_clear_errors (a_this);
01758 return CR_OK;
01759
01760 error:
01761
01762 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
01763
01764 return status;
01765 }
01766
01767
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777
01778 enum CRStatus
01779 cr_parser_parse_term (CRParser * a_this, CRTerm ** a_term)
01780 {
01781 enum CRStatus status = CR_PARSING_ERROR;
01782 CRInputPos init_pos;
01783 CRTerm *result = NULL;
01784 CRTerm *param = NULL;
01785 CRToken *token = NULL;
01786 GString *func_name = NULL;
01787
01788 g_return_val_if_fail (a_this && a_term, CR_BAD_PARAM_ERROR);
01789
01790 RECORD_INITIAL_POS (a_this, &init_pos);
01791
01792 result = cr_term_new ();
01793
01794 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
01795 if (status != CR_OK || !token)
01796 goto error;
01797
01798 if (token->type == DELIM_TK && token->u.unichar == '+') {
01799 result->unary_op = PLUS_UOP;
01800 } else if (token->type == DELIM_TK && token->u.unichar == '-') {
01801 result->unary_op = MINUS_UOP;
01802 } else if (token->type == EMS_TK
01803 || token->type == EXS_TK
01804 || token->type == LENGTH_TK
01805 || token->type == ANGLE_TK
01806 || token->type == TIME_TK
01807 || token->type == FREQ_TK
01808 || token->type == PERCENTAGE_TK
01809 || token->type == NUMBER_TK) {
01810 status = cr_term_set_number (result, token->u.num);
01811 CHECK_PARSING_STATUS (status, TRUE);
01812 token->u.num = NULL;
01813 status = CR_OK;
01814 } else if (token && token->type == FUNCTION_TK) {
01815 status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
01816 token);
01817 token = NULL;
01818 status = cr_parser_parse_function (a_this, &func_name,
01819 ¶m);
01820
01821 if (status == CR_OK) {
01822 status = cr_term_set_function (result, func_name,
01823 param);
01824 CHECK_PARSING_STATUS (status, TRUE);
01825 }
01826 } else if (token && token->type == STRING_TK) {
01827 status = cr_term_set_string (result, token->u.str);
01828 CHECK_PARSING_STATUS (status, TRUE);
01829 token->u.str = NULL;
01830 } else if (token && token->type == IDENT_TK) {
01831 status = cr_term_set_ident (result, token->u.str);
01832 CHECK_PARSING_STATUS (status, TRUE);
01833 token->u.str = NULL;
01834 } else if (token && token->type == URI_TK) {
01835 status = cr_term_set_uri (result, token->u.str);
01836 CHECK_PARSING_STATUS (status, TRUE);
01837 token->u.str = NULL;
01838 } else if (token && token->type == RGB_TK) {
01839 status = cr_term_set_rgb (result, token->u.rgb);
01840 CHECK_PARSING_STATUS (status, TRUE);
01841 token->u.rgb = NULL;
01842 } else if (token && token->type == UNICODERANGE_TK) {
01843 result->type = TERM_UNICODERANGE;
01844 status = CR_PARSING_ERROR;
01845 } else if (token && token->type == HASH_TK) {
01846 status = cr_term_set_hash (result, token->u.str);
01847 CHECK_PARSING_STATUS (status, TRUE);
01848 token->u.str = NULL;
01849 } else {
01850 status = CR_PARSING_ERROR;
01851 }
01852
01853 if (status != CR_OK) {
01854 goto error;
01855 }
01856
01857 *a_term = cr_term_append_term (*a_term, result);
01858
01859 result = NULL;
01860
01861 cr_parser_try_to_skip_spaces_and_comments (a_this);
01862
01863 if (token) {
01864 cr_token_destroy (token);
01865 token = NULL;
01866 }
01867
01868 cr_parser_clear_errors (a_this);
01869 return CR_OK;
01870
01871 error:
01872
01873 if (result) {
01874 cr_term_destroy (result);
01875 result = NULL;
01876 }
01877
01878 if (token) {
01879 cr_token_destroy (token);
01880 token = NULL;
01881 }
01882
01883 if (param) {
01884 cr_term_destroy (param);
01885 param = NULL;
01886 }
01887
01888 if (func_name) {
01889 g_string_free (func_name, TRUE);
01890 func_name = NULL;
01891 }
01892
01893 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
01894
01895 return status;
01896 }
01897
01898
01899
01900
01901
01902
01903
01904
01905
01906
01907
01908
01909 static enum CRStatus
01910 cr_parser_parse_simple_selector (CRParser * a_this, CRSimpleSel ** a_sel)
01911 {
01912 enum CRStatus status = CR_ERROR;
01913 CRInputPos init_pos;
01914 CRToken *token = NULL;
01915 CRSimpleSel *sel = NULL;
01916 CRAdditionalSel *add_sel_list = NULL;
01917 gboolean found_sel = FALSE;
01918 guint32 cur_char = 0;
01919
01920 g_return_val_if_fail (a_this && a_sel, CR_BAD_PARAM_ERROR);
01921
01922 RECORD_INITIAL_POS (a_this, &init_pos);
01923
01924 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
01925 if (status != CR_OK)
01926 goto error;
01927
01928 sel = cr_simple_sel_new ();
01929 ENSURE_PARSING_COND (sel);
01930
01931 if (token && token->type == DELIM_TK && token->u.unichar == '*') {
01932 sel->type_mask |= UNIVERSAL_SELECTOR;
01933 sel->name = g_string_new ("*");
01934 found_sel = TRUE;
01935 } else if (token && token->type == IDENT_TK) {
01936 sel->name = token->u.str;
01937 sel->type_mask |= TYPE_SELECTOR;
01938 token->u.str = NULL;
01939 found_sel = TRUE;
01940
01941 } else {
01942 status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
01943 token);
01944 token = NULL;
01945 }
01946
01947 if (token) {
01948 cr_token_destroy (token);
01949 token = NULL;
01950 }
01951
01952 cr_parser_try_to_skip_spaces_and_comments (a_this);
01953
01954 for (;;) {
01955 if (token) {
01956 cr_token_destroy (token);
01957 token = NULL;
01958 }
01959
01960 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
01961 &token);
01962 if (status != CR_OK)
01963 goto error;
01964
01965 if (token && token->type == HASH_TK) {
01966
01967 CRAdditionalSel *add_sel = NULL;
01968
01969 add_sel = cr_additional_sel_new_with_type
01970 (ID_ADD_SELECTOR);
01971
01972 add_sel->content.id_name = token->u.str;
01973 token->u.str = NULL;
01974
01975 add_sel_list =
01976 cr_additional_sel_append
01977 (add_sel_list, add_sel);
01978
01979 found_sel = TRUE;
01980 } else if (token && (token->type == DELIM_TK)
01981 && (token->u.unichar == '.')) {
01982 cr_token_destroy (token);
01983 token = NULL;
01984
01985 status = cr_tknzr_get_next_token
01986 (PRIVATE (a_this)->tknzr, &token);
01987 if (status != CR_OK)
01988 goto error;
01989
01990 if (token && token->type == IDENT_TK) {
01991 CRAdditionalSel *add_sel = NULL;
01992
01993 add_sel = cr_additional_sel_new_with_type
01994 (CLASS_ADD_SELECTOR);
01995
01996 add_sel->content.class_name = token->u.str;
01997 token->u.str = NULL;
01998
01999 add_sel_list =
02000 cr_additional_sel_append
02001 (add_sel_list, add_sel);
02002 found_sel = TRUE;
02003 } else {
02004 status = CR_PARSING_ERROR;
02005 goto error;
02006 }
02007 } else if (token && token->type == BO_TK) {
02008 CRAttrSel *attr_sel = NULL;
02009 CRAdditionalSel *add_sel = NULL;
02010
02011 status = cr_tknzr_unget_token
02012 (PRIVATE (a_this)->tknzr, token);
02013 if (status != CR_OK)
02014 goto error;
02015 token = NULL;
02016
02017 status = cr_parser_parse_attribute_selector
02018 (a_this, &attr_sel);
02019 CHECK_PARSING_STATUS (status, FALSE);
02020
02021 add_sel = cr_additional_sel_new_with_type
02022 (ATTRIBUTE_ADD_SELECTOR);
02023
02024 ENSURE_PARSING_COND (add_sel != NULL);
02025
02026 add_sel->content.attr_sel = attr_sel;
02027
02028 add_sel_list =
02029 cr_additional_sel_append
02030 (add_sel_list, add_sel);
02031 found_sel = TRUE;
02032 } else if (token && (token->type == DELIM_TK)
02033 && (token->u.unichar == ':')) {
02034 CRPseudo *pseudo = NULL;
02035
02036
02037
02038 if (token) {
02039 cr_token_destroy (token);
02040 token = NULL;
02041 }
02042
02043 pseudo = cr_pseudo_new ();
02044
02045 status = cr_tknzr_get_next_token
02046 (PRIVATE (a_this)->tknzr, &token);
02047
02048 ENSURE_PARSING_COND (status == CR_OK && token);
02049
02050 if (token->type == IDENT_TK) {
02051 pseudo->type = IDENT_PSEUDO;
02052 pseudo->name = token->u.str;
02053 token->u.str = NULL;
02054 found_sel = TRUE;
02055 } else if (token->type == FUNCTION_TK) {
02056 pseudo->name = token->u.str;
02057 token->u.str = NULL;
02058 cr_parser_try_to_skip_spaces_and_comments
02059 (a_this);
02060 status = cr_parser_parse_ident
02061 (a_this, &pseudo->extra);
02062
02063 ENSURE_PARSING_COND (status == CR_OK);
02064 READ_NEXT_CHAR (a_this, &cur_char);
02065 ENSURE_PARSING_COND (cur_char == ')');
02066 pseudo->type = FUNCTION_PSEUDO;
02067 found_sel = TRUE;
02068 } else {
02069 status = CR_PARSING_ERROR;
02070 goto error;
02071 }
02072
02073 if (status == CR_OK) {
02074 CRAdditionalSel *add_sel = NULL;
02075
02076 add_sel = cr_additional_sel_new_with_type
02077 (PSEUDO_CLASS_ADD_SELECTOR);
02078
02079 add_sel->content.pseudo = pseudo;
02080
02081 add_sel_list =
02082 cr_additional_sel_append
02083 (add_sel_list, add_sel);
02084
02085 status = CR_OK;
02086 }
02087 } else {
02088 status = cr_tknzr_unget_token
02089 (PRIVATE (a_this)->tknzr, token);
02090 token = NULL;
02091 break;
02092 }
02093 }
02094
02095 if (status == CR_OK && found_sel == TRUE) {
02096 cr_parser_try_to_skip_spaces_and_comments (a_this);
02097
02098 sel->add_sel = add_sel_list;
02099 add_sel_list = NULL;
02100
02101 if (*a_sel == NULL) {
02102 *a_sel = sel;
02103 } else {
02104 cr_simple_sel_append_simple_sel (*a_sel, sel);
02105 }
02106
02107 sel = NULL;
02108
02109 if (token) {
02110 cr_token_destroy (token);
02111 token = NULL;
02112 }
02113
02114 cr_parser_clear_errors (a_this);
02115 return CR_OK;
02116 } else {
02117 status = CR_PARSING_ERROR;
02118 }
02119
02120 error:
02121
02122 if (token) {
02123 cr_token_destroy (token);
02124 token = NULL;
02125 }
02126
02127 if (add_sel_list) {
02128 cr_additional_sel_destroy (add_sel_list);
02129 add_sel_list = NULL;
02130 }
02131
02132 if (sel) {
02133 cr_simple_sel_destroy (sel);
02134 sel = NULL;
02135 }
02136
02137 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
02138
02139 return status;
02140
02141 }
02142
02143
02144
02145
02146
02147
02148
02149
02150
02151
02152
02153
02154
02155 static enum CRStatus
02156 cr_parser_parse_simple_sels (CRParser * a_this, CRSimpleSel ** a_sel)
02157 {
02158 enum CRStatus status = CR_ERROR;
02159 CRInputPos init_pos;
02160 CRSimpleSel *sel = NULL;
02161 guint32 cur_char = 0;
02162
02163 g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
02164
02165 RECORD_INITIAL_POS (a_this, &init_pos);
02166
02167 status = cr_parser_parse_simple_selector (a_this, &sel);
02168 CHECK_PARSING_STATUS (status, FALSE);
02169
02170 *a_sel = cr_simple_sel_append_simple_sel (*a_sel, sel);
02171
02172 for (;;) {
02173 guint32 next_char = 0;
02174 enum Combinator comb = 0;
02175
02176 sel = NULL;
02177
02178 PEEK_NEXT_CHAR (a_this, &next_char);
02179
02180 if (next_char == '+') {
02181 READ_NEXT_CHAR (a_this, &cur_char);
02182 comb = COMB_PLUS;
02183 cr_parser_try_to_skip_spaces_and_comments (a_this);
02184 } else if (next_char == '>') {
02185 READ_NEXT_CHAR (a_this, &cur_char);
02186 comb = COMB_GT;
02187 cr_parser_try_to_skip_spaces_and_comments (a_this);
02188 } else {
02189 comb = COMB_WS;
02190 }
02191
02192 status = cr_parser_parse_simple_selector (a_this, &sel);
02193 if (status != CR_OK)
02194 break;
02195
02196 if (comb && sel) {
02197 sel->combinator = comb;
02198 comb = 0;
02199 }
02200 if (sel)
02201 *a_sel = cr_simple_sel_append_simple_sel (*a_sel, sel);
02202 }
02203
02204 cr_parser_clear_errors (a_this);
02205 return CR_OK;
02206
02207 error:
02208
02209 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
02210
02211 return status;
02212 }
02213
02214 static enum CRStatus
02215 cr_parser_parse_selector (CRParser * a_this, CRSelector ** a_selector)
02216 {
02217 enum CRStatus status = CR_OK;
02218 CRInputPos init_pos;
02219 guint32 cur_char = 0,
02220 next_char = 0;
02221 CRSimpleSel *simple_sels = NULL;
02222 CRSelector *selector = NULL;
02223
02224 g_return_val_if_fail (a_this && a_selector, CR_BAD_PARAM_ERROR);
02225
02226 RECORD_INITIAL_POS (a_this, &init_pos);
02227
02228 status = cr_parser_parse_simple_sels (a_this, &simple_sels);
02229
02230 CHECK_PARSING_STATUS (status, FALSE);
02231
02232 if (simple_sels) {
02233 selector = cr_selector_append_simple_sel
02234 (selector, simple_sels);
02235 simple_sels = NULL;
02236 }
02237
02238 status = cr_tknzr_peek_char (PRIVATE (a_this)->tknzr, &next_char);
02239 if (status != CR_OK) {
02240 if (status == CR_END_OF_INPUT_ERROR) {
02241 status = CR_OK;
02242 goto okay;
02243 } else {
02244 goto error;
02245 }
02246 }
02247
02248 if (next_char == ',') {
02249 for (;;) {
02250 simple_sels = NULL;
02251
02252 status = cr_tknzr_peek_char (PRIVATE (a_this)->tknzr,
02253 &next_char);
02254 if (status != CR_OK) {
02255 if (status == CR_END_OF_INPUT_ERROR) {
02256 status = CR_OK;
02257 break;
02258 } else {
02259 goto error;
02260 }
02261 }
02262
02263 if (next_char != ',')
02264 break;
02265
02266
02267 READ_NEXT_CHAR (a_this, &cur_char);
02268
02269 cr_parser_try_to_skip_spaces_and_comments (a_this);
02270
02271 status = cr_parser_parse_simple_sels
02272 (a_this, &simple_sels);
02273
02274 CHECK_PARSING_STATUS (status, FALSE);
02275
02276 if (simple_sels) {
02277 selector =
02278 cr_selector_append_simple_sel
02279 (selector, simple_sels);
02280
02281 simple_sels = NULL;
02282 }
02283 }
02284 }
02285
02286 okay:
02287 cr_parser_try_to_skip_spaces_and_comments (a_this);
02288
02289 if (!*a_selector) {
02290 *a_selector = selector;
02291 } else {
02292 *a_selector = cr_selector_append (*a_selector, selector);
02293 }
02294
02295 selector = NULL;
02296 return CR_OK;
02297
02298 error:
02299
02300 if (simple_sels) {
02301 cr_simple_sel_destroy (simple_sels);
02302 simple_sels = NULL;
02303 }
02304
02305 if (selector) {
02306 cr_selector_unref (selector);
02307 selector = NULL;
02308 }
02309
02310 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
02311
02312 return status;
02313 }
02314
02315
02316
02317
02318
02319
02320
02321
02322
02323
02324
02325
02326
02327 static enum CRStatus
02328 cr_parser_parse_function (CRParser * a_this,
02329 GString ** a_func_name, CRTerm ** a_expr)
02330 {
02331 CRInputPos init_pos;
02332 enum CRStatus status = CR_OK;
02333 CRToken *token = NULL;
02334 CRTerm *expr = NULL;
02335
02336 g_return_val_if_fail (a_this && PRIVATE (a_this)
02337 && a_func_name, CR_BAD_PARAM_ERROR);
02338
02339 RECORD_INITIAL_POS (a_this, &init_pos);
02340
02341 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
02342 if (status != CR_OK)
02343 goto error;
02344
02345 if (token && token->type == FUNCTION_TK) {
02346 *a_func_name = token->u.str;
02347 token->u.str = NULL;
02348 } else {
02349 status = CR_PARSING_ERROR;
02350 goto error;
02351 }
02352
02353 cr_token_destroy (token);
02354 token = NULL;
02355
02356 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
02357 if (status != CR_OK)
02358 goto error;
02359
02360 ENSURE_PARSING_COND (token && token->type == PO_TK);
02361
02362 cr_token_destroy (token);
02363 token = NULL;
02364
02365 status = cr_parser_parse_term (a_this, &expr);
02366
02367 CHECK_PARSING_STATUS (status, FALSE);
02368
02369 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
02370 if (status != CR_OK)
02371 goto error;
02372
02373 ENSURE_PARSING_COND (token && token->type == PC_TK);
02374
02375 cr_token_destroy (token);
02376 token = NULL;
02377
02378 if (expr) {
02379 *a_expr = cr_term_append_term (*a_expr, expr);
02380 expr = NULL;
02381 }
02382
02383 cr_parser_clear_errors (a_this);
02384 return CR_OK;
02385
02386 error:
02387
02388 if (*a_func_name) {
02389 g_string_free (*a_func_name, TRUE);
02390 *a_func_name = NULL;
02391 }
02392
02393 if (expr) {
02394 cr_term_destroy (expr);
02395 expr = NULL;
02396 }
02397
02398 if (token) {
02399 cr_token_destroy (token);
02400
02401 }
02402
02403 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
02404
02405 return status;
02406 }
02407
02408
02409
02410
02411
02412
02413
02414
02415
02416
02417 static enum CRStatus
02418 cr_parser_parse_uri (CRParser * a_this, GString ** a_str)
02419 {
02420
02421 enum CRStatus status = CR_PARSING_ERROR;
02422
02423 g_return_val_if_fail (a_this && PRIVATE (a_this)
02424 && PRIVATE (a_this)->tknzr, CR_BAD_PARAM_ERROR);
02425
02426 status = cr_tknzr_parse_token (PRIVATE (a_this)->tknzr,
02427 URI_TK, NO_ET, a_str, NULL);
02428 return status;
02429 }
02430
02431
02432
02433
02434
02435
02436
02437
02438
02439
02440
02441
02442
02443
02444
02445
02446 static enum CRStatus
02447 cr_parser_parse_string (CRParser * a_this, GString ** a_str)
02448 {
02449 enum CRStatus status = CR_OK;
02450
02451 g_return_val_if_fail (a_this && PRIVATE (a_this)
02452 && PRIVATE (a_this)->tknzr
02453 && a_str, CR_BAD_PARAM_ERROR);
02454
02455 status = cr_tknzr_parse_token (PRIVATE (a_this)->tknzr,
02456 STRING_TK, NO_ET, a_str, NULL);
02457 return status;
02458 }
02459
02460
02461
02462
02463
02464
02465
02466
02467
02468
02469
02470
02471
02472
02473
02474 static enum CRStatus
02475 cr_parser_parse_ident (CRParser * a_this, GString ** a_str)
02476 {
02477 enum CRStatus status = CR_OK;
02478
02479 g_return_val_if_fail (a_this && PRIVATE (a_this)
02480 && PRIVATE (a_this)->tknzr
02481 && a_str, CR_BAD_PARAM_ERROR);
02482
02483 status = cr_tknzr_parse_token (PRIVATE (a_this)->tknzr,
02484 IDENT_TK, NO_ET, a_str, NULL);
02485 return status;
02486 }
02487
02488
02489
02490
02491
02492
02493
02494
02495
02496
02497
02498
02499
02500
02501
02502
02503
02504
02505 static enum CRStatus
02506 cr_parser_parse_stylesheet (CRParser * a_this)
02507 {
02508 enum CRStatus status = CR_OK;
02509 CRInputPos init_pos;
02510 CRToken *token = NULL;
02511 GString *charset = NULL;
02512
02513 g_return_val_if_fail (a_this && PRIVATE (a_this)
02514 && PRIVATE (a_this)->tknzr, CR_BAD_PARAM_ERROR);
02515
02516 RECORD_INITIAL_POS (a_this, &init_pos);
02517
02518 PRIVATE (a_this)->state = READY_STATE;
02519
02520 if (PRIVATE (a_this)->sac_handler
02521 && PRIVATE (a_this)->sac_handler->start_document) {
02522 PRIVATE (a_this)->sac_handler->start_document
02523 (PRIVATE (a_this)->sac_handler);
02524 }
02525
02526
02527 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
02528
02529 if (status == CR_END_OF_INPUT_ERROR)
02530 goto done;
02531 CHECK_PARSING_STATUS (status, TRUE);
02532
02533 if (token && token->type == CHARSET_SYM_TK) {
02534 status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
02535 token);
02536 CHECK_PARSING_STATUS (status, TRUE);
02537 token = NULL;
02538
02539 status = cr_parser_parse_charset (a_this, &charset);
02540
02541 if (status == CR_OK && charset) {
02542 if (PRIVATE (a_this)->sac_handler
02543 && PRIVATE (a_this)->sac_handler->charset) {
02544 PRIVATE (a_this)->sac_handler->charset
02545 (PRIVATE (a_this)->sac_handler,
02546 charset);
02547 }
02548 } else if (status != CR_END_OF_INPUT_ERROR) {
02549 status = cr_parser_parse_atrule_core (a_this);
02550 CHECK_PARSING_STATUS (status, FALSE);
02551 }
02552
02553 if (charset) {
02554 g_string_free (charset, TRUE);
02555 charset = NULL;
02556 }
02557 } else if (token
02558 && (token->type == S_TK || token->type == COMMENT_TK)) {
02559 status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
02560 token);
02561 token = NULL;
02562 CHECK_PARSING_STATUS (status, TRUE);
02563
02564 cr_parser_try_to_skip_spaces_and_comments (a_this);
02565 } else if (token) {
02566 status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
02567 token);
02568 token = NULL;
02569 CHECK_PARSING_STATUS (status, TRUE);
02570 }
02571
02572
02573 do {
02574 if (token) {
02575 cr_token_destroy (token);
02576 token = NULL;
02577 }
02578 status = cr_tknzr_get_next_token
02579 (PRIVATE (a_this)->tknzr, &token);
02580
02581 if (status == CR_END_OF_INPUT_ERROR)
02582 goto done;
02583 CHECK_PARSING_STATUS (status, TRUE);
02584 } while (token
02585 && (token->type == S_TK
02586 || token->type == CDO_TK || token->type == CDC_TK));
02587
02588 if (token) {
02589 status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
02590 token);
02591 token = NULL;
02592 }
02593
02594 for (;;) {
02595 status = cr_tknzr_get_next_token
02596 (PRIVATE (a_this)->tknzr, &token);
02597 if (status == CR_END_OF_INPUT_ERROR)
02598 goto done;
02599 CHECK_PARSING_STATUS (status, TRUE);
02600
02601 if (token && token->type == IMPORT_SYM_TK) {
02602 GList *media_list = NULL;
02603 GString *import_string = NULL;
02604
02605 status = cr_tknzr_unget_token
02606 (PRIVATE (a_this)->tknzr, token);
02607 token = NULL;
02608 CHECK_PARSING_STATUS (status, TRUE);
02609
02610 status = cr_parser_parse_import (a_this,
02611 &media_list,
02612 &import_string);
02613
02614 if (status == CR_OK) {
02615 if (import_string
02616 && PRIVATE (a_this)->sac_handler
02617 && PRIVATE (a_this)->sac_handler->
02618 import_style) {
02619 PRIVATE (a_this)->sac_handler->
02620 import_style (PRIVATE
02621 (a_this)->
02622 sac_handler,
02623 media_list,
02624 import_string,
02625 NULL);
02626
02627 if ((PRIVATE (a_this)->sac_handler->
02628 resolve_import == TRUE)) {
02629
02630
02631
02632
02633 }
02634
02635 if ((PRIVATE (a_this)->sac_handler->
02636 import_style_result)) {
02637 PRIVATE (a_this)->
02638 sac_handler->
02639 import_style_result
02640 (PRIVATE (a_this)->
02641 sac_handler,
02642 media_list,
02643 import_string,
02644 NULL, NULL);
02645 }
02646 }
02647 } else if (status != CR_END_OF_INPUT_ERROR) {
02648 if (PRIVATE (a_this)->sac_handler
02649 && PRIVATE (a_this)->sac_handler->error) {
02650 PRIVATE (a_this)->sac_handler->
02651 error
02652 (PRIVATE (a_this)->
02653 sac_handler);
02654 }
02655 status = cr_parser_parse_atrule_core (a_this);
02656 CHECK_PARSING_STATUS (status, TRUE) ;
02657 } else {
02658 goto error ;
02659 }
02660
02661
02662
02663
02664
02665
02666 if (media_list) {
02667 GList *cur = NULL;
02668
02669
02670 for (cur = media_list; cur; cur = cur->next) {
02671 if (cur->data) {
02672 g_string_free (cur->data,
02673 TRUE);
02674 }
02675 }
02676
02677 g_list_free (media_list);
02678 media_list = NULL;
02679 }
02680
02681 if (import_string) {
02682 g_string_free (import_string, TRUE);
02683 import_string = NULL;
02684 }
02685
02686 cr_parser_try_to_skip_spaces_and_comments (a_this);
02687 } else if (token
02688 && (token->type == S_TK
02689 || token->type == CDO_TK
02690 || token->type == CDC_TK)) {
02691 status = cr_tknzr_unget_token
02692 (PRIVATE (a_this)->tknzr, token);
02693 token = NULL;
02694
02695 do {
02696 if (token) {
02697 cr_token_destroy (token);
02698 token = NULL;
02699 }
02700
02701 status = cr_tknzr_get_next_token
02702 (PRIVATE (a_this)->tknzr, &token);
02703
02704 if (status == CR_END_OF_INPUT_ERROR)
02705 goto done;
02706 CHECK_PARSING_STATUS (status, TRUE);
02707 } while (token
02708 && (token->type == S_TK
02709 || token->type == CDO_TK
02710 || token->type == CDC_TK));
02711 } else {
02712 if (token) {
02713 status = cr_tknzr_unget_token
02714 (PRIVATE (a_this)->tknzr, token);
02715 token = NULL;
02716 }
02717 goto parse_ruleset_and_others;
02718 }
02719 }
02720
02721 parse_ruleset_and_others:
02722
02723 cr_parser_try_to_skip_spaces_and_comments (a_this);
02724
02725 for (;;) {
02726 status = cr_tknzr_get_next_token
02727 (PRIVATE (a_this)->tknzr, &token);
02728 if (status == CR_END_OF_INPUT_ERROR)
02729 goto done;
02730 CHECK_PARSING_STATUS (status, TRUE);
02731
02732 if (token
02733 && (token->type == S_TK
02734 || token->type == CDO_TK || token->type == CDC_TK)) {
02735 status = cr_tknzr_unget_token
02736 (PRIVATE (a_this)->tknzr, token);
02737 token = NULL;
02738
02739 do {
02740 if (token) {
02741 cr_token_destroy (token);
02742 token = NULL;
02743 }
02744
02745 cr_parser_try_to_skip_spaces_and_comments
02746 (a_this);
02747 status = cr_tknzr_get_next_token
02748 (PRIVATE (a_this)->tknzr, &token);
02749 } while (token
02750 && (token->type == S_TK
02751 || token->type == COMMENT_TK
02752 || token->type == CDO_TK
02753 || token->type == CDC_TK));
02754 if (token) {
02755 cr_tknzr_unget_token
02756 (PRIVATE (a_this)->tknzr, token);
02757 token = NULL;
02758 }
02759 } else if (token
02760 && (token->type == HASH_TK
02761 || (token->type == DELIM_TK
02762 && token->u.unichar == '.')
02763 || (token->type == DELIM_TK
02764 && token->u.unichar == ':')
02765 || (token->type == DELIM_TK
02766 && token->u.unichar == '*')
02767 || (token->type == BO_TK)
02768 || token->type == IDENT_TK)) {
02769
02770
02771
02772
02773
02774 status = cr_tknzr_unget_token
02775 (PRIVATE (a_this)->tknzr, token);
02776 CHECK_PARSING_STATUS (status, TRUE);
02777 token = NULL;
02778
02779 status = cr_parser_parse_ruleset (a_this);
02780
02781 if (status == CR_OK) {
02782 continue;
02783 } else {
02784 if (PRIVATE (a_this)->sac_handler
02785 && PRIVATE (a_this)->sac_handler->error) {
02786 PRIVATE (a_this)->sac_handler->
02787 error
02788 (PRIVATE (a_this)->
02789 sac_handler);
02790 }
02791
02792 status = cr_parser_parse_ruleset_core
02793 (a_this);
02794
02795 if (status == CR_OK) {
02796 continue;
02797 } else {
02798 break;
02799 }
02800 }
02801 } else if (token && token->type == MEDIA_SYM_TK) {
02802 status = cr_tknzr_unget_token
02803 (PRIVATE (a_this)->tknzr, token);
02804 CHECK_PARSING_STATUS (status, TRUE);
02805 token = NULL;
02806
02807 status = cr_parser_parse_media (a_this);
02808 if (status == CR_OK) {
02809 continue;
02810 } else {
02811 if (PRIVATE (a_this)->sac_handler
02812 && PRIVATE (a_this)->sac_handler->error) {
02813 PRIVATE (a_this)->sac_handler->
02814 error
02815 (PRIVATE (a_this)->
02816 sac_handler);
02817 }
02818
02819 status = cr_parser_parse_atrule_core (a_this);
02820
02821 if (status == CR_OK) {
02822 continue;
02823 } else {
02824 break;
02825 }
02826 }
02827
02828 } else if (token && token->type == PAGE_SYM_TK) {
02829 status = cr_tknzr_unget_token
02830 (PRIVATE (a_this)->tknzr, token);
02831 CHECK_PARSING_STATUS (status, TRUE);
02832 token = NULL;
02833 status = cr_parser_parse_page (a_this);
02834
02835 if (status == CR_OK) {
02836 continue;
02837 } else {
02838 if (PRIVATE (a_this)->sac_handler
02839 && PRIVATE (a_this)->sac_handler->error) {
02840 PRIVATE (a_this)->sac_handler->
02841 error
02842 (PRIVATE (a_this)->
02843 sac_handler);
02844 }
02845
02846 status = cr_parser_parse_atrule_core (a_this);
02847
02848 if (status == CR_OK) {
02849 continue;
02850 } else {
02851 break;
02852 }
02853 }
02854 } else if (token && token->type == FONT_FACE_SYM_TK) {
02855 status = cr_tknzr_unget_token
02856 (PRIVATE (a_this)->tknzr, token);
02857 CHECK_PARSING_STATUS (status, TRUE);
02858 token = NULL;
02859 status = cr_parser_parse_font_face (a_this);
02860
02861 if (status == CR_OK) {
02862 continue;
02863 } else {
02864 if (PRIVATE (a_this)->sac_handler
02865 && PRIVATE (a_this)->sac_handler->error) {
02866 PRIVATE (a_this)->sac_handler->
02867 error
02868 (PRIVATE (a_this)->
02869 sac_handler);
02870 }
02871
02872 status = cr_parser_parse_atrule_core (a_this);
02873
02874 if (status == CR_OK) {
02875 continue;
02876 } else {
02877 break;
02878 }
02879 }
02880 } else {
02881 status = cr_tknzr_unget_token
02882 (PRIVATE (a_this)->tknzr, token);
02883 CHECK_PARSING_STATUS (status, TRUE);
02884 token = NULL;
02885 status = cr_parser_parse_statement_core (a_this);
02886
02887 if (status == CR_OK) {
02888 continue;
02889 } else {
02890 break;
02891 }
02892 }
02893 }
02894
02895 done:
02896 if (token) {
02897 cr_token_destroy (token);
02898 token = NULL;
02899 }
02900
02901 if (status == CR_END_OF_INPUT_ERROR || status == CR_OK) {
02902
02903 if (PRIVATE (a_this)->sac_handler
02904 && PRIVATE (a_this)->sac_handler->end_document) {
02905 PRIVATE (a_this)->sac_handler->end_document
02906 (PRIVATE (a_this)->sac_handler);
02907 }
02908
02909 return CR_OK;
02910 }
02911
02912 cr_parser_push_error
02913 (a_this, "could not recognize next production", CR_ERROR);
02914
02915 if (PRIVATE (a_this)->sac_handler
02916 && PRIVATE (a_this)->sac_handler->unrecoverable_error) {
02917 PRIVATE (a_this)->sac_handler->
02918 unrecoverable_error (PRIVATE (a_this)->sac_handler);
02919 }
02920
02921 cr_parser_dump_err_stack (a_this, TRUE);
02922
02923 return status;
02924
02925 error:
02926
02927 if (token) {
02928 cr_token_destroy (token);
02929 token = NULL;
02930 }
02931
02932 if (PRIVATE (a_this)->sac_handler
02933 && PRIVATE (a_this)->sac_handler->unrecoverable_error) {
02934 PRIVATE (a_this)->sac_handler->
02935 unrecoverable_error (PRIVATE (a_this)->sac_handler);
02936 }
02937
02938 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
02939
02940 return status;
02941 }
02942
02943
02944
02945
02946
02947
02948
02949
02950
02951
02952
02953
02954
02955
02956
02957 CRParser *
02958 cr_parser_new (CRTknzr * a_tknzr)
02959 {
02960 CRParser *result = NULL;
02961 enum CRStatus status = CR_OK;
02962
02963 result = g_malloc0 (sizeof (CRParser));
02964
02965 PRIVATE (result) = g_malloc0 (sizeof (CRParserPriv));
02966
02967 if (a_tknzr) {
02968 status = cr_parser_set_tknzr (result, a_tknzr);
02969 }
02970
02971 g_return_val_if_fail (status == CR_OK, NULL);
02972
02973 return result;
02974 }
02975
02976
02977
02978
02979
02980
02981
02982
02983
02984
02985
02986
02987 CRParser *
02988 cr_parser_new_from_buf (guchar * a_buf,
02989 gulong a_len,
02990 enum CREncoding a_enc,
02991 gboolean a_free_buf)
02992 {
02993 CRParser *result = NULL;
02994 CRInput *input = NULL;
02995
02996 g_return_val_if_fail (a_buf && a_len, NULL);
02997
02998 input = cr_input_new_from_buf (a_buf, a_len, a_enc, a_free_buf);
02999 g_return_val_if_fail (input, NULL);
03000
03001 result = cr_parser_new_from_input (input);
03002 if (!result) {
03003 cr_input_destroy (input);
03004 input = NULL;
03005 return NULL;
03006 }
03007 return result;
03008 }
03009
03010 CRParser *
03011 cr_parser_new_from_input (CRInput * a_input)
03012 {
03013 CRParser *result = NULL;
03014 CRTknzr *tokenizer = NULL;
03015
03016 if (a_input) {
03017 tokenizer = cr_tknzr_new (a_input);
03018 g_return_val_if_fail (tokenizer, NULL);
03019 }
03020
03021 result = cr_parser_new (tokenizer);
03022 g_return_val_if_fail (result, NULL);
03023
03024 return result;
03025 }
03026
03027 CRParser *
03028 cr_parser_new_from_file (const guchar * a_file_uri, enum CREncoding a_enc)
03029 {
03030 CRParser *result = NULL;
03031 CRTknzr *tokenizer = NULL;
03032
03033 tokenizer = cr_tknzr_new_from_uri (a_file_uri, a_enc);
03034 if (!tokenizer) {
03035 cr_utils_trace_info ("Could not open input file");
03036 return NULL;
03037 }
03038
03039 result = cr_parser_new (tokenizer);
03040 g_return_val_if_fail (result, NULL);
03041 return result;
03042 }
03043
03044
03045
03046
03047
03048
03049
03050 enum CRStatus
03051 cr_parser_set_sac_handler (CRParser * a_this, CRDocHandler * a_handler)
03052 {
03053 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
03054
03055 if (PRIVATE (a_this)->sac_handler) {
03056 cr_doc_handler_unref (PRIVATE (a_this)->sac_handler);
03057 }
03058
03059 PRIVATE (a_this)->sac_handler = a_handler;
03060 cr_doc_handler_ref (a_handler);
03061
03062 return CR_OK;
03063 }
03064
03065
03066
03067
03068
03069
03070
03071
03072
03073 enum CRStatus
03074 cr_parser_get_sac_handler (CRParser * a_this, CRDocHandler ** a_handler)
03075 {
03076 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
03077
03078 *a_handler = PRIVATE (a_this)->sac_handler;
03079
03080 return CR_OK;
03081 }
03082
03083
03084
03085
03086
03087
03088
03089 enum CRStatus
03090 cr_parser_set_default_sac_handler (CRParser * a_this)
03091 {
03092 CRDocHandler *default_sac_handler = NULL;
03093 enum CRStatus status = CR_ERROR;
03094
03095 g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
03096
03097 default_sac_handler = cr_doc_handler_new ();
03098
03099 cr_doc_handler_set_default_sac_handler (default_sac_handler);
03100
03101 status = cr_parser_set_sac_handler (a_this, default_sac_handler);
03102
03103 if (status != CR_OK) {
03104 cr_doc_handler_destroy (default_sac_handler);
03105 default_sac_handler = NULL;
03106 }
03107
03108 return status;
03109 }
03110
03111 enum CRStatus
03112 cr_parser_set_use_core_grammar (CRParser * a_this,
03113 gboolean a_use_core_grammar)
03114 {
03115 g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
03116
03117 PRIVATE (a_this)->use_core_grammar = a_use_core_grammar;
03118
03119 return CR_OK;
03120 }
03121
03122 enum CRStatus
03123 cr_parser_get_use_core_grammar (CRParser * a_this,
03124 gboolean * a_use_core_grammar)
03125 {
03126 g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
03127
03128 *a_use_core_grammar = PRIVATE (a_this)->use_core_grammar;
03129
03130 return CR_OK;
03131 }
03132
03133
03134
03135
03136
03137
03138
03139
03140 enum CRStatus
03141 cr_parser_parse_file (CRParser * a_this,
03142 const guchar * a_file_uri, enum CREncoding a_enc)
03143 {
03144 enum CRStatus status = CR_ERROR;
03145 CRTknzr *tknzr = NULL;
03146
03147 g_return_val_if_fail (a_this && PRIVATE (a_this)
03148 && a_file_uri, CR_BAD_PARAM_ERROR);
03149
03150 tknzr = cr_tknzr_new_from_uri (a_file_uri, a_enc);
03151
03152 g_return_val_if_fail (tknzr != NULL, CR_ERROR);
03153
03154 status = cr_parser_set_tknzr (a_this, tknzr);
03155 g_return_val_if_fail (status == CR_OK, CR_ERROR);
03156
03157 status = cr_parser_parse (a_this);
03158
03159 return status;
03160 }
03161
03162
03163
03164
03165
03166
03167 enum CRStatus
03168 cr_parser_parse_expr (CRParser * a_this, CRTerm ** a_expr)
03169 {
03170 enum CRStatus status = CR_ERROR;
03171 CRInputPos init_pos;
03172 CRTerm *expr = NULL,
03173 *expr2 = NULL;
03174 guchar next_byte = 0;
03175 gulong nb_terms = 0;
03176
03177 g_return_val_if_fail (a_this && PRIVATE (a_this)
03178 && a_expr, CR_BAD_PARAM_ERROR);
03179
03180 RECORD_INITIAL_POS (a_this, &init_pos);
03181
03182 status = cr_parser_parse_term (a_this, &expr);
03183
03184 CHECK_PARSING_STATUS (status, FALSE);
03185
03186 for (;;) {
03187 guchar operator = 0;
03188
03189 status = cr_tknzr_peek_byte (PRIVATE (a_this)->tknzr,
03190 1, &next_byte);
03191 if (status != CR_OK) {
03192 if (status == CR_END_OF_INPUT_ERROR) {
03193
03194
03195
03196
03197
03198
03199 status = CR_OK;
03200 break;
03201 } else {
03202 goto error;
03203 }
03204 }
03205
03206 if (next_byte == '/' || next_byte == ',') {
03207 READ_NEXT_BYTE (a_this, &operator);
03208 }
03209
03210 cr_parser_try_to_skip_spaces_and_comments (a_this);
03211
03212 status = cr_parser_parse_term (a_this, &expr2);
03213
03214 if (status != CR_OK || expr2 == NULL) {
03215 status = CR_OK;
03216 break;
03217 }
03218
03219 switch (operator) {
03220 case '/':
03221 expr2->the_operator = DIVIDE;
03222 break;
03223 case ',':
03224 expr2->the_operator = COMMA;
03225
03226 default:
03227 break;
03228 }
03229
03230 expr = cr_term_append_term (expr, expr2);
03231 expr2 = NULL;
03232 operator = 0;
03233 nb_terms++;
03234 }
03235
03236 if (status == CR_OK) {
03237 *a_expr = cr_term_append_term (*a_expr, expr);
03238 expr = NULL;
03239
03240 cr_parser_clear_errors (a_this);
03241 return CR_OK;
03242 }
03243
03244 error:
03245
03246 if (expr) {
03247 cr_term_destroy (expr);
03248 expr = NULL;
03249 }
03250
03251 if (expr2) {
03252 cr_term_destroy (expr2);
03253 expr2 = NULL;
03254 }
03255
03256 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
03257
03258 return status;
03259 }
03260
03261
03262
03263
03264
03265
03266
03267
03268
03269
03270 enum CRStatus
03271 cr_parser_parse_prio (CRParser * a_this, GString ** a_prio)
03272 {
03273 enum CRStatus status = CR_ERROR;
03274 CRInputPos init_pos;
03275 CRToken *token = NULL;
03276
03277 g_return_val_if_fail (a_this && PRIVATE (a_this)
03278 && a_prio
03279 && *a_prio == NULL, CR_BAD_PARAM_ERROR);
03280
03281 RECORD_INITIAL_POS (a_this, &init_pos);
03282
03283 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
03284 if (status == CR_END_OF_INPUT_ERROR) {
03285 goto error;
03286 }
03287 ENSURE_PARSING_COND (status == CR_OK
03288 && token && token->type == IMPORTANT_SYM_TK);
03289
03290 cr_parser_try_to_skip_spaces_and_comments (a_this);
03291 *a_prio = g_string_new ("!important");
03292 cr_token_destroy (token);
03293 token = NULL;
03294 return CR_OK;
03295
03296 error:
03297 if (token) {
03298 cr_token_destroy (token);
03299 token = NULL;
03300 }
03301 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
03302
03303 return status;
03304 }
03305
03306
03307
03308
03309
03310
03311
03312
03313
03314
03315
03316
03317
03318
03319 enum CRStatus
03320 cr_parser_parse_declaration (CRParser * a_this,
03321 GString ** a_property,
03322 CRTerm ** a_expr, gboolean * a_important)
03323 {
03324 enum CRStatus status = CR_ERROR;
03325 CRInputPos init_pos;
03326 guint32 cur_char = 0;
03327 CRTerm *expr = NULL;
03328 GString *prio = NULL;
03329
03330 g_return_val_if_fail (a_this && PRIVATE (a_this)
03331 && a_property && a_expr
03332 && a_important, CR_BAD_PARAM_ERROR);
03333
03334 RECORD_INITIAL_POS (a_this, &init_pos);
03335
03336 status = cr_parser_parse_property (a_this, a_property);
03337
03338 if (status == CR_END_OF_INPUT_ERROR)
03339 goto error;
03340
03341 CHECK_PARSING_STATUS_ERR
03342 (a_this, status, FALSE,
03343 "while parsing declaration: next property is malformed",
03344 CR_SYNTAX_ERROR);
03345
03346 READ_NEXT_CHAR (a_this, &cur_char);
03347
03348 if (cur_char != ':') {
03349 status = CR_PARSING_ERROR;
03350 cr_parser_push_error
03351 (a_this,
03352 "while parsing declaration: this char must be ':'",
03353 CR_SYNTAX_ERROR);
03354 goto error;
03355 }
03356
03357 cr_parser_try_to_skip_spaces_and_comments (a_this);
03358
03359 status = cr_parser_parse_expr (a_this, &expr);
03360
03361 CHECK_PARSING_STATUS_ERR
03362 (a_this, status, FALSE,
03363 "while parsing declaration: next expression is malformed",
03364 CR_SYNTAX_ERROR);
03365
03366 cr_parser_try_to_skip_spaces_and_comments (a_this);
03367 status = cr_parser_parse_prio (a_this, &prio);
03368 if (prio) {
03369 g_string_free (prio, TRUE);
03370 prio = NULL;
03371 *a_important = TRUE;
03372 } else {
03373 *a_important = FALSE;
03374 }
03375 if (*a_expr) {
03376 cr_term_append_term (*a_expr, expr);
03377 expr = NULL;
03378 } else {
03379 *a_expr = expr;
03380 expr = NULL;
03381 }
03382
03383 cr_parser_clear_errors (a_this);
03384 return CR_OK;
03385
03386 error:
03387
03388 if (expr) {
03389 cr_term_destroy (expr);
03390 expr = NULL;
03391 }
03392
03393 if (*a_property) {
03394 g_string_free (*a_property, TRUE);
03395 *a_property = NULL;
03396 }
03397
03398 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
03399
03400 return status;
03401 }
03402
03403
03404
03405
03406
03407
03408
03409
03410 enum CRStatus
03411 cr_parser_parse_statement_core (CRParser * a_this)
03412 {
03413 CRToken *token = NULL;
03414 CRInputPos init_pos;
03415 enum CRStatus status = CR_ERROR;
03416
03417 g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
03418
03419 RECORD_INITIAL_POS (a_this, &init_pos);
03420
03421 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
03422
03423 ENSURE_PARSING_COND (status == CR_OK && token);
03424
03425 switch (token->type) {
03426 case ATKEYWORD_TK:
03427 case IMPORT_SYM_TK:
03428 case PAGE_SYM_TK:
03429 case MEDIA_SYM_TK:
03430 case FONT_FACE_SYM_TK:
03431 case CHARSET_SYM_TK:
03432 cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
03433 token = NULL;
03434 status = cr_parser_parse_atrule_core (a_this);
03435 CHECK_PARSING_STATUS (status, TRUE);
03436 break;
03437
03438 default:
03439 cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
03440 token = NULL;
03441 status = cr_parser_parse_ruleset_core (a_this);
03442 cr_parser_clear_errors (a_this);
03443 CHECK_PARSING_STATUS (status, TRUE);
03444 }
03445
03446 return CR_OK;
03447
03448 error:
03449 if (token) {
03450 cr_token_destroy (token);
03451 token = NULL;
03452 }
03453
03454 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
03455
03456 return status;
03457 }
03458
03459
03460
03461
03462
03463
03464
03465
03466
03467
03468
03469
03470
03471 enum CRStatus
03472 cr_parser_parse_ruleset (CRParser * a_this)
03473 {
03474 enum CRStatus status = CR_OK;
03475 CRInputPos init_pos;
03476 guint32 cur_char = 0,
03477 next_char = 0;
03478 GString *property = NULL;
03479 CRTerm *expr = NULL;
03480 CRSimpleSel *simple_sels = NULL;
03481 CRSelector *selector = NULL;
03482 gboolean start_selector = FALSE,
03483 is_important = FALSE;
03484
03485 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
03486
03487 RECORD_INITIAL_POS (a_this, &init_pos);
03488
03489 status = cr_parser_parse_selector (a_this, &selector);
03490 CHECK_PARSING_STATUS (status, FALSE);
03491
03492 READ_NEXT_CHAR (a_this, &cur_char);
03493
03494 ENSURE_PARSING_COND_ERR
03495 (a_this, cur_char == '{',
03496 "while parsing rulset: current char should be '{'",
03497 CR_SYNTAX_ERROR);
03498
03499 if (PRIVATE (a_this)->sac_handler
03500 && PRIVATE (a_this)->sac_handler->start_selector) {
03501
03502
03503
03504
03505 if (selector) {
03506 cr_selector_ref (selector);
03507 }
03508
03509 PRIVATE (a_this)->sac_handler->start_selector
03510 (PRIVATE (a_this)->sac_handler, selector);
03511 start_selector = TRUE;
03512 }
03513
03514 cr_parser_try_to_skip_spaces_and_comments (a_this);
03515
03516 PRIVATE (a_this)->state = TRY_PARSE_RULESET_STATE;
03517
03518 status = cr_parser_parse_declaration (a_this, &property,
03519 &expr, &is_important);
03520 if (expr) {
03521 cr_term_ref (expr);
03522 }
03523 if (status == CR_OK
03524 && PRIVATE (a_this)->sac_handler
03525 && PRIVATE (a_this)->sac_handler->property) {
03526 PRIVATE (a_this)->sac_handler->property
03527 (PRIVATE (a_this)->sac_handler, property, expr,
03528 is_important);
03529 }
03530 if (status == CR_OK) {
03531
03532
03533
03534
03535
03536 if (property) {
03537 g_string_free (property, TRUE);
03538 property = NULL;
03539 }
03540 if (expr) {
03541 cr_term_unref (expr);
03542 expr = NULL;
03543 }
03544 } else {
03545 guint32 c = 0 ;
03546
03547
03548
03549
03550
03551 status = cr_tknzr_peek_char (PRIVATE (a_this)->tknzr, &c) ;
03552 if (status == CR_OK && c == '}') {
03553 status = CR_OK ;
03554 goto end_of_ruleset ;
03555 }
03556 }
03557 CHECK_PARSING_STATUS_ERR
03558 (a_this, status, FALSE,
03559 "while parsing ruleset: next construction should be a declaration",
03560 CR_SYNTAX_ERROR);
03561
03562 for (;;) {
03563 PEEK_NEXT_CHAR (a_this, &next_char);
03564 if (next_char != ';')
03565 break;
03566
03567
03568 READ_NEXT_CHAR (a_this, &cur_char);
03569
03570 cr_parser_try_to_skip_spaces_and_comments (a_this);
03571
03572 status = cr_parser_parse_declaration (a_this, &property,
03573 &expr, &is_important);
03574
03575 if (expr) {
03576 cr_term_ref (expr);
03577 }
03578 if (status == CR_OK
03579 && PRIVATE (a_this)->sac_handler
03580 && PRIVATE (a_this)->sac_handler->property) {
03581 PRIVATE (a_this)->sac_handler->property
03582 (PRIVATE (a_this)->sac_handler,
03583 property, expr, is_important);
03584 }
03585 if (property) {
03586 g_string_free (property, TRUE);
03587 property = NULL;
03588 }
03589 if (expr) {
03590 cr_term_unref (expr);
03591 expr = NULL;
03592 }
03593 }
03594
03595 end_of_ruleset:
03596 cr_parser_try_to_skip_spaces_and_comments (a_this);
03597 READ_NEXT_CHAR (a_this, &cur_char);
03598 ENSURE_PARSING_COND_ERR
03599 (a_this, cur_char == '}',
03600 "while parsing rulset: current char must be a '}'",
03601 CR_SYNTAX_ERROR);
03602
03603 if (PRIVATE (a_this)->sac_handler
03604 && PRIVATE (a_this)->sac_handler->end_selector) {
03605 PRIVATE (a_this)->sac_handler->end_selector
03606 (PRIVATE (a_this)->sac_handler, selector);
03607 start_selector = FALSE;
03608 }
03609
03610 if (expr) {
03611 cr_term_unref (expr);
03612 expr = NULL;
03613 }
03614
03615 if (simple_sels) {
03616 cr_simple_sel_destroy (simple_sels);
03617 simple_sels = NULL;
03618 }
03619
03620 if (selector) {
03621 cr_selector_unref (selector);
03622 selector = NULL;
03623 }
03624
03625 cr_parser_clear_errors (a_this);
03626 PRIVATE (a_this)->state = RULESET_PARSED_STATE;
03627
03628 return CR_OK;
03629
03630 error:
03631 if (start_selector == TRUE
03632 && PRIVATE (a_this)->sac_handler
03633 && PRIVATE (a_this)->sac_handler->error) {
03634 PRIVATE (a_this)->sac_handler->error
03635 (PRIVATE (a_this)->sac_handler);
03636 }
03637 if (expr) {
03638 cr_term_unref (expr);
03639 expr = NULL;
03640 }
03641 if (simple_sels) {
03642 cr_simple_sel_destroy (simple_sels);
03643 simple_sels = NULL;
03644 }
03645 if (property) {
03646 g_string_free (property, TRUE);
03647 }
03648 if (selector) {
03649 cr_selector_unref (selector);
03650 selector = NULL;
03651 }
03652
03653 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
03654
03655 return status;
03656 }
03657
03658
03659
03660
03661
03662
03663
03664
03665
03666
03667
03668
03669
03670
03671
03672
03673
03674
03675
03676
03677
03678
03679
03680
03681
03682
03683 enum CRStatus
03684 cr_parser_parse_import (CRParser * a_this,
03685 GList ** a_media_list, GString ** a_import_string)
03686 {
03687 enum CRStatus status = CR_OK;
03688 CRInputPos init_pos;
03689 guint32 cur_char = 0,
03690 next_char = 0;
03691 GString *medium = NULL;
03692
03693 g_return_val_if_fail (a_this
03694 && a_import_string
03695 && (*a_import_string == NULL),
03696 CR_BAD_PARAM_ERROR);
03697
03698 RECORD_INITIAL_POS (a_this, &init_pos);
03699
03700 if (BYTE (a_this, 1, NULL) == '@'
03701 && BYTE (a_this, 2, NULL) == 'i'
03702 && BYTE (a_this, 3, NULL) == 'm'
03703 && BYTE (a_this, 4, NULL) == 'p'
03704 && BYTE (a_this, 5, NULL) == 'o'
03705 && BYTE (a_this, 6, NULL) == 'r'
03706 && BYTE (a_this, 7, NULL) == 't') {
03707 SKIP_CHARS (a_this, 7);
03708 status = CR_OK;
03709 } else {
03710 status = CR_PARSING_ERROR;
03711 goto error;
03712 }
03713
03714 cr_parser_try_to_skip_spaces_and_comments (a_this);
03715
03716 PRIVATE (a_this)->state = TRY_PARSE_IMPORT_STATE;
03717
03718 PEEK_NEXT_CHAR (a_this, &next_char);
03719
03720 if (next_char == '"' || next_char == '\'') {
03721 status = cr_parser_parse_string (a_this, a_import_string);
03722
03723 CHECK_PARSING_STATUS (status, FALSE);
03724 } else {
03725 status = cr_parser_parse_uri (a_this, a_import_string);
03726
03727 CHECK_PARSING_STATUS (status, FALSE);
03728 }
03729
03730 cr_parser_try_to_skip_spaces_and_comments (a_this);
03731
03732 status = cr_parser_parse_ident (a_this, &medium);
03733
03734 if (status == CR_OK && medium) {
03735 *a_media_list = g_list_append (*a_media_list, medium);
03736 medium = NULL;
03737 }
03738
03739 cr_parser_try_to_skip_spaces_and_comments (a_this);
03740
03741 for (; status == CR_OK;) {
03742 if ((status = cr_tknzr_peek_char (PRIVATE (a_this)->tknzr,
03743 &next_char)) != CR_OK) {
03744 if (status == CR_END_OF_INPUT_ERROR) {
03745 status = CR_OK;
03746 goto okay;
03747 }
03748 goto error;
03749 }
03750
03751 if (next_char == ',') {
03752 READ_NEXT_CHAR (a_this, &cur_char);
03753 } else {
03754 break;
03755 }
03756
03757 cr_parser_try_to_skip_spaces_and_comments (a_this);
03758
03759 status = cr_parser_parse_ident (a_this, &medium);
03760
03761 cr_parser_try_to_skip_spaces_and_comments (a_this);
03762
03763 if ((status == CR_OK) && medium) {
03764 *a_media_list = g_list_append (*a_media_list, medium);
03765
03766 medium = NULL;
03767 }
03768
03769 CHECK_PARSING_STATUS (status, FALSE);
03770 cr_parser_try_to_skip_spaces_and_comments (a_this);
03771 }
03772 cr_parser_try_to_skip_spaces_and_comments (a_this);
03773 READ_NEXT_CHAR (a_this, &cur_char);
03774 ENSURE_PARSING_COND (cur_char == ';');
03775 cr_parser_try_to_skip_spaces_and_comments (a_this);
03776 okay:
03777 cr_parser_clear_errors (a_this);
03778 PRIVATE (a_this)->state = IMPORT_PARSED_STATE;
03779
03780 return CR_OK;
03781
03782 error:
03783
03784 if (*a_media_list) {
03785 GList *cur = NULL;
03786
03787
03788
03789
03790
03791
03792
03793
03794
03795
03796
03797 for (cur = *a_media_list; cur; cur = cur->next) {
03798 if (cur->data) {
03799 g_string_free (cur->data, TRUE);
03800 }
03801 }
03802
03803 g_list_free (*a_media_list);
03804 *a_media_list = NULL;
03805 }
03806
03807 if (*a_import_string) {
03808 g_string_free (*a_import_string, TRUE);
03809 *a_import_string = NULL;
03810 }
03811
03812 if (medium) {
03813 g_string_free (medium, TRUE);
03814 medium = NULL;
03815 }
03816
03817 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
03818
03819 return status;
03820 }
03821
03822
03823
03824
03825
03826
03827
03828
03829
03830
03831
03832
03833
03834 enum CRStatus
03835 cr_parser_parse_media (CRParser * a_this)
03836 {
03837 enum CRStatus status = CR_OK;
03838 CRInputPos init_pos;
03839 CRToken *token = NULL;
03840 guint32 next_char = 0,
03841 cur_char = 0;
03842 GString *medium = NULL;
03843 GList *media_list = NULL;
03844
03845 g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
03846
03847 RECORD_INITIAL_POS (a_this, &init_pos);
03848
03849 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
03850 ENSURE_PARSING_COND (status == CR_OK
03851 && token && token->type == MEDIA_SYM_TK);
03852
03853 cr_token_destroy (token);
03854 token = NULL;
03855
03856 cr_parser_try_to_skip_spaces_and_comments (a_this);
03857
03858 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
03859 ENSURE_PARSING_COND (status == CR_OK
03860 && token && token->type == IDENT_TK);
03861
03862 medium = token->u.str;
03863 token->u.str = NULL;
03864 cr_token_destroy (token);
03865 token = NULL;
03866
03867 if (medium) {
03868 media_list = g_list_append (media_list, medium);
03869 medium = NULL;
03870 }
03871
03872 for (; status == CR_OK;) {
03873 cr_parser_try_to_skip_spaces_and_comments (a_this);
03874 PEEK_NEXT_CHAR (a_this, &next_char);
03875
03876 if (next_char == ',') {
03877 READ_NEXT_CHAR (a_this, &cur_char);
03878 } else {
03879 break;
03880 }
03881
03882 cr_parser_try_to_skip_spaces_and_comments (a_this);
03883
03884 status = cr_parser_parse_ident (a_this, &medium);
03885
03886 CHECK_PARSING_STATUS (status, FALSE);
03887
03888 if (medium) {
03889 media_list = g_list_append (media_list, medium);
03890 medium = NULL;
03891 }
03892 }
03893
03894 READ_NEXT_CHAR (a_this, &cur_char);
03895
03896 ENSURE_PARSING_COND (cur_char == '{');
03897
03898
03899
03900
03901 if (PRIVATE (a_this)->sac_handler
03902 && PRIVATE (a_this)->sac_handler->start_media) {
03903 PRIVATE (a_this)->sac_handler->start_media
03904 (PRIVATE (a_this)->sac_handler, media_list);
03905 }
03906
03907 cr_parser_try_to_skip_spaces_and_comments (a_this);
03908
03909 PRIVATE (a_this)->state = TRY_PARSE_MEDIA_STATE;
03910
03911 for (; status == CR_OK;) {
03912 status = cr_parser_parse_ruleset (a_this);
03913 cr_parser_try_to_skip_spaces_and_comments (a_this);
03914 }
03915
03916 READ_NEXT_CHAR (a_this, &cur_char);
03917
03918 ENSURE_PARSING_COND (cur_char == '}');
03919
03920
03921
03922
03923 if (PRIVATE (a_this)->sac_handler
03924 && PRIVATE (a_this)->sac_handler->end_media) {
03925 PRIVATE (a_this)->sac_handler->end_media
03926 (PRIVATE (a_this)->sac_handler, media_list);
03927 }
03928
03929 cr_parser_try_to_skip_spaces_and_comments (a_this);
03930
03931
03932
03933
03934
03935 if (medium) {
03936 g_string_free (medium, TRUE);
03937 medium = NULL;
03938 }
03939
03940 if (media_list) {
03941 GList *cur = NULL;
03942
03943 for (cur = media_list; cur; cur = cur->next) {
03944 g_string_free (cur->data, TRUE);
03945 }
03946
03947 g_list_free (media_list);
03948 media_list = NULL;
03949 }
03950
03951 cr_parser_clear_errors (a_this);
03952 PRIVATE (a_this)->state = MEDIA_PARSED_STATE;
03953
03954 return CR_OK;
03955
03956 error:
03957
03958 if (token) {
03959 cr_token_destroy (token);
03960 token = NULL;
03961 }
03962
03963 if (medium) {
03964 g_string_free (medium, TRUE);
03965 medium = NULL;
03966 }
03967
03968 if (media_list) {
03969 GList *cur = NULL;
03970
03971 for (cur = media_list; cur; cur = cur->next) {
03972 g_string_free (cur->data, TRUE);
03973 }
03974
03975 g_list_free (media_list);
03976 media_list = NULL;
03977 }
03978
03979 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
03980
03981 return status;
03982 }
03983
03984
03985
03986
03987
03988
03989
03990
03991
03992
03993
03994
03995 enum CRStatus
03996 cr_parser_parse_page (CRParser * a_this)
03997 {
03998 enum CRStatus status = CR_OK;
03999 CRInputPos init_pos;
04000 CRToken *token = NULL;
04001 CRTerm *css_expression = NULL;
04002 GString *page_selector = NULL,
04003 *page_pseudo_class = NULL,
04004 *property = NULL;
04005 gboolean important = TRUE;
04006
04007 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
04008
04009 RECORD_INITIAL_POS (a_this, &init_pos);
04010
04011 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
04012 ENSURE_PARSING_COND (status == CR_OK
04013 && token && token->type == PAGE_SYM_TK);
04014
04015 cr_token_destroy (token);
04016 token = NULL;
04017
04018 cr_parser_try_to_skip_spaces_and_comments (a_this);
04019
04020 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
04021 ENSURE_PARSING_COND (status == CR_OK && token);
04022
04023 if (token->type == IDENT_TK) {
04024 page_selector = token->u.str;
04025 token->u.str = NULL;
04026 cr_token_destroy (token);
04027 token = NULL;
04028 } else {
04029 cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
04030 token = NULL;
04031 }
04032
04033
04034
04035
04036 cr_parser_try_to_skip_spaces_and_comments (a_this);
04037 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
04038 ENSURE_PARSING_COND (status == CR_OK && token);
04039
04040 if (token->type == DELIM_TK && token->u.unichar == ':') {
04041 cr_token_destroy (token);
04042 token = NULL;
04043 status = cr_parser_parse_ident (a_this, &page_pseudo_class);
04044 CHECK_PARSING_STATUS (status, FALSE);
04045 } else {
04046 cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
04047 token = NULL;
04048 }
04049
04050
04051
04052
04053
04054 cr_parser_try_to_skip_spaces_and_comments (a_this);
04055
04056 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
04057
04058 ENSURE_PARSING_COND (status == CR_OK && token
04059 && token->type == CBO_TK);
04060
04061 cr_token_destroy (token);
04062 token = NULL;
04063
04064
04065
04066
04067 if (PRIVATE (a_this)->sac_handler
04068 && PRIVATE (a_this)->sac_handler->start_page) {
04069 PRIVATE (a_this)->sac_handler->start_page
04070 (PRIVATE (a_this)->sac_handler,
04071 page_selector, page_pseudo_class);
04072 }
04073 cr_parser_try_to_skip_spaces_and_comments (a_this);
04074
04075 PRIVATE (a_this)->state = TRY_PARSE_PAGE_STATE;
04076
04077 status = cr_parser_parse_declaration (a_this, &property,
04078 &css_expression, &important);
04079 ENSURE_PARSING_COND (status == CR_OK);
04080
04081
04082
04083
04084 if (PRIVATE (a_this)->sac_handler
04085 && PRIVATE (a_this)->sac_handler->property) {
04086 if (css_expression)
04087 cr_term_ref (css_expression);
04088
04089 PRIVATE (a_this)->sac_handler->property
04090 (PRIVATE (a_this)->sac_handler,
04091 property, css_expression, important);
04092 }
04093
04094
04095
04096
04097 if (property) {
04098 g_string_free (property, TRUE);
04099 property = NULL;
04100 }
04101 if (css_expression) {
04102 cr_term_unref (css_expression);
04103 css_expression = NULL;
04104 }
04105
04106 for (;;) {
04107
04108 if (token) {
04109 cr_token_destroy (token);
04110 token = NULL;
04111 }
04112 status = cr_tknzr_get_next_token
04113 (PRIVATE (a_this)->tknzr, &token);
04114
04115 ENSURE_PARSING_COND (status == CR_OK && token);
04116
04117 if (token->type != SEMICOLON_TK)
04118 break;
04119
04120 cr_token_destroy (token);
04121 token = NULL;
04122 cr_parser_try_to_skip_spaces_and_comments (a_this);
04123
04124 status = cr_parser_parse_declaration (a_this, &property,
04125 &css_expression,
04126 &important);
04127 CHECK_PARSING_STATUS (status, FALSE);
04128
04129
04130
04131
04132 if (PRIVATE (a_this)->sac_handler
04133 && PRIVATE (a_this)->sac_handler->property) {
04134 cr_term_ref (css_expression);
04135 PRIVATE (a_this)->sac_handler->property
04136 (PRIVATE (a_this)->sac_handler,
04137 property, css_expression, important);
04138 }
04139
04140
04141
04142
04143 if (property) {
04144 g_string_free (property, TRUE);
04145 property = NULL;
04146 }
04147 if (css_expression) {
04148 cr_term_unref (css_expression);
04149 css_expression = NULL;
04150 }
04151 }
04152 ENSURE_PARSING_COND (status == CR_OK && token
04153 && token->type == CBC_TK);
04154 cr_token_destroy (token);
04155 token = NULL;
04156
04157
04158
04159
04160 if (PRIVATE (a_this)->sac_handler
04161 && PRIVATE (a_this)->sac_handler->end_page) {
04162 PRIVATE (a_this)->sac_handler->end_page
04163 (PRIVATE (a_this)->sac_handler,
04164 page_selector, page_pseudo_class);
04165 }
04166
04167 if (page_selector) {
04168 g_string_free (page_selector, TRUE);
04169 page_selector = NULL;
04170 }
04171
04172 if (page_pseudo_class) {
04173 g_string_free (page_pseudo_class, TRUE);
04174 page_pseudo_class = NULL;
04175 }
04176
04177 cr_parser_try_to_skip_spaces_and_comments (a_this);
04178
04179
04180
04181 cr_parser_clear_errors (a_this);
04182 PRIVATE (a_this)->state = PAGE_PARSED_STATE;
04183
04184 return CR_OK;
04185
04186 error:
04187 if (token) {
04188 cr_token_destroy (token);
04189 token = NULL;
04190 }
04191 if (page_selector) {
04192 g_string_free (page_selector, TRUE);
04193 page_selector = NULL;
04194 }
04195 if (page_pseudo_class) {
04196 g_string_free (page_pseudo_class, TRUE);
04197 page_pseudo_class = NULL;
04198 }
04199 if (property) {
04200 g_string_free (property, TRUE);
04201 property = NULL;
04202 }
04203 if (css_expression) {
04204 cr_term_destroy (css_expression);
04205 css_expression = NULL;
04206 }
04207 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
04208 return status;
04209 }
04210
04211
04212
04213
04214
04215
04216
04217
04218
04219
04220
04221
04222 enum CRStatus
04223 cr_parser_parse_charset (CRParser * a_this, GString ** a_value)
04224 {
04225 enum CRStatus status = CR_OK;
04226 CRInputPos init_pos;
04227 CRToken *token = NULL;
04228 GString *charset_str = NULL;
04229
04230 g_return_val_if_fail (a_this && a_value
04231 && (*a_value == NULL), CR_BAD_PARAM_ERROR);
04232
04233 RECORD_INITIAL_POS (a_this, &init_pos);
04234
04235 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
04236
04237 ENSURE_PARSING_COND (status == CR_OK
04238 && token && token->type == CHARSET_SYM_TK);
04239
04240 cr_token_destroy (token);
04241 token = NULL;
04242
04243 PRIVATE (a_this)->state = TRY_PARSE_CHARSET_STATE;
04244
04245 cr_parser_try_to_skip_spaces_and_comments (a_this);
04246
04247 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
04248 ENSURE_PARSING_COND (status == CR_OK
04249 && token && token->type == STRING_TK);
04250 charset_str = token->u.str;
04251 token->u.str = NULL;
04252 cr_token_destroy (token);
04253 token = NULL;
04254
04255 cr_parser_try_to_skip_spaces_and_comments (a_this);
04256
04257 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
04258
04259 ENSURE_PARSING_COND (status == CR_OK
04260 && token && token->type == SEMICOLON_TK);
04261 cr_token_destroy (token);
04262 token = NULL;
04263
04264 if (charset_str) {
04265 *a_value = charset_str;
04266 charset_str = NULL;
04267 }
04268
04269 PRIVATE (a_this)->state = CHARSET_PARSED_STATE;
04270 return CR_OK;
04271
04272 error:
04273
04274 if (token) {
04275 cr_token_destroy (token);
04276 token = NULL;
04277 }
04278
04279 if (*a_value) {
04280 g_string_free (*a_value, TRUE);
04281 *a_value = NULL;
04282 }
04283
04284 if (charset_str) {
04285 g_string_free (charset_str, TRUE);
04286 charset_str = NULL;
04287 }
04288
04289 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
04290
04291 return status;
04292 }
04293
04294
04295
04296
04297
04298
04299
04300
04301
04302
04303
04304 enum CRStatus
04305 cr_parser_parse_font_face (CRParser * a_this)
04306 {
04307 enum CRStatus status = CR_ERROR;
04308 CRInputPos init_pos;
04309 GString *property = NULL;
04310 CRTerm *css_expression = NULL;
04311 CRToken *token = NULL;
04312 gboolean important = FALSE;
04313 guint32 next_char = 0,
04314 cur_char = 0;
04315
04316 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
04317
04318 RECORD_INITIAL_POS (a_this, &init_pos);
04319
04320 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
04321 ENSURE_PARSING_COND (status == CR_OK
04322 && token && token->type == FONT_FACE_SYM_TK);
04323
04324 cr_parser_try_to_skip_spaces_and_comments (a_this);
04325 if (token) {
04326 cr_token_destroy (token);
04327 token = NULL;
04328 }
04329 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
04330 ENSURE_PARSING_COND (status == CR_OK && token
04331 && token->type == CBO_TK);
04332 if (token) {
04333 cr_token_destroy (token);
04334 token = NULL;
04335 }
04336
04337
04338
04339 if (PRIVATE (a_this)->sac_handler
04340 && PRIVATE (a_this)->sac_handler->start_font_face) {
04341 PRIVATE (a_this)->sac_handler->start_font_face
04342 (PRIVATE (a_this)->sac_handler);
04343 }
04344 PRIVATE (a_this)->state = TRY_PARSE_FONT_FACE_STATE;
04345
04346
04347
04348 cr_parser_try_to_skip_spaces_and_comments (a_this);
04349 status = cr_parser_parse_declaration (a_this, &property,
04350 &css_expression, &important);
04351 if (status == CR_OK) {
04352
04353
04354
04355 cr_term_ref (css_expression);
04356 if (PRIVATE (a_this)->sac_handler &&
04357 PRIVATE (a_this)->sac_handler->property) {
04358 PRIVATE (a_this)->sac_handler->property
04359 (PRIVATE (a_this)->sac_handler,
04360 property, css_expression, important);
04361 }
04362 ENSURE_PARSING_COND (css_expression && property);
04363 }
04364
04365 if (property) {
04366 g_string_free (property, TRUE);
04367 property = NULL;
04368 }
04369 if (css_expression) {
04370 cr_term_unref (css_expression);
04371 css_expression = NULL;
04372 }
04373 for (;;) {
04374 PEEK_NEXT_CHAR (a_this, &next_char);
04375 if (next_char == ';') {
04376 READ_NEXT_CHAR (a_this, &cur_char);
04377 } else {
04378 break;
04379 }
04380 cr_parser_try_to_skip_spaces_and_comments (a_this);
04381 status = cr_parser_parse_declaration (a_this, &property,
04382 &css_expression,
04383 &important);
04384 if (status != CR_OK)
04385 break;
04386
04387
04388
04389 cr_term_ref (css_expression);
04390 if (PRIVATE (a_this)->sac_handler->property) {
04391 PRIVATE (a_this)->sac_handler->property
04392 (PRIVATE (a_this)->sac_handler,
04393 property, css_expression, important);
04394 }
04395
04396
04397
04398
04399 if (property) {
04400 g_string_free (property, TRUE);
04401 property = NULL;
04402 }
04403 if (css_expression) {
04404 cr_term_unref (css_expression);
04405 css_expression = NULL;
04406 }
04407 }
04408 cr_parser_try_to_skip_spaces_and_comments (a_this);
04409 READ_NEXT_CHAR (a_this, &cur_char);
04410 ENSURE_PARSING_COND (cur_char == '}');
04411
04412
04413
04414 if (PRIVATE (a_this)->sac_handler->end_font_face) {
04415 PRIVATE (a_this)->sac_handler->end_font_face
04416 (PRIVATE (a_this)->sac_handler);
04417 }
04418 cr_parser_try_to_skip_spaces_and_comments (a_this);
04419
04420 if (token) {
04421 cr_token_destroy (token);
04422 token = NULL;
04423 }
04424 cr_parser_clear_errors (a_this);
04425 PRIVATE (a_this)->state = FONT_FACE_PARSED_STATE;
04426 return CR_OK;
04427
04428 error:
04429 if (token) {
04430 cr_token_destroy (token);
04431 token = NULL;
04432 }
04433 if (property) {
04434 g_string_free (property, TRUE);
04435 property = NULL;
04436 }
04437 if (css_expression) {
04438 cr_term_destroy (css_expression);
04439 css_expression = NULL;
04440 }
04441 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
04442 return status;
04443 }
04444
04445
04446
04447
04448
04449
04450
04451
04452 enum CRStatus
04453 cr_parser_parse (CRParser * a_this)
04454 {
04455 enum CRStatus status = CR_ERROR;
04456
04457 g_return_val_if_fail (a_this && PRIVATE (a_this)
04458 && PRIVATE (a_this)->tknzr, CR_BAD_PARAM_ERROR);
04459
04460 if (PRIVATE (a_this)->use_core_grammar == FALSE) {
04461 status = cr_parser_parse_stylesheet (a_this);
04462 } else {
04463 status = cr_parser_parse_stylesheet_core (a_this);
04464 }
04465
04466 return status;
04467 }
04468
04469 enum CRStatus
04470 cr_parser_set_tknzr (CRParser * a_this, CRTknzr * a_tknzr)
04471 {
04472 g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
04473
04474 if (PRIVATE (a_this)->tknzr) {
04475 cr_tknzr_unref (PRIVATE (a_this)->tknzr);
04476 }
04477
04478 PRIVATE (a_this)->tknzr = a_tknzr;
04479
04480 if (a_tknzr)
04481 cr_tknzr_ref (a_tknzr);
04482
04483 return CR_OK;
04484 }
04485
04486
04487
04488
04489
04490
04491
04492
04493 enum CRStatus
04494 cr_parser_get_tknzr (CRParser * a_this, CRTknzr ** a_tknzr)
04495 {
04496 g_return_val_if_fail (a_this && PRIVATE (a_this)
04497 && a_tknzr, CR_BAD_PARAM_ERROR);
04498
04499 *a_tknzr = PRIVATE (a_this)->tknzr;
04500 return CR_OK;
04501 }
04502
04503
04504
04505
04506
04507
04508
04509
04510
04511 enum CRStatus
04512 cr_parser_parse_buf (CRParser * a_this,
04513 const guchar * a_buf,
04514 gulong a_len, enum CREncoding a_enc)
04515 {
04516 enum CRStatus status = CR_ERROR;
04517 CRTknzr *tknzr = NULL;
04518
04519 g_return_val_if_fail (a_this && PRIVATE (a_this)
04520 && a_buf, CR_BAD_PARAM_ERROR);
04521
04522 tknzr = cr_tknzr_new_from_buf ((guchar*)a_buf, a_len, a_enc, FALSE);
04523
04524 g_return_val_if_fail (tknzr != NULL, CR_ERROR);
04525
04526 status = cr_parser_set_tknzr (a_this, tknzr);
04527 g_return_val_if_fail (status == CR_OK, CR_ERROR);
04528
04529 status = cr_parser_parse (a_this);
04530
04531 return status;
04532 }
04533
04534
04535
04536
04537
04538
04539
04540 void
04541 cr_parser_destroy (CRParser * a_this)
04542 {
04543 g_return_if_fail (a_this && PRIVATE (a_this));
04544
04545 if (PRIVATE (a_this)->tknzr) {
04546 if (cr_tknzr_unref (PRIVATE (a_this)->tknzr) == TRUE)
04547 PRIVATE (a_this)->tknzr = NULL;
04548 }
04549
04550 if (PRIVATE (a_this)->sac_handler) {
04551 cr_doc_handler_unref (PRIVATE (a_this)->sac_handler);
04552 PRIVATE (a_this)->sac_handler = NULL;
04553 }
04554
04555 if (PRIVATE (a_this)->err_stack) {
04556 cr_parser_clear_errors (a_this);
04557 PRIVATE (a_this)->err_stack = NULL;
04558 }
04559
04560 if (PRIVATE (a_this)) {
04561 g_free (PRIVATE (a_this));
04562 PRIVATE (a_this) = NULL;
04563 }
04564
04565 if (a_this) {
04566 g_free (a_this);
04567 a_this = NULL;
04568 }
04569 }