00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <stdio.h>
00025 #include <string.h>
00026 #include "cr-term.h"
00027 #include "cr-num.h"
00028 #include "cr-parser.h"
00029
00030
00031
00032
00033
00034
00035 static void
00036 cr_term_clear (CRTerm * a_this)
00037 {
00038 g_return_if_fail (a_this);
00039
00040 switch (a_this->type) {
00041 case TERM_NUMBER:
00042 if (a_this->content.num) {
00043 cr_num_destroy (a_this->content.num);
00044 a_this->content.num = NULL;
00045 }
00046 break;
00047
00048 case TERM_FUNCTION:
00049 if (a_this->ext_content.func_param) {
00050 cr_term_destroy (a_this->ext_content.func_param);
00051 a_this->ext_content.func_param = NULL;
00052 }
00053 case TERM_STRING:
00054 case TERM_IDENT:
00055 case TERM_URI:
00056 case TERM_HASH:
00057 if (a_this->content.str) {
00058 cr_string_destroy (a_this->content.str);
00059 a_this->content.str = NULL;
00060 }
00061 break;
00062
00063 case TERM_RGB:
00064 if (a_this->content.rgb) {
00065 cr_rgb_destroy (a_this->content.rgb);
00066 a_this->content.rgb = NULL;
00067 }
00068 break;
00069
00070 case TERM_UNICODERANGE:
00071 case TERM_NO_TYPE:
00072 default:
00073 break;
00074 }
00075
00076 a_this->type = TERM_NO_TYPE;
00077 }
00078
00079
00080
00081
00082
00083
00084 CRTerm *
00085 cr_term_new (void)
00086 {
00087 CRTerm *result = NULL;
00088
00089 result = g_try_malloc (sizeof (CRTerm));
00090 if (!result) {
00091 cr_utils_trace_info ("Out of memory");
00092 return NULL;
00093 }
00094 memset (result, 0, sizeof (CRTerm));
00095 return result;
00096 }
00097
00098
00099
00100
00101
00102
00103
00104
00105 CRTerm *
00106 cr_term_parse_expression_from_buf (const guchar * a_buf,
00107 enum CREncoding a_encoding)
00108 {
00109 CRParser *parser = NULL;
00110 CRTerm *result = NULL;
00111 enum CRStatus status = CR_OK;
00112
00113 g_return_val_if_fail (a_buf, NULL);
00114
00115 parser = cr_parser_new_from_buf ((guchar*)a_buf, strlen (a_buf),
00116 a_encoding, FALSE);
00117 g_return_val_if_fail (parser, NULL);
00118
00119 status = cr_parser_try_to_skip_spaces_and_comments (parser);
00120 if (status != CR_OK) {
00121 goto cleanup;
00122 }
00123 status = cr_parser_parse_expr (parser, &result);
00124 if (status != CR_OK) {
00125 if (result) {
00126 cr_term_destroy (result);
00127 result = NULL;
00128 }
00129 }
00130
00131 cleanup:
00132 if (parser) {
00133 cr_parser_destroy (parser);
00134 parser = NULL;
00135 }
00136
00137 return result;
00138 }
00139
00140 enum CRStatus
00141 cr_term_set_number (CRTerm * a_this, CRNum * a_num)
00142 {
00143 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
00144
00145 cr_term_clear (a_this);
00146
00147 a_this->type = TERM_NUMBER;
00148 a_this->content.num = a_num;
00149 return CR_OK;
00150 }
00151
00152 enum CRStatus
00153 cr_term_set_function (CRTerm * a_this, CRString * a_func_name,
00154 CRTerm * a_func_param)
00155 {
00156 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
00157
00158 cr_term_clear (a_this);
00159
00160 a_this->type = TERM_FUNCTION;
00161 a_this->content.str = a_func_name;
00162 a_this->ext_content.func_param = a_func_param;
00163 return CR_OK;
00164 }
00165
00166 enum CRStatus
00167 cr_term_set_string (CRTerm * a_this, CRString * a_str)
00168 {
00169 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
00170
00171 cr_term_clear (a_this);
00172
00173 a_this->type = TERM_STRING;
00174 a_this->content.str = a_str;
00175 return CR_OK;
00176 }
00177
00178 enum CRStatus
00179 cr_term_set_ident (CRTerm * a_this, CRString * a_str)
00180 {
00181 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
00182
00183 cr_term_clear (a_this);
00184
00185 a_this->type = TERM_IDENT;
00186 a_this->content.str = a_str;
00187 return CR_OK;
00188 }
00189
00190 enum CRStatus
00191 cr_term_set_uri (CRTerm * a_this, CRString * a_str)
00192 {
00193 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
00194
00195 cr_term_clear (a_this);
00196
00197 a_this->type = TERM_URI;
00198 a_this->content.str = a_str;
00199 return CR_OK;
00200 }
00201
00202 enum CRStatus
00203 cr_term_set_rgb (CRTerm * a_this, CRRgb * a_rgb)
00204 {
00205 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
00206
00207 cr_term_clear (a_this);
00208
00209 a_this->type = TERM_RGB;
00210 a_this->content.rgb = a_rgb;
00211 return CR_OK;
00212 }
00213
00214 enum CRStatus
00215 cr_term_set_hash (CRTerm * a_this, CRString * a_str)
00216 {
00217 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
00218
00219 cr_term_clear (a_this);
00220
00221 a_this->type = TERM_HASH;
00222 a_this->content.str = a_str;
00223 return CR_OK;
00224 }
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234 CRTerm *
00235 cr_term_append_term (CRTerm * a_this, CRTerm * a_new_term)
00236 {
00237 CRTerm *cur = NULL;
00238
00239 g_return_val_if_fail (a_new_term, NULL);
00240
00241 if (a_this == NULL)
00242 return a_new_term;
00243
00244 for (cur = a_this; cur->next; cur = cur->next) ;
00245
00246 cur->next = a_new_term;
00247 a_new_term->prev = cur;
00248
00249 return a_this;
00250 }
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260 CRTerm *
00261 cr_term_prepend_term (CRTerm * a_this, CRTerm * a_new_term)
00262 {
00263 g_return_val_if_fail (a_this && a_new_term, NULL);
00264
00265 a_new_term->next = a_this;
00266 a_this->prev = a_new_term;
00267
00268 return a_new_term;
00269 }
00270
00271
00272
00273
00274
00275
00276
00277
00278 guchar *
00279 cr_term_to_string (CRTerm * a_this)
00280 {
00281 GString *str_buf = NULL;
00282 CRTerm *cur = NULL;
00283 guchar *result = NULL,
00284 *content = NULL;
00285
00286 g_return_val_if_fail (a_this, NULL);
00287
00288 str_buf = g_string_new (NULL);
00289 g_return_val_if_fail (str_buf, NULL);
00290
00291 for (cur = a_this; cur; cur = cur->next) {
00292 if ((cur->content.str == NULL)
00293 && (cur->content.num == NULL)
00294 && (cur->content.str == NULL)
00295 && (cur->content.rgb == NULL))
00296 continue;
00297
00298 switch (cur->the_operator) {
00299 case DIVIDE:
00300 g_string_append (str_buf, " / ");
00301 break;
00302
00303 case COMMA:
00304 g_string_append (str_buf, ", ");
00305 break;
00306
00307 case NO_OP:
00308 if (cur->prev) {
00309 g_string_append (str_buf, " ");
00310 }
00311 break;
00312 default:
00313
00314 break;
00315 }
00316
00317 switch (cur->unary_op) {
00318 case PLUS_UOP:
00319 g_string_append (str_buf, "+");
00320 break;
00321
00322 case MINUS_UOP:
00323 g_string_append (str_buf, "-");
00324 break;
00325
00326 default:
00327 break;
00328 }
00329
00330 switch (cur->type) {
00331 case TERM_NUMBER:
00332 if (cur->content.num) {
00333 content = cr_num_to_string (cur->content.num);
00334 }
00335
00336 if (content) {
00337 g_string_append (str_buf, content);
00338 g_free (content);
00339 content = NULL;
00340 }
00341
00342 break;
00343
00344 case TERM_FUNCTION:
00345 if (cur->content.str) {
00346 content = g_strndup
00347 (cur->content.str->stryng->str,
00348 cur->content.str->stryng->len);
00349 }
00350
00351 if (content) {
00352 g_string_append_printf (str_buf, "%s(",
00353 content);
00354
00355 if (cur->ext_content.func_param) {
00356 guchar *tmp_str = NULL;
00357
00358 tmp_str = cr_term_to_string
00359 (cur->
00360 ext_content.func_param);
00361
00362 if (tmp_str) {
00363 g_string_append (str_buf,
00364 tmp_str);
00365 g_free (tmp_str);
00366 tmp_str = NULL;
00367 }
00368
00369 g_free (content);
00370 content = NULL;
00371 }
00372 g_string_append (str_buf, ")");
00373 }
00374
00375 break;
00376
00377 case TERM_STRING:
00378 if (cur->content.str) {
00379 content = g_strndup
00380 (cur->content.str->stryng->str,
00381 cur->content.str->stryng->len);
00382 }
00383
00384 if (content) {
00385 g_string_append_printf (str_buf,
00386 "\"%s\"", content);
00387 g_free (content);
00388 content = NULL;
00389 }
00390 break;
00391
00392 case TERM_IDENT:
00393 if (cur->content.str) {
00394 content = g_strndup
00395 (cur->content.str->stryng->str,
00396 cur->content.str->stryng->len);
00397 }
00398
00399 if (content) {
00400 g_string_append (str_buf, content);
00401 g_free (content);
00402 content = NULL;
00403 }
00404 break;
00405
00406 case TERM_URI:
00407 if (cur->content.str) {
00408 content = g_strndup
00409 (cur->content.str->stryng->str,
00410 cur->content.str->stryng->len);
00411 }
00412
00413 if (content) {
00414 g_string_append_printf
00415 (str_buf, "url(%s)", content);
00416 g_free (content);
00417 content = NULL;
00418 }
00419 break;
00420
00421 case TERM_RGB:
00422 if (cur->content.rgb) {
00423 guchar *tmp_str = NULL;
00424
00425 g_string_append (str_buf, "rgb(");
00426 tmp_str = cr_rgb_to_string (cur->content.rgb);
00427
00428 if (tmp_str) {
00429 g_string_append (str_buf, tmp_str);
00430 g_free (tmp_str);
00431 tmp_str = NULL;
00432 }
00433 g_string_append (str_buf, ")");
00434 }
00435
00436 break;
00437
00438 case TERM_UNICODERANGE:
00439 g_string_append
00440 (str_buf,
00441 "?found unicoderange: dump not supported yet?");
00442 break;
00443
00444 case TERM_HASH:
00445 if (cur->content.str) {
00446 content = g_strndup
00447 (cur->content.str->stryng->str,
00448 cur->content.str->stryng->len);
00449 }
00450
00451 if (content) {
00452 g_string_append_printf (str_buf,
00453 "#%s", content);
00454 g_free (content);
00455 content = NULL;
00456 }
00457 break;
00458
00459 default:
00460 g_string_append (str_buf,
00461 "Unrecognized Term type");
00462 break;
00463 }
00464 }
00465
00466 if (str_buf) {
00467 result = str_buf->str;
00468 g_string_free (str_buf, FALSE);
00469 str_buf = NULL;
00470 }
00471
00472 return result;
00473 }
00474
00475 guchar *
00476 cr_term_one_to_string (CRTerm * a_this)
00477 {
00478 GString *str_buf = NULL;
00479 guchar *result = NULL,
00480 *content = NULL;
00481
00482 g_return_val_if_fail (a_this, NULL);
00483
00484 str_buf = g_string_new (NULL);
00485 g_return_val_if_fail (str_buf, NULL);
00486
00487 if ((a_this->content.str == NULL)
00488 && (a_this->content.num == NULL)
00489 && (a_this->content.str == NULL)
00490 && (a_this->content.rgb == NULL))
00491 return NULL ;
00492
00493 switch (a_this->the_operator) {
00494 case DIVIDE:
00495 g_string_append_printf (str_buf, " / ");
00496 break;
00497
00498 case COMMA:
00499 g_string_append_printf (str_buf, ", ");
00500 break;
00501
00502 case NO_OP:
00503 if (a_this->prev) {
00504 g_string_append_printf (str_buf, " ");
00505 }
00506 break;
00507 default:
00508
00509 break;
00510 }
00511
00512 switch (a_this->unary_op) {
00513 case PLUS_UOP:
00514 g_string_append_printf (str_buf, "+");
00515 break;
00516
00517 case MINUS_UOP:
00518 g_string_append_printf (str_buf, "-");
00519 break;
00520
00521 default:
00522 break;
00523 }
00524
00525 switch (a_this->type) {
00526 case TERM_NUMBER:
00527 if (a_this->content.num) {
00528 content = cr_num_to_string (a_this->content.num);
00529 }
00530
00531 if (content) {
00532 g_string_append (str_buf, content);
00533 g_free (content);
00534 content = NULL;
00535 }
00536
00537 break;
00538
00539 case TERM_FUNCTION:
00540 if (a_this->content.str) {
00541 content = g_strndup
00542 (a_this->content.str->stryng->str,
00543 a_this->content.str->stryng->len);
00544 }
00545
00546 if (content) {
00547 g_string_append_printf (str_buf, "%s(",
00548 content);
00549
00550 if (a_this->ext_content.func_param) {
00551 guchar *tmp_str = NULL;
00552
00553 tmp_str = cr_term_to_string
00554 (a_this->
00555 ext_content.func_param);
00556
00557 if (tmp_str) {
00558 g_string_append_printf
00559 (str_buf,
00560 "%s", tmp_str);
00561 g_free (tmp_str);
00562 tmp_str = NULL;
00563 }
00564
00565 g_string_append_printf (str_buf, ")");
00566 g_free (content);
00567 content = NULL;
00568 }
00569 }
00570
00571 break;
00572
00573 case TERM_STRING:
00574 if (a_this->content.str) {
00575 content = g_strndup
00576 (a_this->content.str->stryng->str,
00577 a_this->content.str->stryng->len);
00578 }
00579
00580 if (content) {
00581 g_string_append_printf (str_buf,
00582 "\"%s\"", content);
00583 g_free (content);
00584 content = NULL;
00585 }
00586 break;
00587
00588 case TERM_IDENT:
00589 if (a_this->content.str) {
00590 content = g_strndup
00591 (a_this->content.str->stryng->str,
00592 a_this->content.str->stryng->len);
00593 }
00594
00595 if (content) {
00596 g_string_append (str_buf, content);
00597 g_free (content);
00598 content = NULL;
00599 }
00600 break;
00601
00602 case TERM_URI:
00603 if (a_this->content.str) {
00604 content = g_strndup
00605 (a_this->content.str->stryng->str,
00606 a_this->content.str->stryng->len);
00607 }
00608
00609 if (content) {
00610 g_string_append_printf
00611 (str_buf, "url(%s)", content);
00612 g_free (content);
00613 content = NULL;
00614 }
00615 break;
00616
00617 case TERM_RGB:
00618 if (a_this->content.rgb) {
00619 guchar *tmp_str = NULL;
00620
00621 g_string_append_printf (str_buf, "rgb(");
00622 tmp_str = cr_rgb_to_string (a_this->content.rgb);
00623
00624 if (tmp_str) {
00625 g_string_append (str_buf, tmp_str);
00626 g_free (tmp_str);
00627 tmp_str = NULL;
00628 }
00629 g_string_append_printf (str_buf, ")");
00630 }
00631
00632 break;
00633
00634 case TERM_UNICODERANGE:
00635 g_string_append_printf
00636 (str_buf,
00637 "?found unicoderange: dump not supported yet?");
00638 break;
00639
00640 case TERM_HASH:
00641 if (a_this->content.str) {
00642 content = g_strndup
00643 (a_this->content.str->stryng->str,
00644 a_this->content.str->stryng->len);
00645 }
00646
00647 if (content) {
00648 g_string_append_printf (str_buf,
00649 "#%s", content);
00650 g_free (content);
00651 content = NULL;
00652 }
00653 break;
00654
00655 default:
00656 g_string_append_printf (str_buf,
00657 "%s",
00658 "Unrecognized Term type");
00659 break;
00660 }
00661
00662 if (str_buf) {
00663 result = str_buf->str;
00664 g_string_free (str_buf, FALSE);
00665 str_buf = NULL;
00666 }
00667
00668 return result;
00669 }
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679 void
00680 cr_term_dump (CRTerm * a_this, FILE * a_fp)
00681 {
00682 guchar *content = NULL;
00683
00684 g_return_if_fail (a_this);
00685
00686 content = cr_term_to_string (a_this);
00687
00688 if (content) {
00689 fprintf (a_fp, "%s", content);
00690 g_free (content);
00691 }
00692 }
00693
00694
00695
00696
00697
00698
00699 int
00700 cr_term_nr_values (CRTerm *a_this)
00701 {
00702 CRTerm *cur = NULL ;
00703 int nr = 0;
00704
00705 g_return_val_if_fail (a_this, -1) ;
00706
00707 for (cur = a_this ; cur ; cur = cur->next)
00708 nr ++;
00709 return nr;
00710 }
00711
00712
00713
00714
00715
00716
00717
00718
00719 CRTerm *
00720 cr_term_get_from_list (CRTerm *a_this, int itemnr)
00721 {
00722 CRTerm *cur = NULL ;
00723 int nr = 0;
00724
00725 g_return_val_if_fail (a_this, NULL) ;
00726
00727 for (cur = a_this ; cur ; cur = cur->next)
00728 if (nr++ == itemnr)
00729 return cur;
00730 return NULL;
00731 }
00732
00733
00734
00735
00736
00737
00738 void
00739 cr_term_ref (CRTerm * a_this)
00740 {
00741 g_return_if_fail (a_this);
00742
00743 a_this->ref_count++;
00744 }
00745
00746
00747
00748
00749
00750
00751
00752
00753 gboolean
00754 cr_term_unref (CRTerm * a_this)
00755 {
00756 g_return_val_if_fail (a_this, FALSE);
00757
00758 if (a_this->ref_count) {
00759 a_this->ref_count--;
00760 }
00761
00762 if (a_this->ref_count == 0) {
00763 cr_term_destroy (a_this);
00764 return TRUE;
00765 }
00766
00767 return FALSE;
00768 }
00769
00770
00771
00772
00773
00774
00775 void
00776 cr_term_destroy (CRTerm * a_this)
00777 {
00778 g_return_if_fail (a_this);
00779
00780 cr_term_clear (a_this);
00781
00782 if (a_this->next) {
00783 cr_term_destroy (a_this->next);
00784 a_this->next = NULL;
00785 }
00786
00787 if (a_this) {
00788 g_free (a_this);
00789 }
00790
00791 }