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 #include <stdio.h>
00027 #include <string.h>
00028 #include "cr-term.h"
00029 #include "cr-num.h"
00030 #include "cr-parser.h"
00031
00032
00033
00034
00035
00036
00037
00038 static void
00039 cr_term_clear (CRTerm *a_this)
00040 {
00041 g_return_if_fail (a_this) ;
00042
00043 switch (a_this->type)
00044 {
00045 case TERM_NUMBER:
00046 if (a_this->content.num)
00047 {
00048 cr_num_destroy (a_this->content.num) ;
00049 a_this->content.num = NULL ;
00050 }
00051 break ;
00052
00053 case TERM_FUNCTION:
00054 if (a_this->ext_content.func_param)
00055 {
00056 cr_term_destroy (a_this->ext_content.func_param) ;
00057 a_this->ext_content.func_param = NULL ;
00058 }
00059 case TERM_STRING:
00060 case TERM_IDENT:
00061 case TERM_URI:
00062 case TERM_HASH:
00063 if (a_this->content.str)
00064 {
00065 g_string_free (a_this->content.str, TRUE) ;
00066 a_this->content.str = NULL ;
00067 }
00068 break ;
00069
00070 case TERM_RGB:
00071 if (a_this->content.rgb)
00072 {
00073 cr_rgb_destroy (a_this->content.rgb) ;
00074 a_this->content.rgb = NULL ;
00075 }
00076 break ;
00077
00078 case TERM_UNICODERANGE:
00079 case TERM_NO_TYPE:
00080 default:
00081 break ;
00082 }
00083
00084 a_this->type = TERM_NO_TYPE ;
00085 }
00086
00087
00088
00089
00090
00091
00092
00093 CRTerm *
00094 cr_term_new (void)
00095 {
00096 CRTerm *result = NULL ;
00097
00098 result = g_try_malloc (sizeof (CRTerm)) ;
00099 if (!result)
00100 {
00101 cr_utils_trace_info ("Out of memory") ;
00102 return NULL ;
00103 }
00104 memset (result, 0, sizeof (CRTerm)) ;
00105 return result ;
00106 }
00107
00108
00109
00110
00111
00112
00113
00114
00115 CRTerm *
00116 cr_term_parse_expression_from_buf (const guchar *a_buf,
00117 enum CREncoding a_encoding)
00118 {
00119 CRParser *parser = NULL ;
00120 CRTerm *result = NULL ;
00121 enum CRStatus status = CR_OK ;
00122
00123 g_return_val_if_fail (a_buf, NULL) ;
00124
00125 parser = cr_parser_new_from_buf (a_buf, strlen (a_buf),
00126 a_encoding, FALSE) ;
00127 g_return_val_if_fail (parser, NULL) ;
00128
00129 status = cr_parser_try_to_skip_spaces_and_comments (parser) ;
00130 if (status != CR_OK)
00131 {
00132 goto cleanup ;
00133 }
00134
00135 status = cr_parser_parse_expr (parser, &result) ;
00136 if (status != CR_OK)
00137 {
00138 if (result)
00139 {
00140 cr_term_destroy (result) ;
00141 result = NULL ;
00142 }
00143 }
00144
00145 cleanup:
00146 if (parser)
00147 {
00148 cr_parser_destroy (parser) ;
00149 parser = NULL ;
00150 }
00151
00152 return result ;
00153 }
00154
00155 enum CRStatus
00156 cr_term_set_number (CRTerm *a_this, CRNum *a_num)
00157 {
00158 g_return_val_if_fail (a_this,
00159 CR_BAD_PARAM_ERROR) ;
00160
00161 cr_term_clear (a_this) ;
00162
00163 a_this->type = TERM_NUMBER ;
00164 a_this->content.num = a_num ;
00165 return CR_OK ;
00166 }
00167
00168 enum CRStatus
00169 cr_term_set_function (CRTerm *a_this, GString *a_func_name,
00170 CRTerm *a_func_param)
00171 {
00172 g_return_val_if_fail (a_this,
00173 CR_BAD_PARAM_ERROR) ;
00174
00175 cr_term_clear (a_this) ;
00176
00177 a_this->type = TERM_FUNCTION ;
00178 a_this->content.str = a_func_name ;
00179 a_this->ext_content.func_param = a_func_param ;
00180 return CR_OK ;
00181 }
00182
00183 enum CRStatus
00184 cr_term_set_string (CRTerm *a_this, GString *a_str)
00185 {
00186 g_return_val_if_fail (a_this,
00187 CR_BAD_PARAM_ERROR) ;
00188
00189 cr_term_clear (a_this) ;
00190
00191 a_this->type = TERM_STRING ;
00192 a_this->content.str = a_str ;
00193 return CR_OK ;
00194 }
00195
00196 enum CRStatus
00197 cr_term_set_ident (CRTerm *a_this, GString *a_str)
00198 {
00199 g_return_val_if_fail (a_this,
00200 CR_BAD_PARAM_ERROR) ;
00201
00202 cr_term_clear (a_this) ;
00203
00204 a_this->type = TERM_IDENT ;
00205 a_this->content.str = a_str ;
00206 return CR_OK ;
00207 }
00208
00209 enum CRStatus
00210 cr_term_set_uri (CRTerm *a_this, GString *a_str)
00211 {
00212 g_return_val_if_fail (a_this,
00213 CR_BAD_PARAM_ERROR) ;
00214
00215 cr_term_clear (a_this) ;
00216
00217 a_this->type = TERM_URI ;
00218 a_this->content.str = a_str ;
00219 return CR_OK ;
00220 }
00221
00222 enum CRStatus
00223 cr_term_set_rgb (CRTerm *a_this, CRRgb *a_rgb)
00224 {
00225 g_return_val_if_fail (a_this,
00226 CR_BAD_PARAM_ERROR) ;
00227
00228 cr_term_clear (a_this) ;
00229
00230 a_this->type = TERM_RGB ;
00231 a_this->content.rgb = a_rgb ;
00232 return CR_OK ;
00233 }
00234
00235 enum CRStatus
00236 cr_term_set_hash (CRTerm *a_this, GString *a_str)
00237 {
00238 g_return_val_if_fail (a_this,
00239 CR_BAD_PARAM_ERROR) ;
00240
00241 cr_term_clear (a_this) ;
00242
00243 a_this->type = TERM_HASH ;
00244 a_this->content.str = a_str ;
00245 return CR_OK ;
00246 }
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256 CRTerm *
00257 cr_term_append_term (CRTerm *a_this, CRTerm *a_new_term)
00258 {
00259 CRTerm *cur = NULL ;
00260
00261 g_return_val_if_fail (a_new_term,
00262 NULL) ;
00263
00264 if (a_this == NULL)
00265 return a_new_term ;
00266
00267 for (cur = a_this ;cur->next ; cur = cur->next) ;
00268
00269 cur->next = a_new_term ;
00270 a_new_term->prev = cur ;
00271
00272 return a_this ;
00273 }
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284 CRTerm *
00285 cr_term_prepend_term (CRTerm *a_this, CRTerm *a_new_term)
00286 {
00287 g_return_val_if_fail (a_this && a_new_term,
00288 NULL) ;
00289
00290 a_new_term->next = a_this ;
00291 a_this->prev = a_new_term ;
00292
00293 return a_new_term ;
00294 }
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304 guchar *
00305 cr_term_to_string (CRTerm *a_this)
00306 {
00307 GString *str_buf = NULL ;
00308 CRTerm *cur = NULL ;
00309 guchar *result = NULL, *content = NULL ;
00310
00311 g_return_val_if_fail (a_this, NULL) ;
00312
00313 str_buf = g_string_new (NULL) ;
00314 g_return_val_if_fail (str_buf, NULL) ;
00315
00316 for (cur = a_this ; cur ; cur = cur->next)
00317 {
00318 if ((cur->content.str == NULL)
00319 && (cur->content.num == NULL)
00320 && (cur->content.str == NULL)
00321 && (cur->content.rgb == NULL))
00322 continue ;
00323
00324 switch (cur->operator)
00325 {
00326 case DIVIDE:
00327 g_string_append_printf (str_buf, " / ") ;
00328 break ;
00329
00330 case COMMA:
00331 g_string_append_printf (str_buf, ", ") ;
00332 break ;
00333
00334 case NO_OP:
00335 if (cur->prev)
00336 {
00337 g_string_append_printf (str_buf, " ") ;
00338 }
00339 break ;
00340 default:
00341
00342 break ;
00343 }
00344
00345 switch (cur->unary_op)
00346 {
00347 case PLUS_UOP:
00348 g_string_append_printf (str_buf, "+") ;
00349 break ;
00350
00351 case MINUS_UOP:
00352 g_string_append_printf (str_buf, "-") ;
00353 break ;
00354
00355 default :
00356 break ;
00357 }
00358
00359 switch (cur->type)
00360 {
00361 case TERM_NUMBER:
00362 if (cur->content.num)
00363 {
00364 content =
00365 cr_num_to_string
00366 (cur->content.num) ;
00367 }
00368
00369 if (content)
00370 {
00371 g_string_append(str_buf, content) ;
00372 g_free (content) ;
00373 content = NULL ;
00374 }
00375
00376 break ;
00377
00378 case TERM_FUNCTION:
00379 if (cur->content.str)
00380 {
00381 content = g_strndup
00382 (cur->content.str->str,
00383 cur->content.str->len) ;
00384 }
00385
00386 if (content)
00387 {
00388 g_string_append_printf (str_buf, "%s(",
00389 content) ;
00390
00391 if (a_this->ext_content.func_param)
00392 {
00393 guchar *tmp_str = NULL ;
00394
00395 tmp_str = cr_term_to_string
00396 (a_this->
00397 ext_content.func_param);
00398
00399 if (tmp_str)
00400 {
00401 g_string_append_printf
00402 (str_buf,
00403 "%s",
00404 tmp_str) ;
00405 g_free (tmp_str) ;
00406 tmp_str = NULL ;
00407 }
00408
00409 g_string_append_printf (str_buf,
00410 ")") ;
00411 g_free (content) ;
00412 content = NULL ;
00413 }
00414 }
00415
00416 break ;
00417
00418 case TERM_STRING:
00419 if (cur->content.str)
00420 {
00421 content = g_strndup
00422 (cur->content.str->str,
00423 cur->content.str->len) ;
00424 }
00425
00426 if (content)
00427 {
00428 g_string_append_printf (str_buf,
00429 "\"%s\"",
00430 content) ;
00431 g_free (content) ;
00432 content = NULL ;
00433 }
00434 break ;
00435
00436 case TERM_IDENT:
00437 if (cur->content.str)
00438 {
00439 content = g_strndup
00440 (cur->content.str->str,
00441 cur->content.str->len) ;
00442 }
00443
00444 if (content)
00445 {
00446 g_string_append (str_buf,content) ;
00447 g_free (content) ;
00448 content = NULL ;
00449 }
00450 break ;
00451
00452 case TERM_URI:
00453 if (cur->content.str)
00454 {
00455 content = g_strndup
00456 (cur->content.str->str,
00457 cur->content.str->len) ;
00458 }
00459
00460 if (content)
00461 {
00462 g_string_append_printf
00463 (str_buf, "url(%s)",content) ;
00464 g_free (content) ;
00465 content = NULL ;
00466 }
00467 break ;
00468
00469 case TERM_RGB:
00470 if (cur->content.rgb)
00471 {
00472 guchar *tmp_str = NULL ;
00473
00474 g_string_append_printf (str_buf, "rgb(");
00475 tmp_str = cr_rgb_to_string
00476 (cur->content.rgb) ;
00477
00478 if (tmp_str)
00479 {
00480 g_string_append (str_buf,
00481 tmp_str) ;
00482 g_free (tmp_str) ;
00483 tmp_str = NULL ;
00484 }
00485 g_string_append_printf (str_buf, ")") ;
00486 }
00487
00488 break ;
00489
00490 case TERM_UNICODERANGE:
00491 g_string_append_printf
00492 (str_buf,
00493 "?found unicoderange: dump not supported yet?") ;
00494 break ;
00495
00496 case TERM_HASH:
00497 if (cur->content.str)
00498 {
00499 content = g_strndup
00500 (cur->content.str->str,
00501 cur->content.str->len) ;
00502 }
00503
00504 if (content)
00505 {
00506 g_string_append_printf (str_buf,
00507 "#%s", content) ;
00508 g_free (content) ;
00509 content = NULL ;
00510 }
00511 break ;
00512
00513 default:
00514 g_string_append_printf (str_buf,
00515 "%s",
00516 "Unrecognized Term type");
00517 break ;
00518 }
00519 }
00520
00521 if (str_buf)
00522 {
00523 result = str_buf->str ;
00524 g_string_free (str_buf, FALSE) ;
00525 str_buf = NULL ;
00526 }
00527
00528 return result ;
00529 }
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539 void
00540 cr_term_dump (CRTerm *a_this, FILE *a_fp)
00541 {
00542 guchar *content=NULL ;
00543
00544 g_return_if_fail (a_this) ;
00545
00546 content = cr_term_to_string (a_this) ;
00547
00548 if (content)
00549 {
00550 fprintf (a_fp, "%s", content) ;
00551 g_free (content) ;
00552 }
00553 }
00554
00555
00556
00557
00558
00559
00560
00561 void
00562 cr_term_ref (CRTerm *a_this)
00563 {
00564 g_return_if_fail (a_this) ;
00565
00566 a_this->ref_count ++ ;
00567 }
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577 gboolean
00578 cr_term_unref (CRTerm *a_this)
00579 {
00580 g_return_val_if_fail (a_this, FALSE) ;
00581
00582 if (a_this->ref_count)
00583 {
00584 a_this->ref_count -- ;
00585 }
00586
00587 if (a_this->ref_count == 0)
00588 {
00589 cr_term_destroy (a_this) ;
00590 return TRUE ;
00591 }
00592
00593 return FALSE ;
00594 }
00595
00596
00597
00598
00599
00600
00601 void
00602 cr_term_destroy (CRTerm *a_this)
00603 {
00604 g_return_if_fail (a_this) ;
00605
00606 cr_term_clear (a_this) ;
00607
00608 if (a_this->next)
00609 {
00610 cr_term_destroy (a_this->next) ;
00611 a_this->next = NULL ;
00612 }
00613
00614 if (a_this)
00615 {
00616 g_free (a_this) ;
00617 }
00618
00619 }