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 #include "string.h"
00031 #include "cr-tknzr.h"
00032 #include "cr-doc-handler.h"
00033
00034 struct _CRTknzrPriv {
00035
00036 CRInput *input;
00037
00038
00039
00040
00041
00042
00043
00044
00045 CRToken *token_cache;
00046
00047
00048
00049
00050
00051 CRInputPos prev_pos;
00052
00053 CRDocHandler *sac_handler;
00054
00055
00056
00057
00058
00059
00060 glong ref_count;
00061 };
00062
00063 #define PRIVATE(obj) ((obj)->priv)
00064
00065
00066
00067
00068
00069 #define IS_NUM(a_char) (((a_char) >= '0' && (a_char) <= '9')?TRUE:FALSE)
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080 #define CHECK_PARSING_STATUS(status, is_exception) \
00081 if ((status) != CR_OK) \
00082 { \
00083 if (is_exception == FALSE) \
00084 { \
00085 status = CR_PARSING_ERROR ; \
00086 } \
00087 goto error ; \
00088 }
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099 #define PEEK_NEXT_CHAR(a_tknzr, a_to_char) \
00100 {\
00101 status = cr_tknzr_peek_char (a_tknzr, a_to_char) ; \
00102 CHECK_PARSING_STATUS (status, TRUE) \
00103 }
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113 #define READ_NEXT_CHAR(a_tknzr, to_char) \
00114 status = cr_tknzr_read_char (a_tknzr, to_char) ;\
00115 CHECK_PARSING_STATUS (status, TRUE)
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127 #define RECORD_INITIAL_POS(a_tknzr, a_pos) \
00128 status = cr_input_get_cur_pos (PRIVATE \
00129 (a_tknzr)->input, a_pos) ; \
00130 g_return_val_if_fail (status == CR_OK, status)
00131
00132
00133
00134
00135
00136
00137
00138
00139 #define RECORD_CUR_BYTE_ADDR(a_tknzr, a_addr) \
00140 status = cr_input_get_cur_byte_addr \
00141 (PRIVATE (a_tknzr)->input, a_addr) ; \
00142 CHECK_PARSING_STATUS (status, TRUE)
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155 #define PEEK_BYTE(a_tknzr, a_offset, a_byte_ptr) \
00156 status = cr_tknzr_peek_byte (a_tknzr, \
00157 a_offset, \
00158 a_byte_ptr) ; \
00159 CHECK_PARSING_STATUS (status, TRUE) ;
00160
00161 #define BYTE(a_input, a_n, a_eof) \
00162 cr_input_peek_byte2 (a_input, a_n, a_eof)
00163
00164
00165
00166
00167
00168
00169
00170
00171 #define READ_NEXT_BYTE(a_tknzr, a_byte_ptr) \
00172 status = \
00173 cr_input_read_byte (PRIVATE (a_tknzr)->input, a_byte_ptr) ;\
00174 CHECK_PARSING_STATUS (status, TRUE) ;
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184 #define SKIP_BYTES(a_tknzr, a_nb_bytes) \
00185 status = cr_input_seek_index (PRIVATE (a_tknzr)->input, \
00186 CR_SEEK_CUR, a_nb_bytes) ; \
00187 CHECK_PARSING_STATUS (status, TRUE) ;
00188
00189
00190
00191
00192
00193
00194
00195
00196 #define SKIP_CHARS(a_tknzr, a_nb_chars) \
00197 { \
00198 glong nb_chars = a_nb_chars ; \
00199 status = cr_input_consume_chars \
00200 (PRIVATE (a_tknzr)->input,0, &nb_chars) ; \
00201 CHECK_PARSING_STATUS (status, TRUE) ; \
00202 }
00203
00204
00205
00206
00207
00208
00209
00210 #define ENSURE_PARSING_COND(condition) \
00211 if (! (condition)) {status = CR_PARSING_ERROR; goto error ;}
00212
00213 static enum CRStatus cr_tknzr_parse_nl (CRTknzr * a_this,
00214 guchar ** a_start,
00215 guchar ** a_end,
00216 CRParsingLocation *a_location);
00217
00218 static enum CRStatus cr_tknzr_parse_w (CRTknzr * a_this,
00219 guchar ** a_start,
00220 guchar ** a_end,
00221 CRParsingLocation *a_location) ;
00222
00223 static enum CRStatus cr_tknzr_parse_unicode_escape (CRTknzr * a_this,
00224 guint32 * a_unicode,
00225 CRParsingLocation *a_location) ;
00226
00227 static enum CRStatus cr_tknzr_parse_escape (CRTknzr * a_this,
00228 guint32 * a_esc_code,
00229 CRParsingLocation *a_location);
00230
00231 static enum CRStatus cr_tknzr_parse_string (CRTknzr * a_this,
00232 CRString ** a_str);
00233
00234 static enum CRStatus cr_tknzr_parse_comment (CRTknzr * a_this,
00235 CRString ** a_comment);
00236
00237 static enum CRStatus cr_tknzr_parse_nmstart (CRTknzr * a_this,
00238 guint32 * a_char,
00239 CRParsingLocation *a_location);
00240
00241 static enum CRStatus cr_tknzr_parse_num (CRTknzr * a_this,
00242 CRNum ** a_num);
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260 static enum CRStatus
00261 cr_tknzr_parse_w (CRTknzr * a_this,
00262 guchar ** a_start,
00263 guchar ** a_end,
00264 CRParsingLocation *a_location)
00265 {
00266 guint32 cur_char = 0;
00267 CRInputPos init_pos;
00268 enum CRStatus status = CR_OK;
00269
00270 g_return_val_if_fail (a_this && PRIVATE (a_this)
00271 && PRIVATE (a_this)->input
00272 && a_start && a_end,
00273 CR_BAD_PARAM_ERROR);
00274
00275 RECORD_INITIAL_POS (a_this, &init_pos);
00276
00277 *a_start = NULL;
00278 *a_end = NULL;
00279
00280 READ_NEXT_CHAR (a_this, &cur_char);
00281
00282 if (cr_utils_is_white_space (cur_char) == FALSE) {
00283 status = CR_PARSING_ERROR;
00284 goto error;
00285 }
00286 if (a_location) {
00287 cr_tknzr_get_parsing_location (a_this,
00288 a_location) ;
00289 }
00290 RECORD_CUR_BYTE_ADDR (a_this, a_start);
00291 *a_end = *a_start;
00292
00293 for (;;) {
00294 gboolean is_eof = FALSE;
00295
00296 cr_input_get_end_of_file (PRIVATE (a_this)->input, &is_eof);
00297 if (is_eof)
00298 break;
00299
00300 status = cr_tknzr_peek_char (a_this, &cur_char);
00301 if (status == CR_END_OF_INPUT_ERROR) {
00302 status = CR_OK;
00303 break;
00304 } else if (status != CR_OK) {
00305 goto error;
00306 }
00307
00308 if (cr_utils_is_white_space (cur_char) == TRUE) {
00309 READ_NEXT_CHAR (a_this, &cur_char);
00310 RECORD_CUR_BYTE_ADDR (a_this, a_end);
00311 } else {
00312 break;
00313 }
00314 }
00315
00316 return CR_OK;
00317
00318 error:
00319 cr_tknzr_set_cur_pos (a_this, &init_pos);
00320
00321 return status;
00322 }
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335 static enum CRStatus
00336 cr_tknzr_parse_nl (CRTknzr * a_this,
00337 guchar ** a_start,
00338 guchar ** a_end,
00339 CRParsingLocation *a_location)
00340 {
00341 CRInputPos init_pos;
00342 guchar next_chars[2] = { 0 };
00343 enum CRStatus status = CR_PARSING_ERROR;
00344
00345 g_return_val_if_fail (a_this && PRIVATE (a_this)
00346 && a_start && a_end, CR_BAD_PARAM_ERROR);
00347
00348 RECORD_INITIAL_POS (a_this, &init_pos);
00349
00350 PEEK_BYTE (a_this, 1, &next_chars[0]);
00351 PEEK_BYTE (a_this, 2, &next_chars[1]);
00352
00353 if ((next_chars[0] == '\r' && next_chars[1] == '\n')) {
00354 SKIP_BYTES (a_this, 1);
00355 if (a_location) {
00356 cr_tknzr_get_parsing_location
00357 (a_this, a_location) ;
00358 }
00359 SKIP_CHARS (a_this, 1);
00360
00361 RECORD_CUR_BYTE_ADDR (a_this, a_end);
00362
00363 status = CR_OK;
00364 } else if (next_chars[0] == '\n'
00365 || next_chars[0] == '\r' || next_chars[0] == '\f') {
00366 SKIP_CHARS (a_this, 1);
00367 if (a_location) {
00368 cr_tknzr_get_parsing_location
00369 (a_this, a_location) ;
00370 }
00371 RECORD_CUR_BYTE_ADDR (a_this, a_start);
00372 *a_end = *a_start;
00373 status = CR_OK;
00374 } else {
00375 status = CR_PARSING_ERROR;
00376 goto error;
00377 }
00378 return CR_OK ;
00379
00380 error:
00381 cr_tknzr_set_cur_pos (a_this, &init_pos) ;
00382 return status;
00383 }
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393 static enum CRStatus
00394 cr_tknzr_try_to_skip_spaces (CRTknzr * a_this)
00395 {
00396 enum CRStatus status = CR_ERROR;
00397 guint32 cur_char = 0;
00398
00399 g_return_val_if_fail (a_this && PRIVATE (a_this)
00400 && PRIVATE (a_this)->input, CR_BAD_PARAM_ERROR);
00401
00402 status = cr_input_peek_char (PRIVATE (a_this)->input, &cur_char);
00403
00404 if (status != CR_OK) {
00405 if (status == CR_END_OF_INPUT_ERROR)
00406 return CR_OK;
00407 return status;
00408 }
00409
00410 if (cr_utils_is_white_space (cur_char) == TRUE) {
00411 glong nb_chars = -1;
00412
00413 status = cr_input_consume_white_spaces
00414 (PRIVATE (a_this)->input, &nb_chars);
00415 }
00416
00417 return status;
00418 }
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429 static enum CRStatus
00430 cr_tknzr_parse_comment (CRTknzr * a_this,
00431 CRString ** a_comment)
00432 {
00433 enum CRStatus status = CR_OK;
00434 CRInputPos init_pos;
00435 guint32 cur_char = 0, next_char= 0;
00436 CRString *comment = NULL;
00437 CRParsingLocation loc = {0} ;
00438
00439 g_return_val_if_fail (a_this && PRIVATE (a_this)
00440 && PRIVATE (a_this)->input,
00441 CR_BAD_PARAM_ERROR);
00442
00443 RECORD_INITIAL_POS (a_this, &init_pos);
00444 READ_NEXT_CHAR (a_this, &cur_char) ;
00445 ENSURE_PARSING_COND (cur_char == '/');
00446 cr_tknzr_get_parsing_location (a_this, &loc) ;
00447
00448 READ_NEXT_CHAR (a_this, &cur_char);
00449 ENSURE_PARSING_COND (cur_char == '*');
00450 comment = cr_string_new ();
00451 for (;;) {
00452 PEEK_NEXT_CHAR (a_this, &next_char);
00453 if (next_char == '*')
00454 break;
00455 READ_NEXT_CHAR (a_this, &cur_char);
00456 g_string_append_unichar (comment->stryng, cur_char);
00457 }
00458
00459 for (;;) {
00460 READ_NEXT_CHAR(a_this, &cur_char);
00461 ENSURE_PARSING_COND (cur_char == '*');
00462 g_string_append_unichar (comment->stryng, cur_char);
00463 PEEK_NEXT_CHAR (a_this, &next_char);
00464 if (next_char != '*')
00465 break;
00466 }
00467
00468 for (;;) {
00469 if (next_char == '/')
00470 break;
00471 READ_NEXT_CHAR(a_this, &cur_char);
00472 g_string_append_unichar (comment->stryng, cur_char);
00473 for (;;) {
00474 PEEK_NEXT_CHAR (a_this, &next_char);
00475 if (next_char == '*')
00476 break;
00477 READ_NEXT_CHAR (a_this, &cur_char);
00478 g_string_append_unichar (comment->stryng, cur_char);
00479 }
00480
00481 for (;;) {
00482 READ_NEXT_CHAR(a_this, &cur_char);
00483 ENSURE_PARSING_COND (cur_char == '*');
00484 g_string_append_unichar (comment->stryng, cur_char);
00485 PEEK_NEXT_CHAR (a_this, &next_char);
00486 if (next_char != '*')
00487 break;
00488 }
00489
00490 }
00491
00492 READ_NEXT_CHAR(a_this, &cur_char);
00493 g_string_append_unichar (comment->stryng, cur_char);
00494
00495 if (status == CR_OK) {
00496 cr_parsing_location_copy (&comment->location,
00497 &loc) ;
00498 *a_comment = comment;
00499 return CR_OK;
00500 }
00501 error:
00502
00503 if (comment) {
00504 cr_string_destroy (comment);
00505 comment = NULL;
00506 }
00507
00508 cr_tknzr_set_cur_pos (a_this, &init_pos);
00509
00510 return status;
00511 }
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529 static enum CRStatus
00530 cr_tknzr_parse_unicode_escape (CRTknzr * a_this,
00531 guint32 * a_unicode,
00532 CRParsingLocation *a_location)
00533 {
00534 guint32 cur_char;
00535 CRInputPos init_pos;
00536 glong occur = 0;
00537 guint32 unicode = 0;
00538 guchar *tmp_char_ptr1 = NULL,
00539 *tmp_char_ptr2 = NULL;
00540 enum CRStatus status = CR_OK;
00541
00542 g_return_val_if_fail (a_this && PRIVATE (a_this)
00543 && a_unicode, CR_BAD_PARAM_ERROR);
00544
00545
00546 RECORD_INITIAL_POS (a_this, &init_pos);
00547
00548 READ_NEXT_CHAR (a_this, &cur_char);
00549
00550 if (cur_char != '\\') {
00551 status = CR_PARSING_ERROR;
00552 goto error;
00553 }
00554 if (a_location) {
00555 cr_tknzr_get_parsing_location
00556 (a_this, a_location) ;
00557 }
00558 PEEK_NEXT_CHAR (a_this, &cur_char);
00559
00560 for (occur = 0, unicode = 0; ((cur_char >= '0' && cur_char <= '9')
00561 || (cur_char >= 'a' && cur_char <= 'f')
00562 || (cur_char >= 'A' && cur_char <= 'F'))
00563 && occur < 6; occur++) {
00564 gint cur_char_val = 0;
00565
00566 READ_NEXT_CHAR (a_this, &cur_char);
00567
00568 if ((cur_char >= '0' && cur_char <= '9')) {
00569 cur_char_val = (cur_char - '0');
00570 } else if ((cur_char >= 'a' && cur_char <= 'f')) {
00571 cur_char_val = 10 + (cur_char - 'a');
00572 } else if ((cur_char >= 'A' && cur_char <= 'F')) {
00573 cur_char_val = 10 + (cur_char - 'A');
00574 }
00575
00576 unicode = unicode * 16 + cur_char_val;
00577
00578 PEEK_NEXT_CHAR (a_this, &cur_char);
00579 }
00580
00581
00582 cr_tknzr_parse_w (a_this, &tmp_char_ptr1,
00583 &tmp_char_ptr2, NULL);
00584 *a_unicode = unicode;
00585 return CR_OK;
00586
00587 error:
00588
00589
00590
00591
00592 cr_tknzr_set_cur_pos (a_this, &init_pos);
00593
00594 return status;
00595 }
00596
00597
00598
00599
00600
00601
00602 static enum CRStatus
00603 cr_tknzr_parse_escape (CRTknzr * a_this, guint32 * a_esc_code,
00604 CRParsingLocation *a_location)
00605 {
00606 enum CRStatus status = CR_OK;
00607 guint32 cur_char = 0;
00608 CRInputPos init_pos;
00609 guchar next_chars[2];
00610
00611 g_return_val_if_fail (a_this && PRIVATE (a_this)
00612 && a_esc_code, CR_BAD_PARAM_ERROR);
00613
00614 RECORD_INITIAL_POS (a_this, &init_pos);
00615
00616 PEEK_BYTE (a_this, 1, &next_chars[0]);
00617 PEEK_BYTE (a_this, 2, &next_chars[1]);
00618
00619 if (next_chars[0] != '\\') {
00620 status = CR_PARSING_ERROR;
00621 goto error;
00622 }
00623
00624 if ((next_chars[1] >= '0' && next_chars[1] <= '9')
00625 || (next_chars[1] >= 'a' && next_chars[1] <= 'f')
00626 || (next_chars[1] >= 'A' && next_chars[1] <= 'F')) {
00627 status = cr_tknzr_parse_unicode_escape (a_this, a_esc_code,
00628 a_location);
00629 } else {
00630
00631 READ_NEXT_CHAR (a_this, &cur_char);
00632 if (a_location) {
00633 cr_tknzr_get_parsing_location (a_this,
00634 a_location) ;
00635 }
00636
00637 READ_NEXT_CHAR (a_this, &cur_char);
00638
00639 if (cur_char != ' ' && (cur_char < 200 || cur_char > 4177777)) {
00640 status = CR_PARSING_ERROR;
00641 goto error;
00642 }
00643 *a_esc_code = cur_char;
00644
00645 }
00646 if (status == CR_OK) {
00647 return CR_OK;
00648 }
00649 error:
00650 cr_tknzr_set_cur_pos (a_this, &init_pos);
00651 return status;
00652 }
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669 static enum CRStatus
00670 cr_tknzr_parse_string (CRTknzr * a_this, CRString ** a_str)
00671 {
00672 guint32 cur_char = 0,
00673 delim = 0;
00674 CRInputPos init_pos;
00675 enum CRStatus status = CR_OK;
00676 CRString *str = NULL;
00677
00678 g_return_val_if_fail (a_this && PRIVATE (a_this)
00679 && PRIVATE (a_this)->input
00680 && a_str, CR_BAD_PARAM_ERROR);
00681
00682 RECORD_INITIAL_POS (a_this, &init_pos);
00683 READ_NEXT_CHAR (a_this, &cur_char);
00684
00685 if (cur_char == '"')
00686 delim = '"';
00687 else if (cur_char == '\'')
00688 delim = '\'';
00689 else {
00690 status = CR_PARSING_ERROR;
00691 goto error;
00692 }
00693 str = cr_string_new ();
00694 if (str) {
00695 cr_tknzr_get_parsing_location
00696 (a_this, &str->location) ;
00697 }
00698 for (;;) {
00699 guchar next_chars[2] = { 0 };
00700
00701 PEEK_BYTE (a_this, 1, &next_chars[0]);
00702 PEEK_BYTE (a_this, 2, &next_chars[1]);
00703
00704 if (next_chars[0] == '\\') {
00705 guchar *tmp_char_ptr1 = NULL,
00706 *tmp_char_ptr2 = NULL;
00707 guint32 esc_code = 0;
00708
00709 if (next_chars[1] == '\'' || next_chars[1] == '"') {
00710 g_string_append_unichar (str->stryng,
00711 next_chars[1]);
00712 SKIP_BYTES (a_this, 2);
00713 status = CR_OK;
00714 } else {
00715 status = cr_tknzr_parse_escape
00716 (a_this, &esc_code, NULL);
00717
00718 if (status == CR_OK) {
00719 g_string_append_unichar
00720 (str->stryng,
00721 esc_code);
00722 }
00723 }
00724
00725 if (status != CR_OK) {
00726
00727
00728
00729
00730 READ_NEXT_CHAR (a_this, &cur_char);
00731
00732 status = cr_tknzr_parse_nl
00733 (a_this, &tmp_char_ptr1,
00734 &tmp_char_ptr2, NULL);
00735 }
00736
00737 CHECK_PARSING_STATUS (status, FALSE);
00738 } else if (strchr ("\t !#$%&", next_chars[0])
00739 || (next_chars[0] >= '(' && next_chars[0] <= '~')) {
00740 READ_NEXT_CHAR (a_this, &cur_char);
00741 g_string_append_unichar (str->stryng,
00742 cur_char);
00743 status = CR_OK;
00744 }
00745
00746 else if (cr_utils_is_nonascii (next_chars[0])) {
00747 READ_NEXT_CHAR (a_this, &cur_char);
00748 g_string_append_unichar (str->stryng, cur_char);
00749 } else if (next_chars[0] == delim) {
00750 READ_NEXT_CHAR (a_this, &cur_char);
00751 break;
00752 } else {
00753 status = CR_PARSING_ERROR;
00754 goto error;
00755 }
00756 }
00757
00758 if (status == CR_OK) {
00759 if (*a_str == NULL) {
00760 *a_str = str;
00761 str = NULL;
00762 } else {
00763 (*a_str)->stryng = g_string_append_len
00764 ((*a_str)->stryng,
00765 str->stryng->str,
00766 str->stryng->len);
00767 cr_string_destroy (str);
00768 }
00769 return CR_OK;
00770 }
00771
00772 error:
00773
00774 if (str) {
00775 cr_string_destroy (str) ;
00776 str = NULL;
00777 }
00778 cr_tknzr_set_cur_pos (a_this, &init_pos);
00779 return status;
00780 }
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795 static enum CRStatus
00796 cr_tknzr_parse_nmstart (CRTknzr * a_this,
00797 guint32 * a_char,
00798 CRParsingLocation *a_location)
00799 {
00800 CRInputPos init_pos;
00801 enum CRStatus status = CR_OK;
00802 guint32 cur_char = 0,
00803 next_char = 0;
00804
00805 g_return_val_if_fail (a_this && PRIVATE (a_this)
00806 && PRIVATE (a_this)->input
00807 && a_char, CR_BAD_PARAM_ERROR);
00808
00809 RECORD_INITIAL_POS (a_this, &init_pos);
00810
00811 PEEK_NEXT_CHAR (a_this, &next_char);
00812
00813 if (next_char == '\\') {
00814 status = cr_tknzr_parse_escape (a_this, a_char,
00815 a_location);
00816
00817 if (status != CR_OK)
00818 goto error;
00819
00820 } else if (cr_utils_is_nonascii (next_char) == TRUE
00821 || ((next_char >= 'a') && (next_char <= 'z'))
00822 || ((next_char >= 'A') && (next_char <= 'Z'))
00823 ) {
00824 READ_NEXT_CHAR (a_this, &cur_char);
00825 if (a_location) {
00826 cr_tknzr_get_parsing_location (a_this,
00827 a_location) ;
00828 }
00829 *a_char = cur_char;
00830 status = CR_OK;
00831 } else {
00832 status = CR_PARSING_ERROR;
00833 goto error;
00834 }
00835
00836 return CR_OK;
00837
00838 error:
00839 cr_tknzr_set_cur_pos (a_this, &init_pos);
00840
00841 return status;
00842
00843 }
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862 static enum CRStatus
00863 cr_tknzr_parse_nmchar (CRTknzr * a_this, guint32 * a_char,
00864 CRParsingLocation *a_location)
00865 {
00866 guint32 cur_char = 0,
00867 next_char = 0;
00868 enum CRStatus status = CR_OK;
00869 CRInputPos init_pos;
00870
00871 g_return_val_if_fail (a_this && PRIVATE (a_this) && a_char,
00872 CR_BAD_PARAM_ERROR);
00873
00874 RECORD_INITIAL_POS (a_this, &init_pos);
00875
00876 status = cr_input_peek_char (PRIVATE (a_this)->input,
00877 &next_char) ;
00878 if (status != CR_OK)
00879 goto error;
00880
00881 if (next_char == '\\') {
00882 status = cr_tknzr_parse_escape (a_this, a_char,
00883 a_location);
00884
00885 if (status != CR_OK)
00886 goto error;
00887
00888 } else if (cr_utils_is_nonascii (next_char) == TRUE
00889 || ((next_char >= 'a') && (next_char <= 'z'))
00890 || ((next_char >= 'A') && (next_char <= 'Z'))
00891 || ((next_char >= '0') && (next_char <= '9'))
00892 || (next_char == '-')
00893 || (next_char == '_')
00894 ) {
00895 READ_NEXT_CHAR (a_this, &cur_char);
00896 *a_char = cur_char;
00897 status = CR_OK;
00898 if (a_location) {
00899 cr_tknzr_get_parsing_location
00900 (a_this, a_location) ;
00901 }
00902 } else {
00903 status = CR_PARSING_ERROR;
00904 goto error;
00905 }
00906 return CR_OK;
00907
00908 error:
00909 cr_tknzr_set_cur_pos (a_this, &init_pos);
00910 return status;
00911 }
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929 static enum CRStatus
00930 cr_tknzr_parse_ident (CRTknzr * a_this, CRString ** a_str)
00931 {
00932 guint32 tmp_char = 0;
00933 CRString *stringue = NULL ;
00934 CRInputPos init_pos;
00935 enum CRStatus status = CR_OK;
00936 gboolean location_is_set = FALSE ;
00937
00938 g_return_val_if_fail (a_this && PRIVATE (a_this)
00939 && PRIVATE (a_this)->input
00940 && a_str, CR_BAD_PARAM_ERROR);
00941
00942 RECORD_INITIAL_POS (a_this, &init_pos);
00943 PEEK_NEXT_CHAR (a_this, &tmp_char) ;
00944 stringue = cr_string_new () ;
00945 g_return_val_if_fail (stringue,
00946 CR_OUT_OF_MEMORY_ERROR) ;
00947
00948 if (tmp_char == '-') {
00949 READ_NEXT_CHAR (a_this, &tmp_char) ;
00950 cr_tknzr_get_parsing_location
00951 (a_this, &stringue->location) ;
00952 location_is_set = TRUE ;
00953 g_string_append_unichar (stringue->stryng,
00954 tmp_char) ;
00955 }
00956 status = cr_tknzr_parse_nmstart (a_this, &tmp_char, NULL);
00957 if (status != CR_OK) {
00958 status = CR_PARSING_ERROR;
00959 goto end ;
00960 }
00961 if (location_is_set == FALSE) {
00962 cr_tknzr_get_parsing_location
00963 (a_this, &stringue->location) ;
00964 location_is_set = TRUE ;
00965 }
00966 g_string_append_unichar (stringue->stryng, tmp_char);
00967 for (;;) {
00968 status = cr_tknzr_parse_nmchar (a_this,
00969 &tmp_char,
00970 NULL);
00971 if (status != CR_OK) {
00972 status = CR_OK ;
00973 break;
00974 }
00975 g_string_append_unichar (stringue->stryng, tmp_char);
00976 }
00977 if (status == CR_OK) {
00978 if (!*a_str) {
00979 *a_str = stringue ;
00980
00981 } else {
00982 g_string_append_len ((*a_str)->stryng,
00983 stringue->stryng->str,
00984 stringue->stryng->len) ;
00985 cr_string_destroy (stringue) ;
00986 }
00987 stringue = NULL ;
00988 }
00989
00990 error:
00991 end:
00992 if (stringue) {
00993 cr_string_destroy (stringue) ;
00994 stringue = NULL ;
00995 }
00996 if (status != CR_OK ) {
00997 cr_tknzr_set_cur_pos (a_this, &init_pos) ;
00998 }
00999 return status ;
01000 }
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016 static enum CRStatus
01017 cr_tknzr_parse_name (CRTknzr * a_this,
01018 CRString ** a_str)
01019 {
01020 guint32 tmp_char = 0;
01021 CRInputPos init_pos;
01022 enum CRStatus status = CR_OK;
01023 gboolean str_needs_free = FALSE,
01024 is_first_nmchar=TRUE ;
01025 glong i = 0;
01026 CRParsingLocation loc = {0} ;
01027
01028 g_return_val_if_fail (a_this && PRIVATE (a_this)
01029 && PRIVATE (a_this)->input
01030 && a_str,
01031 CR_BAD_PARAM_ERROR) ;
01032
01033 RECORD_INITIAL_POS (a_this, &init_pos);
01034
01035 if (*a_str == NULL) {
01036 *a_str = cr_string_new ();
01037 str_needs_free = TRUE;
01038 }
01039 for (i = 0;; i++) {
01040 if (is_first_nmchar == TRUE) {
01041 status = cr_tknzr_parse_nmchar
01042 (a_this, &tmp_char,
01043 &loc) ;
01044 is_first_nmchar = FALSE ;
01045 } else {
01046 status = cr_tknzr_parse_nmchar
01047 (a_this, &tmp_char, NULL) ;
01048 }
01049 if (status != CR_OK)
01050 break;
01051 g_string_append_unichar ((*a_str)->stryng,
01052 tmp_char);
01053 }
01054 if (i > 0) {
01055 cr_parsing_location_copy
01056 (&(*a_str)->location, &loc) ;
01057 return CR_OK;
01058 }
01059 if (str_needs_free == TRUE && *a_str) {
01060 cr_string_destroy (*a_str);
01061 *a_str = NULL;
01062 }
01063 cr_tknzr_set_cur_pos (a_this, &init_pos);
01064 return CR_PARSING_ERROR;
01065 }
01066
01067
01068
01069
01070
01071 static enum CRStatus
01072 cr_tknzr_parse_hash (CRTknzr * a_this, CRString ** a_str)
01073 {
01074 guint32 cur_char = 0;
01075 CRInputPos init_pos;
01076 enum CRStatus status = CR_OK;
01077 gboolean str_needs_free = FALSE;
01078 CRParsingLocation loc = {0} ;
01079
01080 g_return_val_if_fail (a_this && PRIVATE (a_this)
01081 && PRIVATE (a_this)->input,
01082 CR_BAD_PARAM_ERROR);
01083
01084 RECORD_INITIAL_POS (a_this, &init_pos);
01085 READ_NEXT_CHAR (a_this, &cur_char);
01086 if (cur_char != '#') {
01087 status = CR_PARSING_ERROR;
01088 goto error;
01089 }
01090 if (*a_str == NULL) {
01091 *a_str = cr_string_new ();
01092 str_needs_free = TRUE;
01093 }
01094 cr_tknzr_get_parsing_location (a_this,
01095 &loc) ;
01096 status = cr_tknzr_parse_name (a_this, a_str);
01097 cr_parsing_location_copy (&(*a_str)->location, &loc) ;
01098 if (status != CR_OK) {
01099 goto error;
01100 }
01101 return CR_OK;
01102
01103 error:
01104 if (str_needs_free == TRUE && *a_str) {
01105 cr_string_destroy (*a_str);
01106 *a_str = NULL;
01107 }
01108
01109 cr_tknzr_set_cur_pos (a_this, &init_pos);
01110 return status;
01111 }
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122 static enum CRStatus
01123 cr_tknzr_parse_uri (CRTknzr * a_this,
01124 CRString ** a_str)
01125 {
01126 guint32 cur_char = 0;
01127 CRInputPos init_pos;
01128 enum CRStatus status = CR_PARSING_ERROR;
01129 guchar tab[4] = { 0 }, *tmp_ptr1 = NULL, *tmp_ptr2 = NULL;
01130 CRString *str = NULL;
01131 CRParsingLocation location = {0} ;
01132
01133 g_return_val_if_fail (a_this
01134 && PRIVATE (a_this)
01135 && PRIVATE (a_this)->input
01136 && a_str,
01137 CR_BAD_PARAM_ERROR);
01138
01139 RECORD_INITIAL_POS (a_this, &init_pos);
01140
01141 PEEK_BYTE (a_this, 1, &tab[0]);
01142 PEEK_BYTE (a_this, 2, &tab[1]);
01143 PEEK_BYTE (a_this, 3, &tab[2]);
01144 PEEK_BYTE (a_this, 4, &tab[3]);
01145
01146 if (tab[0] != 'u' || tab[1] != 'r' || tab[2] != 'l' || tab[3] != '(') {
01147 status = CR_PARSING_ERROR;
01148 goto error;
01149 }
01150
01151
01152
01153
01154
01155
01156 SKIP_CHARS (a_this, 1);
01157 cr_tknzr_get_parsing_location (a_this, &location) ;
01158 SKIP_CHARS (a_this, 3);
01159 cr_tknzr_try_to_skip_spaces (a_this);
01160 status = cr_tknzr_parse_string (a_this, a_str);
01161
01162 if (status == CR_OK) {
01163 guint32 next_char = 0;
01164 status = cr_tknzr_parse_w (a_this, &tmp_ptr1,
01165 &tmp_ptr2, NULL);
01166 cr_tknzr_try_to_skip_spaces (a_this);
01167 PEEK_NEXT_CHAR (a_this, &next_char);
01168 if (next_char == ')') {
01169 READ_NEXT_CHAR (a_this, &cur_char);
01170 status = CR_OK;
01171 } else {
01172 status = CR_PARSING_ERROR;
01173 }
01174 }
01175 if (status != CR_OK) {
01176 str = cr_string_new ();
01177 for (;;) {
01178 guint32 next_char = 0;
01179 PEEK_NEXT_CHAR (a_this, &next_char);
01180 if (strchr ("!#$%&", next_char)
01181 || (next_char >= '*' && next_char <= '~')
01182 || (cr_utils_is_nonascii (next_char) == TRUE)) {
01183 READ_NEXT_CHAR (a_this, &cur_char);
01184 g_string_append_unichar
01185 (str->stryng, cur_char);
01186 status = CR_OK;
01187 } else {
01188 guint32 esc_code = 0;
01189 status = cr_tknzr_parse_escape
01190 (a_this, &esc_code, NULL);
01191 if (status == CR_OK) {
01192 g_string_append_unichar
01193 (str->stryng,
01194 esc_code);
01195 } else {
01196 status = CR_OK;
01197 break;
01198 }
01199 }
01200 }
01201 cr_tknzr_try_to_skip_spaces (a_this);
01202 READ_NEXT_CHAR (a_this, &cur_char);
01203 if (cur_char == ')') {
01204 status = CR_OK;
01205 } else {
01206 status = CR_PARSING_ERROR;
01207 goto error;
01208 }
01209 if (str) {
01210 if (*a_str == NULL) {
01211 *a_str = str;
01212 str = NULL;
01213 } else {
01214 g_string_append_len
01215 ((*a_str)->stryng,
01216 str->stryng->str,
01217 str->stryng->len);
01218 cr_string_destroy (str);
01219 }
01220 }
01221 }
01222
01223 cr_parsing_location_copy
01224 (&(*a_str)->location,
01225 &location) ;
01226 return CR_OK ;
01227 error:
01228 if (str) {
01229 cr_string_destroy (str);
01230 str = NULL;
01231 }
01232 cr_tknzr_set_cur_pos (a_this, &init_pos);
01233 return status;
01234 }
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244 static enum CRStatus
01245 cr_tknzr_parse_rgb (CRTknzr * a_this, CRRgb ** a_rgb)
01246 {
01247 enum CRStatus status = CR_OK;
01248 CRInputPos init_pos;
01249 CRNum *num = NULL;
01250 guchar next_bytes[3] = { 0 }, cur_byte = 0;
01251 glong red = 0,
01252 green = 0,
01253 blue = 0,
01254 i = 0;
01255 gboolean is_percentage = FALSE;
01256 CRParsingLocation location = {0} ;
01257
01258 g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
01259
01260 RECORD_INITIAL_POS (a_this, &init_pos);
01261
01262 PEEK_BYTE (a_this, 1, &next_bytes[0]);
01263 PEEK_BYTE (a_this, 2, &next_bytes[1]);
01264 PEEK_BYTE (a_this, 3, &next_bytes[2]);
01265
01266 if (((next_bytes[0] == 'r') || (next_bytes[0] == 'R'))
01267 && ((next_bytes[1] == 'g') || (next_bytes[1] == 'G'))
01268 && ((next_bytes[2] == 'b') || (next_bytes[2] == 'B'))) {
01269 SKIP_CHARS (a_this, 1);
01270 cr_tknzr_get_parsing_location (a_this, &location) ;
01271 SKIP_CHARS (a_this, 2);
01272 } else {
01273 status = CR_PARSING_ERROR;
01274 goto error;
01275 }
01276 READ_NEXT_BYTE (a_this, &cur_byte);
01277 ENSURE_PARSING_COND (cur_byte == '(');
01278
01279 cr_tknzr_try_to_skip_spaces (a_this);
01280 status = cr_tknzr_parse_num (a_this, &num);
01281 ENSURE_PARSING_COND ((status == CR_OK) && (num != NULL));
01282
01283 red = num->val;
01284 cr_num_destroy (num);
01285 num = NULL;
01286
01287 PEEK_BYTE (a_this, 1, &next_bytes[0]);
01288 if (next_bytes[0] == '%') {
01289 SKIP_CHARS (a_this, 1);
01290 is_percentage = TRUE;
01291 }
01292 cr_tknzr_try_to_skip_spaces (a_this);
01293
01294 for (i = 0; i < 2; i++) {
01295 READ_NEXT_BYTE (a_this, &cur_byte);
01296 ENSURE_PARSING_COND (cur_byte == ',');
01297
01298 cr_tknzr_try_to_skip_spaces (a_this);
01299 status = cr_tknzr_parse_num (a_this, &num);
01300 ENSURE_PARSING_COND ((status == CR_OK) && (num != NULL));
01301
01302 PEEK_BYTE (a_this, 1, &next_bytes[0]);
01303 if (next_bytes[0] == '%') {
01304 SKIP_CHARS (a_this, 1);
01305 is_percentage = 1;
01306 }
01307
01308 if (i == 0) {
01309 green = num->val;
01310 } else if (i == 1) {
01311 blue = num->val;
01312 }
01313
01314 if (num) {
01315 cr_num_destroy (num);
01316 num = NULL;
01317 }
01318 cr_tknzr_try_to_skip_spaces (a_this);
01319 }
01320
01321 READ_NEXT_BYTE (a_this, &cur_byte);
01322 if (*a_rgb == NULL) {
01323 *a_rgb = cr_rgb_new_with_vals (red, green, blue,
01324 is_percentage);
01325
01326 if (*a_rgb == NULL) {
01327 status = CR_ERROR;
01328 goto error;
01329 }
01330 status = CR_OK;
01331 } else {
01332 (*a_rgb)->red = red;
01333 (*a_rgb)->green = green;
01334 (*a_rgb)->blue = blue;
01335 (*a_rgb)->is_percentage = is_percentage;
01336
01337 status = CR_OK;
01338 }
01339
01340 if (status == CR_OK) {
01341 if (a_rgb && *a_rgb) {
01342 cr_parsing_location_copy
01343 (&(*a_rgb)->location,
01344 &location) ;
01345 }
01346 return CR_OK;
01347 }
01348
01349 error:
01350 if (num) {
01351 cr_num_destroy (num);
01352 num = NULL;
01353 }
01354
01355 cr_tknzr_set_cur_pos (a_this, &init_pos);
01356 return CR_OK;
01357 }
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374 static enum CRStatus
01375 cr_tknzr_parse_atkeyword (CRTknzr * a_this,
01376 CRString ** a_str)
01377 {
01378 guint32 cur_char = 0;
01379 CRInputPos init_pos;
01380 gboolean str_needs_free = FALSE;
01381 enum CRStatus status = CR_OK;
01382
01383 g_return_val_if_fail (a_this && PRIVATE (a_this)
01384 && PRIVATE (a_this)->input
01385 && a_str, CR_BAD_PARAM_ERROR);
01386
01387 RECORD_INITIAL_POS (a_this, &init_pos);
01388
01389 READ_NEXT_CHAR (a_this, &cur_char);
01390
01391 if (cur_char != '@') {
01392 status = CR_PARSING_ERROR;
01393 goto error;
01394 }
01395
01396 if (*a_str == NULL) {
01397 *a_str = cr_string_new ();
01398 str_needs_free = TRUE;
01399 }
01400 status = cr_tknzr_parse_ident (a_this, a_str);
01401 if (status != CR_OK) {
01402 goto error;
01403 }
01404 return CR_OK;
01405 error:
01406
01407 if (str_needs_free == TRUE && *a_str) {
01408 cr_string_destroy (*a_str);
01409 *a_str = NULL;
01410 }
01411 cr_tknzr_set_cur_pos (a_this, &init_pos);
01412 return status;
01413 }
01414
01415 static enum CRStatus
01416 cr_tknzr_parse_important (CRTknzr * a_this,
01417 CRParsingLocation *a_location)
01418 {
01419 guint32 cur_char = 0;
01420 CRInputPos init_pos;
01421 enum CRStatus status = CR_OK;
01422
01423 g_return_val_if_fail (a_this && PRIVATE (a_this)
01424 && PRIVATE (a_this)->input,
01425 CR_BAD_PARAM_ERROR);
01426
01427 RECORD_INITIAL_POS (a_this, &init_pos);
01428 READ_NEXT_CHAR (a_this, &cur_char);
01429 ENSURE_PARSING_COND (cur_char == '!');
01430 if (a_location) {
01431 cr_tknzr_get_parsing_location (a_this,
01432 a_location) ;
01433 }
01434 cr_tknzr_try_to_skip_spaces (a_this);
01435
01436 if (BYTE (PRIVATE (a_this)->input, 1, NULL) == 'i'
01437 && BYTE (PRIVATE (a_this)->input, 2, NULL) == 'm'
01438 && BYTE (PRIVATE (a_this)->input, 3, NULL) == 'p'
01439 && BYTE (PRIVATE (a_this)->input, 4, NULL) == 'o'
01440 && BYTE (PRIVATE (a_this)->input, 5, NULL) == 'r'
01441 && BYTE (PRIVATE (a_this)->input, 6, NULL) == 't'
01442 && BYTE (PRIVATE (a_this)->input, 7, NULL) == 'a'
01443 && BYTE (PRIVATE (a_this)->input, 8, NULL) == 'n'
01444 && BYTE (PRIVATE (a_this)->input, 9, NULL) == 't') {
01445 SKIP_BYTES (a_this, 9);
01446 if (a_location) {
01447 cr_tknzr_get_parsing_location (a_this,
01448 a_location) ;
01449 }
01450 return CR_OK;
01451 } else {
01452 status = CR_PARSING_ERROR;
01453 }
01454
01455 error:
01456 cr_tknzr_set_cur_pos (a_this, &init_pos);
01457
01458 return status;
01459 }
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469 static enum CRStatus
01470 cr_tknzr_parse_num (CRTknzr * a_this,
01471 CRNum ** a_num)
01472 {
01473 enum CRStatus status = CR_PARSING_ERROR;
01474 enum CRNumType val_type = NUM_GENERIC;
01475 gboolean parsing_dec,
01476 parsed;
01477
01478 guint32 cur_char = 0,
01479 next_char = 0;
01480 gdouble numerator, denominator = 1;
01481 CRInputPos init_pos;
01482 CRParsingLocation location = {0} ;
01483
01484 g_return_val_if_fail (a_this && PRIVATE (a_this)
01485 && PRIVATE (a_this)->input,
01486 CR_BAD_PARAM_ERROR);
01487
01488 RECORD_INITIAL_POS (a_this, &init_pos);
01489 READ_NEXT_CHAR (a_this, &cur_char);
01490 if (IS_NUM (cur_char)) {
01491 numerator = (cur_char - '0');
01492 parsing_dec = FALSE;
01493 parsed = TRUE;
01494 } else if (cur_char == '.') {
01495 numerator = 0;
01496 parsing_dec = TRUE;
01497 parsed = FALSE;
01498 } else {
01499 status = CR_PARSING_ERROR;
01500 goto error;
01501 }
01502 cr_tknzr_get_parsing_location (a_this, &location) ;
01503
01504 for (;;) {
01505 status = cr_tknzr_peek_char (a_this, &next_char);
01506 if (status != CR_OK) {
01507 if (status == CR_END_OF_INPUT_ERROR)
01508 status = CR_OK;
01509 break;
01510 }
01511 if (next_char == '.') {
01512 if (parsing_dec) {
01513 status = CR_PARSING_ERROR;
01514 goto error;
01515 }
01516
01517 READ_NEXT_CHAR (a_this, &cur_char);
01518 parsing_dec = TRUE;
01519 parsed = FALSE;
01520
01521 } else if (IS_NUM (next_char)) {
01522 READ_NEXT_CHAR (a_this, &cur_char);
01523 parsed = TRUE;
01524
01525 numerator = numerator * 10 + (cur_char - '0');
01526 if (parsing_dec) {
01527 denominator *= 10;
01528 }
01529 } else {
01530 break;
01531 }
01532 }
01533
01534 if (!parsed) {
01535 status = CR_PARSING_ERROR;
01536 }
01537
01538
01539
01540
01541 if (status == CR_OK) {
01542 gdouble val = numerator / denominator;
01543 if (*a_num == NULL) {
01544 *a_num = cr_num_new_with_val (val, val_type);
01545
01546 if (*a_num == NULL) {
01547 status = CR_ERROR;
01548 goto error;
01549 }
01550 } else {
01551 (*a_num)->val = val;
01552 (*a_num)->type = val_type;
01553 }
01554 cr_parsing_location_copy (&(*a_num)->location,
01555 &location) ;
01556 return CR_OK;
01557 }
01558
01559 error:
01560
01561 cr_tknzr_set_cur_pos (a_this, &init_pos);
01562
01563 return status;
01564 }
01565
01566
01567
01568
01569
01570 CRTknzr *
01571 cr_tknzr_new (CRInput * a_input)
01572 {
01573 CRTknzr *result = NULL;
01574
01575 result = g_try_malloc (sizeof (CRTknzr));
01576
01577 if (result == NULL) {
01578 cr_utils_trace_info ("Out of memory");
01579 return NULL;
01580 }
01581
01582 memset (result, 0, sizeof (CRTknzr));
01583
01584 result->priv = g_try_malloc (sizeof (CRTknzrPriv));
01585
01586 if (result->priv == NULL) {
01587 cr_utils_trace_info ("Out of memory");
01588
01589 if (result) {
01590 g_free (result);
01591 result = NULL;
01592 }
01593
01594 return NULL;
01595 }
01596 memset (result->priv, 0, sizeof (CRTknzrPriv));
01597 if (a_input)
01598 cr_tknzr_set_input (result, a_input);
01599 return result;
01600 }
01601
01602 CRTknzr *
01603 cr_tknzr_new_from_buf (guchar * a_buf, gulong a_len,
01604 enum CREncoding a_enc,
01605 gboolean a_free_at_destroy)
01606 {
01607 CRTknzr *result = NULL;
01608 CRInput *input = NULL;
01609
01610 input = cr_input_new_from_buf (a_buf, a_len, a_enc,
01611 a_free_at_destroy);
01612
01613 g_return_val_if_fail (input != NULL, NULL);
01614
01615 result = cr_tknzr_new (input);
01616
01617 return result;
01618 }
01619
01620 CRTknzr *
01621 cr_tknzr_new_from_uri (const guchar * a_file_uri,
01622 enum CREncoding a_enc)
01623 {
01624 CRTknzr *result = NULL;
01625 CRInput *input = NULL;
01626
01627 input = cr_input_new_from_uri (a_file_uri, a_enc);
01628 g_return_val_if_fail (input != NULL, NULL);
01629
01630 result = cr_tknzr_new (input);
01631
01632 return result;
01633 }
01634
01635 void
01636 cr_tknzr_ref (CRTknzr * a_this)
01637 {
01638 g_return_if_fail (a_this && PRIVATE (a_this));
01639
01640 PRIVATE (a_this)->ref_count++;
01641 }
01642
01643 gboolean
01644 cr_tknzr_unref (CRTknzr * a_this)
01645 {
01646 g_return_val_if_fail (a_this && PRIVATE (a_this), FALSE);
01647
01648 if (PRIVATE (a_this)->ref_count > 0) {
01649 PRIVATE (a_this)->ref_count--;
01650 }
01651
01652 if (PRIVATE (a_this)->ref_count == 0) {
01653 cr_tknzr_destroy (a_this);
01654 return TRUE;
01655 }
01656
01657 return FALSE;
01658 }
01659
01660 enum CRStatus
01661 cr_tknzr_set_input (CRTknzr * a_this, CRInput * a_input)
01662 {
01663 g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
01664
01665 if (PRIVATE (a_this)->input) {
01666 cr_input_unref (PRIVATE (a_this)->input);
01667 }
01668
01669 PRIVATE (a_this)->input = a_input;
01670
01671 cr_input_ref (PRIVATE (a_this)->input);
01672
01673 return CR_OK;
01674 }
01675
01676 enum CRStatus
01677 cr_tknzr_get_input (CRTknzr * a_this, CRInput ** a_input)
01678 {
01679 g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
01680
01681 *a_input = PRIVATE (a_this)->input;
01682
01683 return CR_OK;
01684 }
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699 enum CRStatus
01700 cr_tknzr_read_byte (CRTknzr * a_this, guchar * a_byte)
01701 {
01702 g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
01703
01704 return cr_input_read_byte (PRIVATE (a_this)->input, a_byte);
01705
01706 }
01707
01708
01709
01710
01711
01712
01713
01714
01715 enum CRStatus
01716 cr_tknzr_read_char (CRTknzr * a_this, guint32 * a_char)
01717 {
01718 g_return_val_if_fail (a_this && PRIVATE (a_this)
01719 && PRIVATE (a_this)->input
01720 && a_char, CR_BAD_PARAM_ERROR);
01721
01722 if (PRIVATE (a_this)->token_cache) {
01723 cr_input_set_cur_pos (PRIVATE (a_this)->input,
01724 &PRIVATE (a_this)->prev_pos);
01725 cr_token_destroy (PRIVATE (a_this)->token_cache);
01726 PRIVATE (a_this)->token_cache = NULL;
01727 }
01728
01729 return cr_input_read_char (PRIVATE (a_this)->input, a_char);
01730 }
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740 enum CRStatus
01741 cr_tknzr_peek_char (CRTknzr * a_this, guint32 * a_char)
01742 {
01743 g_return_val_if_fail (a_this && PRIVATE (a_this)
01744 && PRIVATE (a_this)->input
01745 && a_char, CR_BAD_PARAM_ERROR);
01746
01747 if (PRIVATE (a_this)->token_cache) {
01748 cr_input_set_cur_pos (PRIVATE (a_this)->input,
01749 &PRIVATE (a_this)->prev_pos);
01750 cr_token_destroy (PRIVATE (a_this)->token_cache);
01751 PRIVATE (a_this)->token_cache = NULL;
01752 }
01753
01754 return cr_input_peek_char (PRIVATE (a_this)->input, a_char);
01755 }
01756
01757
01758
01759
01760
01761
01762
01763
01764
01765
01766 enum CRStatus
01767 cr_tknzr_peek_byte (CRTknzr * a_this, gulong a_offset, guchar * a_byte)
01768 {
01769 g_return_val_if_fail (a_this && PRIVATE (a_this)
01770 && PRIVATE (a_this)->input && a_byte,
01771 CR_BAD_PARAM_ERROR);
01772
01773 if (PRIVATE (a_this)->token_cache) {
01774 cr_input_set_cur_pos (PRIVATE (a_this)->input,
01775 &PRIVATE (a_this)->prev_pos);
01776 cr_token_destroy (PRIVATE (a_this)->token_cache);
01777 PRIVATE (a_this)->token_cache = NULL;
01778 }
01779
01780 return cr_input_peek_byte (PRIVATE (a_this)->input,
01781 CR_SEEK_CUR, a_offset, a_byte);
01782 }
01783
01784
01785
01786
01787
01788
01789
01790
01791
01792
01793
01794 guchar
01795 cr_tknzr_peek_byte2 (CRTknzr * a_this, gulong a_offset, gboolean * a_eof)
01796 {
01797 g_return_val_if_fail (a_this && PRIVATE (a_this)
01798 && PRIVATE (a_this)->input, 0);
01799
01800 return cr_input_peek_byte2 (PRIVATE (a_this)->input, a_offset, a_eof);
01801 }
01802
01803
01804
01805
01806
01807
01808
01809 glong
01810 cr_tknzr_get_nb_bytes_left (CRTknzr * a_this)
01811 {
01812 g_return_val_if_fail (a_this && PRIVATE (a_this)
01813 && PRIVATE (a_this)->input, CR_BAD_PARAM_ERROR);
01814
01815 if (PRIVATE (a_this)->token_cache) {
01816 cr_input_set_cur_pos (PRIVATE (a_this)->input,
01817 &PRIVATE (a_this)->prev_pos);
01818 cr_token_destroy (PRIVATE (a_this)->token_cache);
01819 PRIVATE (a_this)->token_cache = NULL;
01820 }
01821
01822 return cr_input_get_nb_bytes_left (PRIVATE (a_this)->input);
01823 }
01824
01825 enum CRStatus
01826 cr_tknzr_get_cur_pos (CRTknzr * a_this, CRInputPos * a_pos)
01827 {
01828 g_return_val_if_fail (a_this && PRIVATE (a_this)
01829 && PRIVATE (a_this)->input
01830 && a_pos, CR_BAD_PARAM_ERROR);
01831
01832 if (PRIVATE (a_this)->token_cache) {
01833 cr_input_set_cur_pos (PRIVATE (a_this)->input,
01834 &PRIVATE (a_this)->prev_pos);
01835 cr_token_destroy (PRIVATE (a_this)->token_cache);
01836 PRIVATE (a_this)->token_cache = NULL;
01837 }
01838
01839 return cr_input_get_cur_pos (PRIVATE (a_this)->input, a_pos);
01840 }
01841
01842 enum CRStatus
01843 cr_tknzr_get_parsing_location (CRTknzr *a_this,
01844 CRParsingLocation *a_loc)
01845 {
01846 g_return_val_if_fail (a_this
01847 && PRIVATE (a_this)
01848 && a_loc,
01849 CR_BAD_PARAM_ERROR) ;
01850
01851 return cr_input_get_parsing_location
01852 (PRIVATE (a_this)->input, a_loc) ;
01853 }
01854
01855 enum CRStatus
01856 cr_tknzr_get_cur_byte_addr (CRTknzr * a_this, guchar ** a_addr)
01857 {
01858 g_return_val_if_fail (a_this && PRIVATE (a_this)
01859 && PRIVATE (a_this)->input, CR_BAD_PARAM_ERROR);
01860 if (PRIVATE (a_this)->token_cache) {
01861 cr_input_set_cur_pos (PRIVATE (a_this)->input,
01862 &PRIVATE (a_this)->prev_pos);
01863 cr_token_destroy (PRIVATE (a_this)->token_cache);
01864 PRIVATE (a_this)->token_cache = NULL;
01865 }
01866
01867 return cr_input_get_cur_byte_addr (PRIVATE (a_this)->input, a_addr);
01868 }
01869
01870 enum CRStatus
01871 cr_tknzr_seek_index (CRTknzr * a_this, enum CRSeekPos a_origin, gint a_pos)
01872 {
01873 g_return_val_if_fail (a_this && PRIVATE (a_this)
01874 && PRIVATE (a_this)->input, CR_BAD_PARAM_ERROR);
01875
01876 if (PRIVATE (a_this)->token_cache) {
01877 cr_input_set_cur_pos (PRIVATE (a_this)->input,
01878 &PRIVATE (a_this)->prev_pos);
01879 cr_token_destroy (PRIVATE (a_this)->token_cache);
01880 PRIVATE (a_this)->token_cache = NULL;
01881 }
01882
01883 return cr_input_seek_index (PRIVATE (a_this)->input, a_origin, a_pos);
01884 }
01885
01886 enum CRStatus
01887 cr_tknzr_consume_chars (CRTknzr * a_this, guint32 a_char, glong * a_nb_char)
01888 {
01889 g_return_val_if_fail (a_this && PRIVATE (a_this)
01890 && PRIVATE (a_this)->input, CR_BAD_PARAM_ERROR);
01891
01892 if (PRIVATE (a_this)->token_cache) {
01893 cr_input_set_cur_pos (PRIVATE (a_this)->input,
01894 &PRIVATE (a_this)->prev_pos);
01895 cr_token_destroy (PRIVATE (a_this)->token_cache);
01896 PRIVATE (a_this)->token_cache = NULL;
01897 }
01898
01899 return cr_input_consume_chars (PRIVATE (a_this)->input,
01900 a_char, a_nb_char);
01901 }
01902
01903 enum CRStatus
01904 cr_tknzr_set_cur_pos (CRTknzr * a_this, CRInputPos * a_pos)
01905 {
01906 g_return_val_if_fail (a_this && PRIVATE (a_this)
01907 && PRIVATE (a_this)->input, CR_BAD_PARAM_ERROR);
01908
01909 if (PRIVATE (a_this)->token_cache) {
01910 cr_token_destroy (PRIVATE (a_this)->token_cache);
01911 PRIVATE (a_this)->token_cache = NULL;
01912 }
01913
01914 return cr_input_set_cur_pos (PRIVATE (a_this)->input, a_pos);
01915 }
01916
01917 enum CRStatus
01918 cr_tknzr_unget_token (CRTknzr * a_this, CRToken * a_token)
01919 {
01920 g_return_val_if_fail (a_this && PRIVATE (a_this)
01921 && PRIVATE (a_this)->token_cache == NULL,
01922 CR_BAD_PARAM_ERROR);
01923
01924 PRIVATE (a_this)->token_cache = a_token;
01925
01926 return CR_OK;
01927 }
01928
01929
01930
01931
01932
01933
01934
01935
01936
01937
01938
01939
01940 enum CRStatus
01941 cr_tknzr_get_next_token (CRTknzr * a_this, CRToken ** a_tk)
01942 {
01943 enum CRStatus status = CR_OK;
01944 CRToken *token = NULL;
01945 CRInputPos init_pos;
01946 guint32 next_char = 0;
01947 guchar next_bytes[4] = { 0 };
01948 gboolean reached_eof = FALSE;
01949 CRInput *input = NULL;
01950 CRString *str = NULL;
01951 CRRgb *rgb = NULL;
01952 CRParsingLocation location = {0} ;
01953
01954 g_return_val_if_fail (a_this && PRIVATE (a_this)
01955 && a_tk && *a_tk == NULL
01956 && PRIVATE (a_this)->input,
01957 CR_BAD_PARAM_ERROR);
01958
01959 if (PRIVATE (a_this)->token_cache) {
01960 *a_tk = PRIVATE (a_this)->token_cache;
01961 PRIVATE (a_this)->token_cache = NULL;
01962 return CR_OK;
01963 }
01964
01965 RECORD_INITIAL_POS (a_this, &init_pos);
01966
01967 status = cr_input_get_end_of_file
01968 (PRIVATE (a_this)->input, &reached_eof);
01969 ENSURE_PARSING_COND (status == CR_OK);
01970
01971 if (reached_eof == TRUE) {
01972 status = CR_END_OF_INPUT_ERROR;
01973 goto error;
01974 }
01975
01976 input = PRIVATE (a_this)->input;
01977
01978 PEEK_NEXT_CHAR (a_this, &next_char);
01979 token = cr_token_new ();
01980 ENSURE_PARSING_COND (token);
01981
01982 switch (next_char) {
01983 case '@':
01984 {
01985 if (BYTE (input, 2, NULL) == 'f'
01986 && BYTE (input, 3, NULL) == 'o'
01987 && BYTE (input, 4, NULL) == 'n'
01988 && BYTE (input, 5, NULL) == 't'
01989 && BYTE (input, 6, NULL) == '-'
01990 && BYTE (input, 7, NULL) == 'f'
01991 && BYTE (input, 8, NULL) == 'a'
01992 && BYTE (input, 9, NULL) == 'c'
01993 && BYTE (input, 10, NULL) == 'e') {
01994 SKIP_CHARS (a_this, 1);
01995 cr_tknzr_get_parsing_location
01996 (a_this, &location) ;
01997 SKIP_CHARS (a_this, 9);
01998 status = cr_token_set_font_face_sym (token);
01999 CHECK_PARSING_STATUS (status, TRUE);
02000 cr_parsing_location_copy (&token->location,
02001 &location) ;
02002 goto done;
02003 }
02004
02005 if (BYTE (input, 2, NULL) == 'c'
02006 && BYTE (input, 3, NULL) == 'h'
02007 && BYTE (input, 4, NULL) == 'a'
02008 && BYTE (input, 5, NULL) == 'r'
02009 && BYTE (input, 6, NULL) == 's'
02010 && BYTE (input, 7, NULL) == 'e'
02011 && BYTE (input, 8, NULL) == 't') {
02012 SKIP_CHARS (a_this, 1);
02013 cr_tknzr_get_parsing_location
02014 (a_this, &location) ;
02015 SKIP_CHARS (a_this, 7);
02016 status = cr_token_set_charset_sym (token);
02017 CHECK_PARSING_STATUS (status, TRUE);
02018 cr_parsing_location_copy (&token->location,
02019 &location) ;
02020 goto done;
02021 }
02022
02023 if (BYTE (input, 2, NULL) == 'i'
02024 && BYTE (input, 3, NULL) == 'm'
02025 && BYTE (input, 4, NULL) == 'p'
02026 && BYTE (input, 5, NULL) == 'o'
02027 && BYTE (input, 6, NULL) == 'r'
02028 && BYTE (input, 7, NULL) == 't') {
02029 SKIP_CHARS (a_this, 1);
02030 cr_tknzr_get_parsing_location
02031 (a_this, &location) ;
02032 SKIP_CHARS (a_this, 6);
02033 status = cr_token_set_import_sym (token);
02034 CHECK_PARSING_STATUS (status, TRUE);
02035 cr_parsing_location_copy (&token->location,
02036 &location) ;
02037 goto done;
02038 }
02039
02040 if (BYTE (input, 2, NULL) == 'm'
02041 && BYTE (input, 3, NULL) == 'e'
02042 && BYTE (input, 4, NULL) == 'd'
02043 && BYTE (input, 5, NULL) == 'i'
02044 && BYTE (input, 6, NULL) == 'a') {
02045 SKIP_CHARS (a_this, 1);
02046 cr_tknzr_get_parsing_location (a_this,
02047 &location) ;
02048 SKIP_CHARS (a_this, 5);
02049 status = cr_token_set_media_sym (token);
02050 CHECK_PARSING_STATUS (status, TRUE);
02051 cr_parsing_location_copy (&token->location,
02052 &location) ;
02053 goto done;
02054 }
02055
02056 if (BYTE (input, 2, NULL) == 'p'
02057 && BYTE (input, 3, NULL) == 'a'
02058 && BYTE (input, 4, NULL) == 'g'
02059 && BYTE (input, 5, NULL) == 'e') {
02060 SKIP_CHARS (a_this, 1);
02061 cr_tknzr_get_parsing_location (a_this,
02062 &location) ;
02063 SKIP_CHARS (a_this, 4);
02064 status = cr_token_set_page_sym (token);
02065 CHECK_PARSING_STATUS (status, TRUE);
02066 cr_parsing_location_copy (&token->location,
02067 &location) ;
02068 goto done;
02069 }
02070 status = cr_tknzr_parse_atkeyword (a_this, &str);
02071 if (status == CR_OK) {
02072 status = cr_token_set_atkeyword (token, str);
02073 CHECK_PARSING_STATUS (status, TRUE);
02074 if (str) {
02075 cr_parsing_location_copy (&token->location,
02076 &str->location) ;
02077 }
02078 goto done;
02079 }
02080 }
02081 break;
02082
02083 case 'u':
02084
02085 if (BYTE (input, 2, NULL) == 'r'
02086 && BYTE (input, 3, NULL) == 'l'
02087 && BYTE (input, 4, NULL) == '(') {
02088 CRString *str = NULL;
02089
02090 status = cr_tknzr_parse_uri (a_this, &str);
02091 if (status == CR_OK) {
02092 status = cr_token_set_uri (token, str);
02093 CHECK_PARSING_STATUS (status, TRUE);
02094 if (str) {
02095 cr_parsing_location_copy (&token->location,
02096 &str->location) ;
02097 }
02098 goto done;
02099 }
02100 }
02101 goto fallback;
02102 break;
02103
02104 case 'r':
02105 if (BYTE (input, 2, NULL) == 'g'
02106 && BYTE (input, 3, NULL) == 'b'
02107 && BYTE (input, 4, NULL) == '(') {
02108 status = cr_tknzr_parse_rgb (a_this, &rgb);
02109 if (status == CR_OK && rgb) {
02110 status = cr_token_set_rgb (token, rgb);
02111 CHECK_PARSING_STATUS (status, TRUE);
02112 if (rgb) {
02113 cr_parsing_location_copy (&token->location,
02114 &rgb->location) ;
02115 }
02116 rgb = NULL;
02117 goto done;
02118 }
02119
02120 }
02121 goto fallback;
02122 break;
02123
02124 case '<':
02125 if (BYTE (input, 2, NULL) == '!'
02126 && BYTE (input, 3, NULL) == '-'
02127 && BYTE (input, 4, NULL) == '-') {
02128 SKIP_CHARS (a_this, 1);
02129 cr_tknzr_get_parsing_location (a_this,
02130 &location) ;
02131 SKIP_CHARS (a_this, 3);
02132 status = cr_token_set_cdo (token);
02133 CHECK_PARSING_STATUS (status, TRUE);
02134 cr_parsing_location_copy (&token->location,
02135 &location) ;
02136 goto done;
02137 }
02138 break;
02139
02140 case '-':
02141 if (BYTE (input, 2, NULL) == '-'
02142 && BYTE (input, 3, NULL) == '>') {
02143 SKIP_CHARS (a_this, 1);
02144 cr_tknzr_get_parsing_location (a_this,
02145 &location) ;
02146 SKIP_CHARS (a_this, 2);
02147 status = cr_token_set_cdc (token);
02148 CHECK_PARSING_STATUS (status, TRUE);
02149 cr_parsing_location_copy (&token->location,
02150 &location) ;
02151 goto done;
02152 } else {
02153 status = cr_tknzr_parse_ident
02154 (a_this, &str);
02155 if (status == CR_OK) {
02156 cr_token_set_ident
02157 (token, str);
02158 if (str) {
02159 cr_parsing_location_copy (&token->location,
02160 &str->location) ;
02161 }
02162 goto done;
02163 }
02164 }
02165 break;
02166
02167 case '~':
02168 if (BYTE (input, 2, NULL) == '=') {
02169 SKIP_CHARS (a_this, 1);
02170 cr_tknzr_get_parsing_location (a_this,
02171 &location) ;
02172 SKIP_CHARS (a_this, 1);
02173 status = cr_token_set_includes (token);
02174 CHECK_PARSING_STATUS (status, TRUE);
02175 cr_parsing_location_copy (&token->location,
02176 &location) ;
02177 goto done;
02178 }
02179 break;
02180
02181 case '|':
02182 if (BYTE (input, 2, NULL) == '=') {
02183 SKIP_CHARS (a_this, 1);
02184 cr_tknzr_get_parsing_location (a_this,
02185 &location) ;
02186 SKIP_CHARS (a_this, 1);
02187 status = cr_token_set_dashmatch (token);
02188 CHECK_PARSING_STATUS (status, TRUE);
02189 cr_parsing_location_copy (&token->location,
02190 &location) ;
02191 goto done;
02192 }
02193 break;
02194
02195 case '/':
02196 if (BYTE (input, 2, NULL) == '*') {
02197 status = cr_tknzr_parse_comment (a_this, &str);
02198
02199 if (status == CR_OK) {
02200 status = cr_token_set_comment (token, str);
02201 str = NULL;
02202 CHECK_PARSING_STATUS (status, TRUE);
02203 if (str) {
02204 cr_parsing_location_copy (&token->location,
02205 &str->location) ;
02206 }
02207 goto done;
02208 }
02209 }
02210 break ;
02211
02212 case ';':
02213 SKIP_CHARS (a_this, 1);
02214 cr_tknzr_get_parsing_location (a_this,
02215 &location) ;
02216 status = cr_token_set_semicolon (token);
02217 CHECK_PARSING_STATUS (status, TRUE);
02218 cr_parsing_location_copy (&token->location,
02219 &location) ;
02220 goto done;
02221
02222 case '{':
02223 SKIP_CHARS (a_this, 1);
02224 cr_tknzr_get_parsing_location (a_this,
02225 &location) ;
02226 status = cr_token_set_cbo (token);
02227 CHECK_PARSING_STATUS (status, TRUE);
02228 cr_tknzr_get_parsing_location (a_this,
02229 &location) ;
02230 goto done;
02231
02232 case '}':
02233 SKIP_CHARS (a_this, 1);
02234 cr_tknzr_get_parsing_location (a_this,
02235 &location) ;
02236 status = cr_token_set_cbc (token);
02237 CHECK_PARSING_STATUS (status, TRUE);
02238 cr_parsing_location_copy (&token->location,
02239 &location) ;
02240 goto done;
02241
02242 case '(':
02243 SKIP_CHARS (a_this, 1);
02244 cr_tknzr_get_parsing_location (a_this,
02245 &location) ;
02246 status = cr_token_set_po (token);
02247 CHECK_PARSING_STATUS (status, TRUE);
02248 cr_parsing_location_copy (&token->location,
02249 &location) ;
02250 goto done;
02251
02252 case ')':
02253 SKIP_CHARS (a_this, 1);
02254 cr_tknzr_get_parsing_location (a_this,
02255 &location) ;
02256 status = cr_token_set_pc (token);
02257 CHECK_PARSING_STATUS (status, TRUE);
02258 cr_parsing_location_copy (&token->location,
02259 &location) ;
02260 goto done;
02261
02262 case '[':
02263 SKIP_CHARS (a_this, 1);
02264 cr_tknzr_get_parsing_location (a_this,
02265 &location) ;
02266 status = cr_token_set_bo (token);
02267 CHECK_PARSING_STATUS (status, TRUE);
02268 cr_parsing_location_copy (&token->location,
02269 &location) ;
02270 goto done;
02271
02272 case ']':
02273 SKIP_CHARS (a_this, 1);
02274 cr_tknzr_get_parsing_location (a_this,
02275 &location) ;
02276 status = cr_token_set_bc (token);
02277 CHECK_PARSING_STATUS (status, TRUE);
02278 cr_parsing_location_copy (&token->location,
02279 &location) ;
02280 goto done;
02281
02282 case ' ':
02283 case '\t':
02284 case '\n':
02285 case '\f':
02286 case '\r':
02287 {
02288 guchar *start = NULL,
02289 *end = NULL;
02290
02291 status = cr_tknzr_parse_w (a_this, &start,
02292 &end, &location);
02293 if (status == CR_OK) {
02294 status = cr_token_set_s (token);
02295 CHECK_PARSING_STATUS (status, TRUE);
02296 cr_tknzr_get_parsing_location (a_this,
02297 &location) ;
02298 goto done;
02299 }
02300 }
02301 break;
02302
02303 case '#':
02304 {
02305 status = cr_tknzr_parse_hash (a_this, &str);
02306 if (status == CR_OK && str) {
02307 status = cr_token_set_hash (token, str);
02308 CHECK_PARSING_STATUS (status, TRUE);
02309 if (str) {
02310 cr_parsing_location_copy (&token->location,
02311 &str->location) ;
02312 }
02313 str = NULL;
02314 goto done;
02315 }
02316 }
02317 break;
02318
02319 case '\'':
02320 case '"':
02321 status = cr_tknzr_parse_string (a_this, &str);
02322 if (status == CR_OK && str) {
02323 status = cr_token_set_string (token, str);
02324 CHECK_PARSING_STATUS (status, TRUE);
02325 if (str) {
02326 cr_parsing_location_copy (&token->location,
02327 &str->location) ;
02328 }
02329 str = NULL;
02330 goto done;
02331 }
02332 break;
02333
02334 case '!':
02335 status = cr_tknzr_parse_important (a_this, &location);
02336 if (status == CR_OK) {
02337 status = cr_token_set_important_sym (token);
02338 CHECK_PARSING_STATUS (status, TRUE);
02339 cr_parsing_location_copy (&token->location,
02340 &location) ;
02341 goto done;
02342 }
02343 break;
02344
02345 case '0':
02346 case '1':
02347 case '2':
02348 case '3':
02349 case '4':
02350 case '5':
02351 case '6':
02352 case '7':
02353 case '8':
02354 case '9':
02355 case '.':
02356 {
02357 CRNum *num = NULL;
02358
02359 status = cr_tknzr_parse_num (a_this, &num);
02360 if (status == CR_OK && num) {
02361 next_bytes[0] = BYTE (input, 1, NULL);
02362 next_bytes[1] = BYTE (input, 2, NULL);
02363 next_bytes[2] = BYTE (input, 3, NULL);
02364 next_bytes[3] = BYTE (input, 3, NULL);
02365
02366 if (next_bytes[0] == 'e'
02367 && next_bytes[1] == 'm') {
02368 num->type = NUM_LENGTH_EM;
02369 status = cr_token_set_ems (token,
02370 num);
02371 num = NULL;
02372 SKIP_CHARS (a_this, 2);
02373 } else if (next_bytes[0] == 'e'
02374 && next_bytes[1] == 'x') {
02375 num->type = NUM_LENGTH_EX;
02376 status = cr_token_set_exs (token,
02377 num);
02378 num = NULL;
02379 SKIP_CHARS (a_this, 2);
02380 } else if (next_bytes[0] == 'p'
02381 && next_bytes[1] == 'x') {
02382 num->type = NUM_LENGTH_PX;
02383 status = cr_token_set_length
02384 (token, num, LENGTH_PX_ET);
02385 num = NULL;
02386 SKIP_CHARS (a_this, 2);
02387 } else if (next_bytes[0] == 'c'
02388 && next_bytes[1] == 'm') {
02389 num->type = NUM_LENGTH_CM;
02390 status = cr_token_set_length
02391 (token, num, LENGTH_CM_ET);
02392 num = NULL;
02393 SKIP_CHARS (a_this, 2);
02394 } else if (next_bytes[0] == 'm'
02395 && next_bytes[1] == 'm') {
02396 num->type = NUM_LENGTH_MM;
02397 status = cr_token_set_length
02398 (token, num, LENGTH_MM_ET);
02399 num = NULL;
02400 SKIP_CHARS (a_this, 2);
02401 } else if (next_bytes[0] == 'i'
02402 && next_bytes[1] == 'n') {
02403 num->type = NUM_LENGTH_IN;
02404 status = cr_token_set_length
02405 (token, num, LENGTH_IN_ET);
02406 num = NULL;
02407 SKIP_CHARS (a_this, 2);
02408 } else if (next_bytes[0] == 'p'
02409 && next_bytes[1] == 't') {
02410 num->type = NUM_LENGTH_PT;
02411 status = cr_token_set_length
02412 (token, num, LENGTH_PT_ET);
02413 num = NULL;
02414 SKIP_CHARS (a_this, 2);
02415 } else if (next_bytes[0] == 'p'
02416 && next_bytes[1] == 'c') {
02417 num->type = NUM_LENGTH_PC;
02418 status = cr_token_set_length
02419 (token, num, LENGTH_PC_ET);
02420 num = NULL;
02421 SKIP_CHARS (a_this, 2);
02422 } else if (next_bytes[0] == 'd'
02423 && next_bytes[1] == 'e'
02424 && next_bytes[2] == 'g') {
02425 num->type = NUM_ANGLE_DEG;
02426 status = cr_token_set_angle
02427 (token, num, ANGLE_DEG_ET);
02428 num = NULL;
02429 SKIP_CHARS (a_this, 3);
02430 } else if (next_bytes[0] == 'r'
02431 && next_bytes[1] == 'a'
02432 && next_bytes[2] == 'd') {
02433 num->type = NUM_ANGLE_RAD;
02434 status = cr_token_set_angle
02435 (token, num, ANGLE_RAD_ET);
02436 num = NULL;
02437 SKIP_CHARS (a_this, 3);
02438 } else if (next_bytes[0] == 'g'
02439 && next_bytes[1] == 'r'
02440 && next_bytes[2] == 'a'
02441 && next_bytes[3] == 'd') {
02442 num->type = NUM_ANGLE_GRAD;
02443 status = cr_token_set_angle
02444 (token, num, ANGLE_GRAD_ET);
02445 num = NULL;
02446 SKIP_CHARS (a_this, 4);
02447 } else if (next_bytes[0] == 'm'
02448 && next_bytes[1] == 's') {
02449 num->type = NUM_TIME_MS;
02450 status = cr_token_set_time
02451 (token, num, TIME_MS_ET);
02452 num = NULL;
02453 SKIP_CHARS (a_this, 2);
02454 } else if (next_bytes[0] == 's') {
02455 num->type = NUM_TIME_S;
02456 status = cr_token_set_time
02457 (token, num, TIME_S_ET);
02458 num = NULL;
02459 SKIP_CHARS (a_this, 1);
02460 } else if (next_bytes[0] == 'H'
02461 && next_bytes[1] == 'z') {
02462 num->type = NUM_FREQ_HZ;
02463 status = cr_token_set_freq
02464 (token, num, FREQ_HZ_ET);
02465 num = NULL;
02466 SKIP_CHARS (a_this, 2);
02467 } else if (next_bytes[0] == 'k'
02468 && next_bytes[1] == 'H'
02469 && next_bytes[2] == 'z') {
02470 num->type = NUM_FREQ_KHZ;
02471 status = cr_token_set_freq
02472 (token, num, FREQ_KHZ_ET);
02473 num = NULL;
02474 SKIP_CHARS (a_this, 3);
02475 } else if (next_bytes[0] == '%') {
02476 num->type = NUM_PERCENTAGE;
02477 status = cr_token_set_percentage
02478 (token, num);
02479 num = NULL;
02480 SKIP_CHARS (a_this, 1);
02481 } else {
02482 status = cr_tknzr_parse_ident (a_this,
02483 &str);
02484 if (status == CR_OK && str) {
02485 num->type = NUM_UNKNOWN_TYPE;
02486 status = cr_token_set_dimen
02487 (token, num, str);
02488 num = NULL;
02489 CHECK_PARSING_STATUS (status,
02490 TRUE);
02491 str = NULL;
02492 } else {
02493 status = cr_token_set_number
02494 (token, num);
02495 num = NULL;
02496 CHECK_PARSING_STATUS (status, CR_OK);
02497 str = NULL;
02498 }
02499 }
02500 if (token && token->u.num) {
02501 cr_parsing_location_copy (&token->location,
02502 &token->u.num->location) ;
02503 } else {
02504 status = CR_ERROR ;
02505 }
02506 goto done ;
02507 }
02508 }
02509 break;
02510
02511 default:
02512 fallback:
02513
02514
02515 if (next_char == '\\'
02516 || (cr_utils_is_nonascii (next_bytes[0]) == TRUE)
02517 || ((next_char >= 'a') && (next_char <= 'z'))
02518 || ((next_char >= 'A') && (next_char <= 'Z'))) {
02519 status = cr_tknzr_parse_ident (a_this, &str);
02520 if (status == CR_OK && str) {
02521 guint32 next_c = 0;
02522
02523 status = cr_input_peek_char
02524 (PRIVATE (a_this)->input, &next_c);
02525
02526 if (status == CR_OK && next_c == '(') {
02527
02528 SKIP_CHARS (a_this, 1);
02529 status = cr_token_set_function
02530 (token, str);
02531 CHECK_PARSING_STATUS (status, TRUE);
02532
02533
02534
02535 if (str) {
02536 cr_parsing_location_copy (&token->location,
02537 &str->location) ;
02538 }
02539 str = NULL;
02540 } else {
02541 status = cr_token_set_ident (token,
02542 str);
02543 CHECK_PARSING_STATUS (status, TRUE);
02544 if (str) {
02545 cr_parsing_location_copy (&token->location,
02546 &str->location) ;
02547 }
02548 str = NULL;
02549 }
02550 goto done;
02551 } else {
02552 if (str) {
02553 cr_string_destroy (str);
02554 str = NULL;
02555 }
02556 }
02557 }
02558 break;
02559 }
02560
02561 READ_NEXT_CHAR (a_this, &next_char);
02562 cr_tknzr_get_parsing_location (a_this,
02563 &location) ;
02564 status = cr_token_set_delim (token, next_char);
02565 CHECK_PARSING_STATUS (status, TRUE);
02566 cr_parsing_location_copy (&token->location,
02567 &location) ;
02568 done:
02569
02570 if (status == CR_OK && token) {
02571 *a_tk = token;
02572
02573
02574
02575 memmove (&PRIVATE (a_this)->prev_pos,
02576 &init_pos, sizeof (CRInputPos));
02577 return CR_OK;
02578 }
02579
02580 error:
02581 if (token) {
02582 cr_token_destroy (token);
02583 token = NULL;
02584 }
02585
02586 if (str) {
02587 cr_string_destroy (str);
02588 str = NULL;
02589 }
02590 cr_tknzr_set_cur_pos (a_this, &init_pos);
02591 return status;
02592
02593 }
02594
02595 enum CRStatus
02596 cr_tknzr_parse_token (CRTknzr * a_this, enum CRTokenType a_type,
02597 enum CRTokenExtraType a_et, gpointer a_res,
02598 gpointer a_extra_res)
02599 {
02600 enum CRStatus status = CR_OK;
02601 CRToken *token = NULL;
02602
02603 g_return_val_if_fail (a_this && PRIVATE (a_this)
02604 && PRIVATE (a_this)->input
02605 && a_res, CR_BAD_PARAM_ERROR);
02606
02607 status = cr_tknzr_get_next_token (a_this, &token);
02608 if (status != CR_OK)
02609 return status;
02610 if (token == NULL)
02611 return CR_PARSING_ERROR;
02612
02613 if (token->type == a_type) {
02614 switch (a_type) {
02615 case NO_TK:
02616 case S_TK:
02617 case CDO_TK:
02618 case CDC_TK:
02619 case INCLUDES_TK:
02620 case DASHMATCH_TK:
02621 case IMPORT_SYM_TK:
02622 case PAGE_SYM_TK:
02623 case MEDIA_SYM_TK:
02624 case FONT_FACE_SYM_TK:
02625 case CHARSET_SYM_TK:
02626 case IMPORTANT_SYM_TK:
02627 status = CR_OK;
02628 break;
02629
02630 case STRING_TK:
02631 case IDENT_TK:
02632 case HASH_TK:
02633 case ATKEYWORD_TK:
02634 case FUNCTION_TK:
02635 case COMMENT_TK:
02636 case URI_TK:
02637 *((CRString **) a_res) = token->u.str;
02638 token->u.str = NULL;
02639 status = CR_OK;
02640 break;
02641
02642 case EMS_TK:
02643 case EXS_TK:
02644 case PERCENTAGE_TK:
02645 case NUMBER_TK:
02646 *((CRNum **) a_res) = token->u.num;
02647 token->u.num = NULL;
02648 status = CR_OK;
02649 break;
02650
02651 case LENGTH_TK:
02652 case ANGLE_TK:
02653 case TIME_TK:
02654 case FREQ_TK:
02655 if (token->extra_type == a_et) {
02656 *((CRNum **) a_res) = token->u.num;
02657 token->u.num = NULL;
02658 status = CR_OK;
02659 }
02660 break;
02661
02662 case DIMEN_TK:
02663 *((CRNum **) a_res) = token->u.num;
02664 if (a_extra_res == NULL) {
02665 status = CR_BAD_PARAM_ERROR;
02666 goto error;
02667 }
02668
02669 *((CRString **) a_extra_res) = token->dimen;
02670 token->u.num = NULL;
02671 token->dimen = NULL;
02672 status = CR_OK;
02673 break;
02674
02675 case DELIM_TK:
02676 *((guint32 *) a_res) = token->u.unichar;
02677 status = CR_OK;
02678 break;
02679
02680 case UNICODERANGE_TK:
02681 default:
02682 status = CR_PARSING_ERROR;
02683 break;
02684 }
02685
02686 cr_token_destroy (token);
02687 token = NULL;
02688 } else {
02689 cr_tknzr_unget_token (a_this, token);
02690 token = NULL;
02691 status = CR_PARSING_ERROR;
02692 }
02693
02694 return status;
02695
02696 error:
02697
02698 if (token) {
02699 cr_tknzr_unget_token (a_this, token);
02700 token = NULL;
02701 }
02702
02703 return status;
02704 }
02705
02706 void
02707 cr_tknzr_destroy (CRTknzr * a_this)
02708 {
02709 g_return_if_fail (a_this);
02710
02711 if (PRIVATE (a_this) && PRIVATE (a_this)->input) {
02712 if (cr_input_unref (PRIVATE (a_this)->input)
02713 == TRUE) {
02714 PRIVATE (a_this)->input = NULL;
02715 }
02716 }
02717
02718 if (PRIVATE (a_this)->token_cache) {
02719 cr_token_destroy (PRIVATE (a_this)->token_cache);
02720 PRIVATE (a_this)->token_cache = NULL;
02721 }
02722
02723 if (PRIVATE (a_this)) {
02724 g_free (PRIVATE (a_this));
02725 PRIVATE (a_this) = NULL;
02726 }
02727
02728 g_free (a_this);
02729 }