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