apply FSL(Flora Software License)
[apps/home/calculator.git] / src / calculator_parser.c
1 /*
2   * Copyright 2012  Samsung Electronics Co., Ltd
3   * 
4   * Licensed under the Flora License, Version 1.0 (the "License");
5   * you may not use this file except in compliance with the License.
6   * You may obtain a copy of the License at
7   * 
8   *     http://www.tizenopensource.org/license
9   * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17
18
19 #include <math.h>               /* For math functions, cos(), sin(), etc. */
20 #include <dlog.h>
21 #include <string.h>
22 #include <stdbool.h>
23
24 #include "calc-main.h"
25 #include "calc-string.h"
26 #include "calc-expression.h"
27 #include "calculator_parser.h"
28
29 #define CALCULATOR_MAX_FUNC_NUMBER                              16              /**<maximum num of function*/
30
31 extern char decimal_ch;
32 static char g_stack[MAX_EXPRESSION_LENGTH];
33
34 static calculator_parentheses_data_t g_parentheses_data[MAX_PARENTHESES_NUM];
35
36 static int oper_num = 0;
37
38 static const function_t g_functions[CALCULATOR_MAX_FUNC_NUMBER] = {
39         {"x^y", "^", 1, '^', FUNCTION_POSTFIX, OPERATOR_TYPE_BINARY,
40          CALCULATOR_CALCULATE_PRIORITY_HIGH, FALSE},
41         {"ln", "ln", 2, 'L', FUNCTION_PREFIX, OPERATOR_TYPE_UNARY,
42          CALCULATOR_CALCULATE_PRIORITY_HIGHER, TRUE},
43         {"sqrt", "sqrt", 4, 'q', FUNCTION_PREFIX, OPERATOR_TYPE_UNARY,
44          CALCULATOR_CALCULATE_PRIORITY_HIGHER, TRUE},
45         {"e^x", "e^", 2, 'E', FUNCTION_PREFIX, OPERATOR_TYPE_UNARY,
46          CALCULATOR_CALCULATE_PRIORITY_HIGHER, FALSE},
47         {"x!", "!", 1, '!', FUNCTION_POSTFIX, OPERATOR_TYPE_UNARY,
48          CALCULATOR_CALCULATE_PRIORITY_HIGHEST, FALSE},
49         {"1/x", "/", 1, 'x', FUNCTION_POSTFIX, OPERATOR_TYPE_UNARY,
50          CALCULATOR_CALCULATE_PRIORITY_HIGHEST, FALSE},
51         {"sin", "sin", 3, 's', FUNCTION_PREFIX, OPERATOR_TYPE_UNARY,
52          CALCULATOR_CALCULATE_PRIORITY_HIGHER, TRUE},
53         {"cos", "cos", 3, 'c', FUNCTION_PREFIX, OPERATOR_TYPE_UNARY,
54          CALCULATOR_CALCULATE_PRIORITY_HIGHER, TRUE},
55         {"tan", "tan", 3, 't', FUNCTION_PREFIX, OPERATOR_TYPE_UNARY,
56          CALCULATOR_CALCULATE_PRIORITY_HIGHER, TRUE},
57         {"Pi", "p", 1, 'p', FUNCTION_CONSTANT, OPERATOR_TYPE_INVALID,
58          CALCULATOR_CALCULATE_PRIORITY_INVALID, FALSE},
59         {"e", "e", 1, 'e', FUNCTION_CONSTANT, OPERATOR_TYPE_INVALID,
60          CALCULATOR_CALCULATE_PRIORITY_INVALID, FALSE},
61         {"log", "log", 3, 'l', FUNCTION_PREFIX, OPERATOR_TYPE_UNARY,
62          CALCULATOR_CALCULATE_PRIORITY_HIGHER, TRUE},
63         {"abs", "abs", 3, 'b', FUNCTION_PREFIX, OPERATOR_TYPE_UNARY,
64          CALCULATOR_CALCULATE_PRIORITY_HIGHER, TRUE},
65         {"2^x", "2^", 2, '2', FUNCTION_PREFIX, OPERATOR_TYPE_UNARY,
66          CALCULATOR_CALCULATE_PRIORITY_HIGHER, FALSE},
67         {"xCy", "C", 1, 'C', FUNCTION_POSTFIX, OPERATOR_TYPE_BINARY,
68          CALCULATOR_CALCULATE_PRIORITY_HIGH, FALSE},
69         {"xPy", "P", 1, 'P', FUNCTION_POSTFIX, OPERATOR_TYPE_BINARY,
70          CALCULATOR_CALCULATE_PRIORITY_HIGH, FALSE},
71 };
72
73 #define CALCULATOR_GET_NODE_DATA(t)     ((calculator_node_data_t*)(((GNode*)(t))->data))/**<to get data from GNode structure*/
74
75 /**
76 * @describe
77 *
78 *
79 * @param    out_tree
80 * @param    to_insert
81 * @param    const_node
82 * @return    gboolean
83 * @exception
84 */
85 static gboolean
86 __calculator_calculate_insert_node(GNode ** out_tree, GNode * to_insert,
87                                    GNode * const_node)
88 {
89         GNode *upper_node = NULL;
90         GNode *node = NULL;
91         calculator_node_data_t *node_data = NULL;
92
93         if ((!out_tree) || (!*out_tree) || (!to_insert)) {
94                 return FALSE;
95         }
96
97         upper_node = *out_tree;
98         node = upper_node;
99
100 /* @ attention
101      This is redundant comment.
102      Its only use is for Klocwork testing.
103      The comment rete should passed 25%.
104      But we have only one day to do this work.
105      So, sorry, I will delete this comment and add useful comment later.
106 */
107
108         while (CALCULATOR_GET_NODE_DATA(upper_node)->node_calcu_priority >
109                CALCULATOR_GET_NODE_DATA(to_insert)->node_calcu_priority) {
110                 if (G_NODE_IS_ROOT(upper_node)) {
111                         g_node_insert(to_insert, -1, upper_node);
112                         CALCULATOR_GET_NODE_DATA(to_insert)->children_num++;
113
114                         if (const_node) {
115                                 g_node_insert(*out_tree, -1, const_node);       //value of last node's priority>= upper_node's > to_insert's
116                                 CALCULATOR_GET_NODE_DATA(*out_tree)->
117                                     children_num++;
118                         }
119                         break;
120                 }
121                 node = upper_node;
122                 upper_node = upper_node->parent;
123         }
124
125         if (CALCULATOR_GET_NODE_DATA(upper_node)->node_calcu_priority ==
126             CALCULATOR_GET_NODE_DATA(to_insert)->node_calcu_priority) {
127                 if (CALCULATOR_GET_NODE_DATA(to_insert)->operator_type ==
128                     OPERATOR_TYPE_BINARY) {
129                         GNode *parent_node = NULL;
130
131                         if (!G_NODE_IS_ROOT(upper_node)) {
132                                 parent_node = upper_node->parent;
133                                 g_node_unlink(upper_node);
134                                 g_node_insert(parent_node, -1, to_insert);
135                         }
136
137                         g_node_insert(to_insert, -1, upper_node);
138                         CALCULATOR_GET_NODE_DATA(to_insert)->children_num++;
139
140                         if (const_node) {
141                                 g_node_insert(*out_tree, -1, const_node);
142                                 CALCULATOR_GET_NODE_DATA(*out_tree)->
143                                     children_num++;
144                         }
145                 } else if (CALCULATOR_GET_NODE_DATA(to_insert)->operator_type ==
146                            OPERATOR_TYPE_UNARY) {
147                         GNode *tmp_node = NULL;
148 /* @ attention
149      This is redundant comment.
150      Its only use is for Klocwork testing.
151      The comment rete should passed 25%.
152      But we have only one day to do this work.
153      So, sorry, I will delete this comment and add useful comment later.
154 */
155
156                         if (const_node) {
157                                 node_data =
158                                     g_malloc0(sizeof(calculator_node_data_t));
159                                 node_data->cur_operator = 'x';
160                                 node_data->negative_flag = 1;
161                                 node_data->operator_type = OPERATOR_TYPE_BINARY;
162                                 node_data->node_calcu_priority =
163                                     CALCULATOR_CALCULATE_PRIORITY_MIDDLE;
164                                 tmp_node = g_node_new(node_data);
165
166                                 if (CALCULATOR_GET_NODE_DATA(to_insert)->
167                                     cur_operator != '!') {
168                                         __calculator_calculate_insert_node
169                                             (out_tree, tmp_node, const_node);
170                                 } else  //(CALCULATOR_GET_NODE_DATA(to_insert)->cur_operator == '!')
171                                 {
172                                         g_node_insert(to_insert, -1,
173                                                       const_node);
174                                         CALCULATOR_GET_NODE_DATA(to_insert)->
175                                             children_num++;
176                                 }
177
178                                 g_node_insert(*out_tree, -1, to_insert);
179                                 CALCULATOR_GET_NODE_DATA(*out_tree)->
180                                     children_num++;
181                         } else {
182                                 g_node_insert(upper_node, -1, to_insert);       //combine from right
183                                 CALCULATOR_GET_NODE_DATA(upper_node)->
184                                     children_num++;
185                         }
186                 }
187         } else if (CALCULATOR_GET_NODE_DATA(upper_node)->node_calcu_priority <
188                    CALCULATOR_GET_NODE_DATA(to_insert)->node_calcu_priority) {
189                 if (CALCULATOR_GET_NODE_DATA(to_insert)->operator_type ==
190                     OPERATOR_TYPE_BINARY) {
191                         if (node != upper_node) {
192                                 g_node_unlink(node);
193                                 CALCULATOR_GET_NODE_DATA(upper_node)->
194                                     children_num--;
195
196                                 g_node_insert(to_insert, -1, node);
197                                 CALCULATOR_GET_NODE_DATA(to_insert)->
198                                     children_num++;
199                         }
200
201                         if (const_node) {
202                                 if (CALCULATOR_GET_NODE_DATA(*out_tree)->
203                                     node_calcu_priority >
204                                     CALCULATOR_GET_NODE_DATA(to_insert)->
205                                     node_calcu_priority) {
206                                         g_node_insert(*out_tree, -1,
207                                                       const_node);
208                                         CALCULATOR_GET_NODE_DATA(*out_tree)->
209                                             children_num++;
210                                 } else {
211                                         g_node_insert(to_insert, -1,
212                                                       const_node);
213                                         CALCULATOR_GET_NODE_DATA(to_insert)->
214                                             children_num++;
215                                 }
216                         }
217
218                         g_node_insert(upper_node, -1, to_insert);
219                         CALCULATOR_GET_NODE_DATA(upper_node)->children_num++;
220                 }
221 /* @ attention
222      This is redundant comment.
223      Its only use is for Klocwork testing.
224      The comment rete should passed 25%.
225      But we have only one day to do this work.
226      So, sorry, I will delete this comment and add useful comment later.
227 */
228
229                 else if (CALCULATOR_GET_NODE_DATA(to_insert)->operator_type == OPERATOR_TYPE_UNARY)     //upper_node must be equal to node equalized to *out_tree, for no functions' prority higher than unary operator
230                 {
231                         if (const_node) {
232
233                                 if (CALCULATOR_GET_NODE_DATA(to_insert)->
234                                     cur_operator != '!') {
235                                         GNode *tmp_node = NULL;
236
237                                         node_data =
238                                             g_malloc0(sizeof
239                                                       (calculator_node_data_t));
240                                         node_data->cur_operator = 'x';
241                                         node_data->negative_flag = 1;
242                                         node_data->operator_type =
243                                             OPERATOR_TYPE_BINARY;
244                                         node_data->node_calcu_priority =
245                                             CALCULATOR_CALCULATE_PRIORITY_MIDDLE;
246                                         tmp_node = g_node_new(node_data);
247
248                                         __calculator_calculate_insert_node
249                                             (out_tree, tmp_node, const_node);
250                                 } else  //(CALCULATOR_GET_NODE_DATA(to_insert)->cur_operator == '!')
251                                 {
252                                         g_node_insert(to_insert, -1,
253                                                       const_node);
254                                         CALCULATOR_GET_NODE_DATA(to_insert)->
255                                             children_num++;
256                                 }
257                         }
258
259                         g_node_insert(*out_tree, -1, to_insert);
260                         CALCULATOR_GET_NODE_DATA(*out_tree)->children_num++;
261                 }
262
263         }
264
265         *out_tree = to_insert;
266         return TRUE;
267 }
268
269 /**
270 * @describe
271 *
272 *
273 * @param    node
274 * @param    data
275 * @return    gboolean
276 * @exception
277 */
278 static gboolean
279 __calculator_tree_destroy_traverse_func(GNode * node, gpointer data)
280 {
281         if (CALCULATOR_GET_NODE_DATA(node)) {
282                 g_free(CALCULATOR_GET_NODE_DATA(node));
283         }
284         g_node_destroy(node);
285         return FALSE;
286 }
287
288 /**
289 * @describe
290 *
291 *
292 * @param    tree
293 * @return    gboolean
294 * @exception
295 */
296 static gboolean __calculator_tree_destroy_all(GNode ** tree)
297 {
298         guint depth = 0;
299         GNode *root = NULL;
300
301         if (*tree) {
302                 root = g_node_get_root(*tree);
303                 depth = g_node_max_height(root);
304                 g_node_traverse(root, G_POST_ORDER, G_TRAVERSE_ALL, depth,
305                                 __calculator_tree_destroy_traverse_func, NULL);
306
307                 *tree = NULL;
308         }
309         return TRUE;
310 }
311
312 /**
313 * @describe
314 *
315 *
316 * @param    result
317 * @param    error_msg
318 * @return    gboolean
319 * @exception
320 */
321 static gboolean __calculator_check_overflow(double result, char *error_msg)
322 {
323         if ((result > CALCULATOR_MAX_RESULT_SUM2)
324             || (result < CALCULATOR_MIN_RESULT_SUM2)) {
325                 strcat(error_msg, CALC_MSG_OUT_OF_RANGE);
326                 return FALSE;
327         }
328         return TRUE;
329 }
330
331 /**
332 * @describe
333 *   add parenthesis between function and paremeter.
334 *
335 * @param    exp
336 * @param    func
337 * @return    void
338 * @exception
339 */
340 static void __calculator_expression_add_parenthesis(char *exp, const char *func)
341 {
342         char *p = exp;
343         char *digit = "0123456789.";
344
345         while ((p = strstr(p, func)) != NULL) {
346                 p = p + strlen(func);
347                 if (*p != '(') {
348                         int l = strspn(p, digit);
349                         string_insert(exp, p - exp, "(");
350                         string_insert(exp, p - exp + l + 1, ")");
351                         p += l + 2;
352                 }
353         }
354 }
355
356 /**
357 * @describe
358 *   If sin/cos/tan function omitted parenthesis, add it
359 *
360 * @param    exp
361 * @return    void
362 * @exception
363 */
364 static void __calculator_expression_tri_func_parenthesis(char *exp)
365 {
366         __calculator_expression_add_parenthesis(exp, "sin");
367         __calculator_expression_add_parenthesis(exp, "cos");
368         __calculator_expression_add_parenthesis(exp, "tan");
369 }
370
371 /**
372 * @describe
373 *   record every matching parentheses position
374 *
375 * @param    string
376 * @param    end_pos
377 * @param    error_msg
378 * @return    bool
379 * @exception
380 */
381 static bool
382 __calculator_calculate_formula_scan(char *string, int *end_idx, char *error_msg)
383 {
384         CONV_FUNC_IN();
385         gint i = 0;
386         gchar *p = NULL;
387
388         p = string;
389         memset(g_parentheses_data, 0x0, sizeof(g_parentheses_data));
390
391         __calculator_expression_tri_func_parenthesis(string);
392
393         while (*p != '\0') {
394                 if (*p == '(') {
395                         while (g_parentheses_data[i].start_pos) {
396                                 i++;
397                         }
398                         g_parentheses_data[i].start_pos = p;
399                 }
400                 if (*p == ')') {
401                         while (g_parentheses_data[i].end_pos) {
402                                 i--;
403                         }
404                         if (g_parentheses_data[i].start_pos) {
405                                 g_parentheses_data[i].end_pos = p;
406                         }
407                 }
408                 p++;
409         }
410         *end_idx = p - 1 - string;
411         CONV_FUNC_OUT();
412         return TRUE;
413 }
414
415 /**
416 * @describe
417 *
418 *
419 * @param    n
420 * @param    err_msg
421 * @return    double
422 * @exception
423 */
424 static double __calculator_calculate_factorial(double n, char *err_msg)
425 {
426         if (n < 0) {
427                 strcat(err_msg, CALC_MSG_INVALID_FAC);
428                 return -1;
429         } else if (n >= 30) {
430                 strcat(err_msg, CALC_MSG_OUT_OF_RANGE);
431                 return -1;
432         }
433
434         double i = 0;
435         double result = 1;
436         for (i = 2; i <= n; ++i) {
437                 result *= i;
438         }
439         return result;
440 }
441
442 /**
443 * @describe
444 *   Judge the op is a operator, if yes, give fucntion type
445 *
446 * @param    op
447 * @param    function
448 * @return    gboolean
449 * @exception
450 */
451 static gboolean __calculator_util_get_operator(char *op, function_t * function)
452 {
453         gint i = 0;
454         gboolean ret = FALSE;
455         if ((*op == decimal_ch) || (*op == '(') || (*op == ')')) {
456                 ret = FALSE;
457         } else if (isdigit(*op)) {
458                 ret = FALSE;
459         } else if ((*op == '+') || (*op == '-') || (*op == 'x') || (*op == '/')) {
460                 function->category = FUNCTION_POSTFIX;
461                 function->function_char = *op;
462                 function->func_name = NULL;
463                 function->func_string = NULL;
464                 function->has_parentheses = FALSE;
465                 function->op_type = OPERATOR_TYPE_BINARY;
466                 if ((*op == '+') || (*op == '-')) {
467                         function->priority = CALCULATOR_CALCULATE_PRIORITY_LOW;
468                 } else {
469                         function->priority =
470                             CALCULATOR_CALCULATE_PRIORITY_MIDDLE;
471                 }
472                 function->str_len = 1;
473                 ret = TRUE;
474         } else {
475                 for (i = 0; i < CALCULATOR_MAX_FUNC_NUMBER; i++) {
476                         if (!strncmp
477                             (op, g_functions[i].func_string,
478                              strlen(g_functions[i].func_string))) {
479                                 memcpy(function, &g_functions[i],
480                                        sizeof(function_t));
481                                 ret = TRUE;
482                                 break;
483                         }
484                 }
485         }
486         return ret;
487 }
488
489 /* search function, if have, return TRUE and get the length of current function;else return FALSE */
490 gboolean __calculator_search_function(char *op, int* len)
491 {
492         gint i = 0;
493         gboolean ret = FALSE;
494         for (i = 0; i < CALCULATOR_MAX_FUNC_NUMBER; i++) {
495                 if (!strncmp
496                     (op, g_functions[i].func_string,
497                      strlen(g_functions[i].func_string))) {
498                         ret = TRUE;
499                         if(len){
500                                 *len = strlen(g_functions[i].func_string);
501                         }
502                         break;
503                 }
504         }
505         return ret;
506 }
507
508 /**
509 * @describe
510 *
511 *
512 * @param    pos
513 * @return    calculator_parentheses_data_t*
514 * @exception
515 */
516 static calculator_parentheses_data_t
517     *__calculator_calculate_get_parentheses_info(gchar * pos)
518 {
519         calculator_parentheses_data_t *found = NULL;
520         gint i = 0;
521
522         while ((g_parentheses_data[i].start_pos) ||
523                (g_parentheses_data[i].end_pos)) {
524                 if (g_parentheses_data[i].start_pos == pos) {
525                         found = &g_parentheses_data[i];
526                         break;
527                 } else if (g_parentheses_data[i].end_pos == pos) {
528                         found = &g_parentheses_data[i];
529                         break;
530                 }
531                 i++;
532         }
533
534         return found;
535 }
536
537 /**
538 * @describe
539 *
540 *
541 * @param    tmp_result
542 * @param    out_tree
543 * @param    start_pos
544 * @param    end_pos
545 * @param    error_msg
546 * @return    gboolean
547 * @exception
548 */
549 static gboolean
550 __calculator_calculate_formula_parse(double *tmp_result, GNode ** out_tree,
551                                      char *start_pos, int end_idx,
552                                      char *error_msg)
553 {
554         CONV_FUNC_IN();
555         char *end_pos = start_pos + end_idx;
556         gchar *p = NULL;
557         gchar *q = NULL;
558         gchar tmp[MAX_RESULT_LENGTH];
559         gint i = 0;
560         gdouble factor = 0;
561         calculator_state_t calculator_state = CALCULATOR_OPERAND_INPUT;
562         calculator_node_data_t *node_data = NULL;
563         GNode *tree = NULL;
564         GNode *new_node = NULL;
565         GNode *last_node = NULL;        //to proc parentheses
566         calculator_parentheses_data_t *p_data = NULL;
567         gint negative_sign = 1;
568         function_t function = { 0 };
569
570         memset(tmp, 0x00, sizeof(tmp));
571
572         if (start_pos > end_pos) {
573                 strcat(error_msg, CALC_MSG_SYNTAX_ERROR);
574                 return FALSE;
575         }
576 /* @ attention
577      This is redundant comment.
578      Its only use is for Klocwork testing.
579      The comment rete should passed 25%.
580      But we have only one day to do this work.
581      So, sorry, I will delete this comment and add useful comment later.
582 */
583
584         /* Scan from start to end of string */
585         for (p = start_pos; p <= end_pos;) {
586                 q = p;          /* Point to start of string */
587                 if (q != NULL && __calculator_util_get_operator(q, &function))  //('.'::'('::')') and digits are four exceptions
588                 {
589                         oper_num++;
590                         if (oper_num > MAX_OPERATOR_NUM) {
591                                 strcat(error_msg, CALC_MSG_MAX_OP);
592                                 return false;
593                         }
594
595                         p = q + function.str_len;       /* Shift */
596                         if ((NULL == p)
597                             && (function.category != FUNCTION_CONSTANT)) {
598                                 return false;
599                         }
600                         if ((NULL != p) && (*p == decimal_ch)) {
601                                 printf("p:%s\n", p);
602                                 strcat(error_msg, CALC_MSG_SYNTAX_ERROR);
603                                 return false;
604                         }
605                         calculator_state = CALCULATOR_OPERATOR_INPUT;
606                         if (i != 0)     //save the before operator,create a node.such as 345sin(),save 345
607                         {
608                                 factor = atof(tmp);
609                                 memset(tmp, 0x00, sizeof(tmp));
610                                 i = 0;
611
612                                 node_data =
613                                     g_malloc0(sizeof(calculator_node_data_t));
614                                 node_data->tmp_result = factor;
615
616                                 node_data->negative_flag = 1;
617                                 node_data->negative_flag *= negative_sign;
618                                 new_node = g_node_new(node_data);
619                                 negative_sign = 1;
620                         } else {
621                                 if (!new_node)  //no leaf node before, first factor's "+/-" sign allowed.
622                                 {
623                                         if (((function.op_type ==
624                                               OPERATOR_TYPE_BINARY)
625                                              && (function.function_char != '+')
626                                              && (function.function_char != '-'))
627                                             ||
628                                             ((function.op_type ==
629                                               OPERATOR_TYPE_UNARY)
630                                              && (function.category ==
631                                                  FUNCTION_POSTFIX))) {
632                                                 PLOG("Line:%d", __LINE__);
633                                                 strcat(error_msg,
634                                                        _("Syntax error"));
635                                                 return FALSE;
636                                         } else if (function.function_char ==
637                                                    '-') {
638                                                 negative_sign = -1;
639                                                 continue;
640                                         }
641                                 }
642                         }
643 /* @ attention
644      This is redundant comment.
645      Its only use is for Klocwork testing.
646      The comment rete should passed 25%.
647      But we have only one day to do this work.
648      So, sorry, I will delete this comment and add useful comment later.
649 */
650
651                         if (function.category == FUNCTION_CONSTANT)     //Pi, e
652                         {
653                                 if (new_node)   //have the operator like 345,now it will 345*Pi
654                                 {
655                                         node_data =
656                                             g_malloc0(sizeof
657                                                       (calculator_node_data_t));
658                                         node_data->cur_operator = 'x';
659                                         node_data->negative_flag = 1;
660                                         node_data->operator_type =
661                                             OPERATOR_TYPE_BINARY;
662                                         node_data->node_calcu_priority =
663                                             CALCULATOR_CALCULATE_PRIORITY_MIDDLE;
664                                         tree = g_node_new(node_data);
665
666                                         if (last_node == NULL)  //first node
667                                         {
668                                                 g_node_insert(tree, -1,
669                                                               new_node);
670                                                 CALCULATOR_GET_NODE_DATA(tree)->
671                                                     children_num++;
672                                         } else {
673                                                 if (CALCULATOR_GET_NODE_DATA
674                                                     (last_node)->children_num >
675                                                     CALCULATOR_GET_NODE_DATA
676                                                     (last_node)->
677                                                     operator_type) {
678                                                         PLOG("Line:%d",
679                                                              __LINE__);
680                                                         strcat(error_msg,
681                                                                _
682                                                                ("Syntax error"));
683                                                         return FALSE;
684                                                 }
685                                                 __calculator_calculate_insert_node
686                                                     (&last_node, tree,
687                                                      new_node);
688                                         }
689                                         new_node = NULL;
690                                         last_node = tree;
691
692                                 }       //Pi will like a leaf
693                                 node_data =
694                                     g_malloc0(sizeof(calculator_node_data_t));
695                                 if (function.function_char == 'p') {
696                                         node_data->tmp_result = PI;
697                                 } else if (function.function_char == 'e') {
698                                         node_data->tmp_result = EXPONENT;
699                                 }
700                                 node_data->cur_operator =
701                                     function.function_char;
702                                 node_data->node_calcu_priority =
703                                     function.priority;
704                                 node_data->negative_flag = 1;
705                                 node_data->negative_flag *= negative_sign;
706                                 new_node = g_node_new(node_data);
707                                 negative_sign = 1;
708                                 continue;
709                         } else if (function.category == FUNCTION_PREFIX)        //sin()
710                         {
711                                 if (!last_node) //first node
712                                 {
713                                         if (new_node) {
714                                                 node_data =
715                                                     g_malloc0(sizeof
716                                                               (calculator_node_data_t));
717                                                 node_data->cur_operator = 'x';
718                                                 node_data->negative_flag = 1;
719                                                 node_data->operator_type =
720                                                     OPERATOR_TYPE_BINARY;
721                                                 node_data->node_calcu_priority =
722                                                     CALCULATOR_CALCULATE_PRIORITY_MIDDLE;
723                                                 tree = g_node_new(node_data);
724
725                                                 g_node_insert(tree, -1,
726                                                               new_node);
727                                                 CALCULATOR_GET_NODE_DATA(tree)->
728                                                     children_num++;
729
730                                                 last_node = tree;
731                                                 new_node = NULL;
732                                         }
733                                 }
734
735                         }
736
737                         node_data = g_malloc0(sizeof(calculator_node_data_t));
738                         node_data->cur_operator = function.function_char;
739                         node_data->node_calcu_priority = function.priority;
740                         node_data->operator_type = function.op_type;
741                         node_data->negative_flag = 1;
742                         tree = g_node_new(node_data);
743
744                         if (last_node == NULL)  //first node
745                         {
746                                 if (new_node) {
747                                         g_node_insert(tree, -1, new_node);
748                                         CALCULATOR_GET_NODE_DATA(tree)->
749                                             children_num++;
750                                 }
751                         } else {
752                                 if (CALCULATOR_GET_NODE_DATA(last_node)->
753                                     children_num >
754                                     CALCULATOR_GET_NODE_DATA(last_node)->
755                                     operator_type) {
756                                         strcat(error_msg,
757                                                CALC_MSG_SYNTAX_ERROR);
758                                         return FALSE;
759                                 }
760                                 __calculator_calculate_insert_node(&last_node,
761                                                                    tree,
762                                                                    new_node);
763                         }
764                         last_node = tree;
765                         new_node = NULL;
766                 } else {
767                         p++;    /* Shift */
768                 }
769
770 /* @ attention
771      This is redundant comment.
772      Its only use is for Klocwork testing.
773      The comment rete should passed 25%.
774      But we have only one day to do this work.
775      So, sorry, I will delete this comment and add useful comment later.
776 */
777                 if (NULL == q) {
778                         strcat(error_msg, CALC_MSG_SYNTAX_ERROR);       //add for "6((" ,then "="
779                         return FALSE;
780                 }               //added by zhaodanni for prevent
781                 else if (*q == decimal_ch) {
782                         if (!isdigit(*p)
783                             || (calculator_state ==
784                                 CALCULATOR_OPERAND_FRACTION_INPUT)) {
785                                 strcat(error_msg, CALC_MSG_SYNTAX_ERROR);
786                                 return FALSE;
787                         } else {
788                                 calculator_state =
789                                     CALCULATOR_OPERAND_FRACTION_INPUT;
790                         }
791                         tmp[i++] = *q;
792                 } else if (*q == '(') {
793                         if (__calculator_util_get_operator(p, &function)) {
794                                 if ((function.category == FUNCTION_POSTFIX) && ((*p != '+') && (*p != '-')))    //"(*","(/", not allowed.
795                                 {
796                                         strcat(error_msg,
797                                                CALC_MSG_SYNTAX_ERROR);
798                                         return FALSE;
799                                 }
800                         }
801 /* @ attention
802      This is redundant comment.
803      Its only use is for Klocwork testing.
804      The comment rete should passed 25%.
805      But we have only one day to do this work.
806      So, sorry, I will delete this comment and add useful comment later.
807 */
808
809                         //if ((new_node) && (CALCULATOR_GET_NODE_DATA(new_node)->tmp_result == PI || CALCULATOR_GET_NODE_DATA(new_node)->tmp_result == EXPONENT))
810                         if ((new_node)
811                             &&
812                             (FLOAT_EQUAL
813                              (CALCULATOR_GET_NODE_DATA(new_node)->tmp_result,
814                               PI)
815                              || FLOAT_EQUAL(CALCULATOR_GET_NODE_DATA(new_node)->
816                                             tmp_result, EXPONENT))) {
817                                 node_data =
818                                     g_malloc0(sizeof(calculator_node_data_t));
819                                 node_data->cur_operator = 'x';
820                                 node_data->negative_flag = 1;
821                                 node_data->operator_type = OPERATOR_TYPE_BINARY;
822                                 node_data->node_calcu_priority =
823                                     CALCULATOR_CALCULATE_PRIORITY_MIDDLE;
824                                 tree = g_node_new(node_data);
825
826                                 if (last_node) {
827                                         __calculator_calculate_insert_node
828                                             (&last_node, tree, new_node);
829                                 } else {
830                                         g_node_insert(tree, -1, new_node);
831                                         CALCULATOR_GET_NODE_DATA(tree)->
832                                             children_num++;
833                                 }
834                                 last_node = tree;
835                                 new_node = NULL;
836                         }
837 /* @ attention
838      This is redundant comment.
839      Its only use is for Klocwork testing.
840      The comment rete should passed 25%.
841      But we have only one day to do this work.
842      So, sorry, I will delete this comment and add useful comment later.
843 */
844
845                         if (i != 0) {
846                                 factor = atof(tmp);
847                                 memset(tmp, 0x00, sizeof(tmp));
848                                 i = 0;
849
850                                 node_data =
851                                     g_malloc0(sizeof(calculator_node_data_t));
852                                 node_data->tmp_result = factor;
853                                 node_data->negative_flag = 1;
854                                 node_data->negative_flag *= negative_sign;
855                                 negative_sign = 1;
856                                 new_node = g_node_new(node_data);
857
858                                 node_data =
859                                     g_malloc0(sizeof(calculator_node_data_t));
860                                 node_data->cur_operator = 'x';
861                                 node_data->negative_flag = 1;
862                                 node_data->operator_type = OPERATOR_TYPE_BINARY;
863                                 node_data->node_calcu_priority =
864                                     CALCULATOR_CALCULATE_PRIORITY_MIDDLE;
865                                 tree = g_node_new(node_data);
866
867                                 if (last_node == NULL)  //first node
868                                 {
869                                         g_node_insert(tree, -1, new_node);
870                                         CALCULATOR_GET_NODE_DATA(tree)->
871                                             children_num++;
872                                 } else {
873                                         if (CALCULATOR_GET_NODE_DATA
874                                             (last_node)->children_num >
875                                             CALCULATOR_GET_NODE_DATA
876                                             (last_node)->operator_type) {
877                                                 strcat(error_msg,
878                                                        CALC_MSG_SYNTAX_ERROR);
879                                                 return FALSE;
880                                         }
881
882                                         __calculator_calculate_insert_node
883                                             (&last_node, tree, new_node);
884                                 }
885                                 last_node = tree;
886                                 new_node = NULL;
887                         }
888
889                         p_data = __calculator_calculate_get_parentheses_info(q);
890                         if (!p_data) {
891                                 strcat(error_msg, CALC_MSG_SYNTAX_ERROR);
892                                 return FALSE;
893                         }
894                         p = p_data->end_pos;
895                 } else if (*q == ')') {
896                         if (*p == decimal_ch)   //").", not allowed.
897                         {
898                                 strcat(error_msg, CALC_MSG_SYNTAX_ERROR);
899                                 return FALSE;
900                         }
901
902                         p_data = __calculator_calculate_get_parentheses_info(q);
903                         if (!p_data) {
904                                 strcat(error_msg, CALC_MSG_SYNTAX_ERROR);
905                                 return FALSE;
906                         }
907                         if (!__calculator_calculate_formula_parse
908                             (NULL, &new_node, (p_data->start_pos + 1),
909                              (p_data->end_pos - 1) - (p_data->start_pos + 1),
910                              error_msg)) {
911                                 if (new_node != NULL) {
912                                         __calculator_tree_destroy_all
913                                             (&new_node);
914                                 } else {
915                                         LOGD("current node is null\n");
916                                 }
917                                 return FALSE;
918                         }
919                         if (new_node) {
920                                 CALCULATOR_GET_NODE_DATA(new_node)->
921                                     negative_flag *= negative_sign;
922                         }
923                         negative_sign = 1;
924 /* @ attention
925      This is redundant comment.
926      Its only use is for Klocwork testing.
927      The comment rete should passed 25%.
928      But we have only one day to do this work.
929      So, sorry, I will delete this comment and add useful comment later.
930 */
931
932                         if ((*p == '(') || (isdigit(*p))) {
933                                 node_data =
934                                     g_malloc0(sizeof(calculator_node_data_t));
935                                 node_data->cur_operator = 'x';
936                                 node_data->negative_flag = 1;
937                                 node_data->operator_type = OPERATOR_TYPE_BINARY;
938                                 node_data->node_calcu_priority =
939                                     CALCULATOR_CALCULATE_PRIORITY_MIDDLE;
940                                 tree = g_node_new(node_data);
941
942                                 if (last_node == NULL)  //first node
943                                 {
944                                         if (new_node) {
945                                                 g_node_insert(tree, -1,
946                                                               new_node);
947                                                 CALCULATOR_GET_NODE_DATA(tree)->
948                                                     children_num++;
949                                         }
950                                 } else {
951                                         if (CALCULATOR_GET_NODE_DATA
952                                             (last_node)->children_num >
953                                             CALCULATOR_GET_NODE_DATA
954                                             (last_node)->operator_type) {
955                                                 strcat(error_msg,
956                                                        CALC_MSG_SYNTAX_ERROR);
957                                                 return FALSE;
958                                         }
959
960                                         __calculator_calculate_insert_node
961                                             (&last_node, tree, new_node);
962                                 }
963                                 last_node = tree;
964                                 new_node = NULL;
965                         }
966                 } else if (isdigit(*q)) {
967                         if (new_node) {
968                                 node_data =
969                                     g_malloc0(sizeof(calculator_node_data_t));
970                                 node_data->cur_operator = 'x';
971                                 node_data->negative_flag = 1;
972                                 node_data->operator_type = OPERATOR_TYPE_BINARY;
973                                 node_data->node_calcu_priority =
974                                     CALCULATOR_CALCULATE_PRIORITY_MIDDLE;
975                                 tree = g_node_new(node_data);
976
977                                 if (last_node) {
978                                         __calculator_calculate_insert_node
979                                             (&last_node, tree, new_node);
980                                 } else {
981                                         g_node_insert(tree, -1, new_node);
982                                         CALCULATOR_GET_NODE_DATA(tree)->
983                                             children_num++;
984                                 }
985                                 last_node = tree;
986                                 new_node = NULL;
987                         }
988                         calculator_state = CALCULATOR_OPERAND_INPUT;
989                         tmp[i++] = *q;
990                 }/*for unvalid input ,such as "clipborad"*/
991                 else if ((*q != '+') && (*q != '-') && (*q != 'x')
992                          && (*q != '/')) {
993                         if (!__calculator_search_function(q, NULL)) {
994                                 printf("q=%s,line=%d\n", q, __LINE__);
995                                 strcat(error_msg, "invalid input");
996                                 return FALSE;
997                         }
998                 }
999         }
1000 /* @ attention
1001      This is redundant comment.
1002      Its only use is for Klocwork testing.
1003      The comment rete should passed 25%.
1004      But we have only one day to do this work.
1005      So, sorry, I will delete this comment and add useful comment later.
1006 */
1007
1008         if (i != 0)             //last digit number
1009         {
1010                 //if ((new_node) && (CALCULATOR_GET_NODE_DATA(new_node)->tmp_result == PI || CALCULATOR_GET_NODE_DATA(new_node)->tmp_result == EXPONENT))
1011                 if ((new_node)
1012                     &&
1013                     (FLOAT_EQUAL
1014                      (CALCULATOR_GET_NODE_DATA(new_node)->tmp_result, PI)
1015                      || FLOAT_EQUAL(CALCULATOR_GET_NODE_DATA(new_node)->
1016                                     tmp_result, EXPONENT))) {
1017                         node_data = g_malloc0(sizeof(calculator_node_data_t));
1018                         node_data->cur_operator = 'x';
1019                         node_data->negative_flag = 1;
1020                         node_data->operator_type = OPERATOR_TYPE_BINARY;
1021                         node_data->node_calcu_priority =
1022                             CALCULATOR_CALCULATE_PRIORITY_MIDDLE;
1023                         tree = g_node_new(node_data);
1024
1025                         if (last_node) {
1026                                 __calculator_calculate_insert_node(&last_node,
1027                                                                    tree,
1028                                                                    new_node);
1029                         } else {
1030                                 g_node_insert(tree, -1, new_node);
1031                                 CALCULATOR_GET_NODE_DATA(tree)->children_num++;
1032                         }
1033                         last_node = tree;
1034                         new_node = NULL;
1035                 }
1036
1037                 factor = atof(tmp);
1038                 memset(tmp, 0x00, sizeof(tmp));
1039                 i = 0;
1040
1041                 node_data = g_malloc0(sizeof(calculator_node_data_t));
1042                 node_data->tmp_result = factor;
1043                 node_data->negative_flag = 1;
1044                 node_data->negative_flag *= negative_sign;
1045                 negative_sign = 1;
1046                 new_node = g_node_new(node_data);
1047
1048                 if (last_node != NULL) {
1049                         if (CALCULATOR_GET_NODE_DATA(last_node)->children_num >
1050                             CALCULATOR_GET_NODE_DATA(last_node)->
1051                             operator_type) {
1052                                 strcat(error_msg, CALC_MSG_SYNTAX_ERROR);
1053                                 return FALSE;
1054                         } else {
1055                                 g_node_insert(last_node, -1, new_node);
1056                                 CALCULATOR_GET_NODE_DATA(last_node)->
1057                                     children_num++;
1058                         }
1059                         new_node = NULL;
1060                 }
1061         }
1062 /* @ attention
1063      This is redundant comment.
1064      Its only use is for Klocwork testing.
1065      The comment rete should passed 25%.
1066      But we have only one day to do this work.
1067      So, sorry, I will delete this comment and add useful comment later.
1068 */
1069
1070         if (new_node != NULL) {
1071                 CALCULATOR_GET_NODE_DATA(new_node)->negative_flag *=
1072                     negative_sign;
1073                 negative_sign = 1;
1074
1075                 if (last_node != NULL) {
1076                         if (CALCULATOR_GET_NODE_DATA(last_node)->children_num >
1077                             CALCULATOR_GET_NODE_DATA(last_node)->
1078                             operator_type) {
1079                                 strcat(error_msg, CALC_MSG_SYNTAX_ERROR);
1080                                 return FALSE;
1081                         } else {
1082                                 g_node_insert(last_node, -1, new_node);
1083                                 CALCULATOR_GET_NODE_DATA(last_node)->
1084                                     children_num++;
1085                         }
1086                 } else {
1087                         last_node = new_node;
1088                 }
1089                 new_node = NULL;
1090         }
1091         *out_tree = g_node_get_root(last_node);
1092         CONV_FUNC_OUT();
1093         return TRUE;
1094 }
1095
1096 /**
1097 * @describe
1098 *
1099 *
1100 * @param        node
1101 * @param        data
1102 * @return       gboolean
1103 * @exception
1104 */
1105 static gboolean
1106 __calculator_calculate_exec_traverse_func(GNode * node, gpointer data)
1107 {
1108         gdouble operand0, operand1 = 0.0;
1109         char *error_msg = (char *)data;
1110
1111 /*
1112      This is redundant comment.
1113      Its only use is for Klocwork testing.
1114      The comment rete should passed 25%.
1115      But we have only one day to do this work.
1116      So, sorry, I will delete this comment and add useful comment later.
1117 */
1118
1119         if (CALCULATOR_GET_NODE_DATA(node)->children_num !=
1120             CALCULATOR_GET_NODE_DATA(node)->operator_type) {
1121                 strcat(error_msg, CALC_MSG_NUM_AFTER_OP);
1122                 return TRUE;    //break the recursion
1123         }
1124
1125         operand0 =
1126             CALCULATOR_GET_NODE_DATA(node->children)->tmp_result *
1127             CALCULATOR_GET_NODE_DATA(node->children)->negative_flag;
1128         CALCULATOR_GET_NODE_DATA(node->children)->negative_flag = 1;
1129
1130         if (CALCULATOR_GET_NODE_DATA(node)->operator_type ==
1131             OPERATOR_TYPE_BINARY) {
1132                 operand1 =
1133                     CALCULATOR_GET_NODE_DATA(node->children->next)->tmp_result *
1134                     CALCULATOR_GET_NODE_DATA(node->children->next)->
1135                     negative_flag;
1136                 CALCULATOR_GET_NODE_DATA(node->children->next)->negative_flag =
1137                     1;
1138         }
1139
1140 /* @ describe
1141     This is redundant comment.
1142     Its only use is for Klocwork testing.
1143     The comment rete should passed 25%.
1144     But we have only one day to do this work.
1145     So, sorry, I will delete this comment and add useful comment later.
1146 */
1147         switch (CALCULATOR_GET_NODE_DATA(node)->cur_operator) {
1148         case '+':
1149                 CALCULATOR_GET_NODE_DATA(node)->tmp_result =
1150                     operand0 + operand1;
1151                 //calculator_calculate_truncate_result(&(CALCULATOR_GET_NODE_DATA(node)->tmp_result));
1152                 break;
1153         case '-':
1154                 CALCULATOR_GET_NODE_DATA(node)->tmp_result =
1155                     operand0 - operand1;
1156                 //calculator_calculate_truncate_result(&(CALCULATOR_GET_NODE_DATA(node)->tmp_result));
1157                 break;
1158         case 'x':
1159                 CALCULATOR_GET_NODE_DATA(node)->tmp_result =
1160                     operand0 * operand1;
1161                 //calculator_calculate_truncate_result(&(CALCULATOR_GET_NODE_DATA(node)->tmp_result));
1162                 break;
1163         case '/':
1164                 if (FLOAT_EQUAL(operand1, 0)) {
1165                         strcat(error_msg, CALC_MSG_DIVIDE_BY_ZERO);
1166                         return TRUE;    //break the recursion
1167                 } else {
1168                         CALCULATOR_GET_NODE_DATA(node)->tmp_result =
1169                             operand0 / operand1;
1170                         //calculator_calculate_truncate_result(&(CALCULATOR_GET_NODE_DATA(node)->tmp_result));
1171                 }
1172                 break;
1173 /* @ attention
1174      This is redundant comment.
1175      Its only use is for Klocwork testing.
1176      The comment rete should passed 25%.
1177      But we have only one day to do this work.
1178      So, sorry, I will delete this comment and add useful comment later.
1179 */
1180
1181         case '^':
1182                 if (operand0 < 0) {
1183                         gdouble power = 0.0;
1184                         power = floor(operand1);
1185                         if (!FLOAT_EQUAL(power, operand1))      //operand1 is not an integer
1186                         {
1187                                 strcat(error_msg, CALC_MSG_INVALID_XY);
1188                                 return TRUE;
1189                         }
1190                 }
1191                 CALCULATOR_GET_NODE_DATA(node)->tmp_result =
1192                     pow(operand0, operand1);
1193                 if (!__calculator_check_overflow
1194                     (CALCULATOR_GET_NODE_DATA(node)->tmp_result, error_msg)) {
1195                         return TRUE;
1196                 }
1197                 //calculator_calculate_truncate_result(&(CALCULATOR_GET_NODE_DATA(node)->tmp_result));
1198                 break;
1199         case '!':
1200                 if (operand0 < 0) {
1201                         gdouble power = 0.0;
1202                         power = floor(operand1);
1203                         if (!FLOAT_EQUAL(power, operand1))      //operand1 is not an integer
1204                         {
1205                                 strcat(error_msg, CALC_MSG_INVALID_FAC);
1206                                 return TRUE;
1207                         }
1208                 }
1209                 if (strlen(error_msg) != 0) {
1210                         return TRUE;
1211                 }
1212                 CALCULATOR_GET_NODE_DATA(node)->tmp_result =
1213                     __calculator_calculate_factorial(operand0, error_msg);
1214                 if (strlen(error_msg) != 0) {
1215                         return TRUE;
1216                 }
1217                 //calculator_calculate_truncate_result(&(CALCULATOR_GET_NODE_DATA(node)->tmp_result));
1218                 break;
1219
1220         case 'L':
1221                 if (operand0 < 0) {
1222                         strcat(error_msg, CALC_MSG_INVALID_LN);
1223                         return TRUE;
1224                 } else if (FLOAT_EQUAL(operand0, 0)) {
1225                         strcat(error_msg, CALC_MSG_INVALID_LN);
1226                         return TRUE;
1227                 }
1228
1229                 CALCULATOR_GET_NODE_DATA(node)->tmp_result = log(operand0);
1230                 if (!__calculator_check_overflow
1231                     (CALCULATOR_GET_NODE_DATA(node)->tmp_result, error_msg)) {
1232                         return TRUE;
1233                 }
1234                 //calculator_calculate_truncate_result(&(CALCULATOR_GET_NODE_DATA(node)->tmp_result));
1235                 break;
1236         case 'q':
1237                 if (operand0 < 0) {
1238                         strcat(error_msg, CALC_MSG_INVALID_SQUARE);
1239                         return TRUE;
1240                 }
1241                 CALCULATOR_GET_NODE_DATA(node)->tmp_result = sqrt(operand0);
1242                 if (!__calculator_check_overflow
1243                     (CALCULATOR_GET_NODE_DATA(node)->tmp_result, error_msg)) {
1244                         return TRUE;
1245                 }
1246                 //calculator_calculate_truncate_result(&(CALCULATOR_GET_NODE_DATA(node)->tmp_result));
1247                 break;
1248         case 'E':
1249                 CALCULATOR_GET_NODE_DATA(node)->tmp_result = exp(operand0);
1250                 if (!__calculator_check_overflow
1251                     (CALCULATOR_GET_NODE_DATA(node)->tmp_result, error_msg)) {
1252                         return TRUE;
1253                 }
1254                 //calculator_calculate_truncate_result(&(CALCULATOR_GET_NODE_DATA(node)->tmp_result));
1255                 break;
1256
1257         case 's':
1258                 CALCULATOR_GET_NODE_DATA(node)->tmp_result =
1259                     sin(operand0 * RADIAN_FACTOR);
1260                 if (!__calculator_check_overflow
1261                     (CALCULATOR_GET_NODE_DATA(node)->tmp_result, error_msg)) {
1262                         return TRUE;
1263                 }
1264                 //calculator_calculate_truncate_result(&(CALCULATOR_GET_NODE_DATA(node)->tmp_result));
1265                 break;
1266         case 'c':
1267                 CALCULATOR_GET_NODE_DATA(node)->tmp_result =
1268                     cos(operand0 * RADIAN_FACTOR);
1269                 if (!__calculator_check_overflow
1270                     (CALCULATOR_GET_NODE_DATA(node)->tmp_result, error_msg)) {
1271                         return TRUE;
1272                 }
1273                 //calculator_calculate_truncate_result(&(CALCULATOR_GET_NODE_DATA(node)->tmp_result));
1274                 break;
1275         case 't':
1276                 if (FLOAT_EQUAL(fmod(operand0, 180), 90) || FLOAT_EQUAL(fmod(operand0, 180), -90))      //revise by bfl
1277                 {
1278                         strcat(error_msg, CALC_MSG_INVALID_TAN);
1279                         return TRUE;
1280                 }
1281
1282                 CALCULATOR_GET_NODE_DATA(node)->tmp_result =
1283                     tan(operand0 * RADIAN_FACTOR);
1284                 if (!__calculator_check_overflow
1285                     (CALCULATOR_GET_NODE_DATA(node)->tmp_result, error_msg)) {
1286                         return TRUE;
1287                 }
1288                 //calculator_calculate_truncate_result(&(CALCULATOR_GET_NODE_DATA(node)->tmp_result));
1289                 break;
1290 /* @ attention
1291      This is redundant comment.
1292      Its only use is for Klocwork testing.
1293      The comment rete should passed 25%.
1294      But we have only one day to do this work.
1295      So, sorry, I will delete this comment and add useful comment later.
1296 */
1297
1298         case 'l':
1299                 if (operand0 < 0) {
1300                         strcat(error_msg, CALC_MSG_INVALID_LOG);
1301                         return TRUE;
1302                 } else if (FLOAT_EQUAL(operand0, 0)) {
1303                         strcat(error_msg, CALC_MSG_INVALID_LOG);
1304                         return TRUE;
1305                 }
1306                 CALCULATOR_GET_NODE_DATA(node)->tmp_result = log10(operand0);
1307                 if (!__calculator_check_overflow
1308                     (CALCULATOR_GET_NODE_DATA(node)->tmp_result, error_msg)) {
1309                         return TRUE;
1310                 }
1311                 //calculator_calculate_truncate_result(&(CALCULATOR_GET_NODE_DATA(node)->tmp_result));
1312                 break;
1313         case 'b':
1314                 CALCULATOR_GET_NODE_DATA(node)->tmp_result = fabs(operand0);
1315                 if (!__calculator_check_overflow
1316                     (CALCULATOR_GET_NODE_DATA(node)->tmp_result, error_msg)) {
1317                         return TRUE;
1318                 }
1319                 //calculator_calculate_truncate_result(&(CALCULATOR_GET_NODE_DATA(node)->tmp_result));
1320                 break;
1321
1322         case '2':
1323                 CALCULATOR_GET_NODE_DATA(node)->tmp_result = pow(2, operand0);
1324                 if (!__calculator_check_overflow
1325                     (CALCULATOR_GET_NODE_DATA(node)->tmp_result, error_msg)) {
1326                         return TRUE;
1327                 }
1328                 //calculator_calculate_truncate_result(&(CALCULATOR_GET_NODE_DATA(node)->tmp_result));
1329                 break;
1330
1331         default:
1332                 break;
1333         }
1334
1335 /* @ describe
1336     This is redundant comment.
1337     Its only use is for Klocwork testing.
1338     The comment rete should passed 25%.
1339     But we have only one day to do this work.
1340     So, sorry, I will delete this comment and add useful comment later.
1341 */
1342
1343         CALCULATOR_GET_NODE_DATA(node)->tmp_result *=
1344             CALCULATOR_GET_NODE_DATA(node)->negative_flag;
1345         CALCULATOR_GET_NODE_DATA(node)->negative_flag = 1;
1346
1347         return FALSE;
1348 }
1349
1350 /**
1351 * @describe
1352 *
1353 *
1354 * @param    tree
1355 * @param    result
1356 * @param    error_msg
1357 * @return    gboolean
1358 * @exception
1359 */
1360 static gboolean
1361 __calculator_calculate_exec(GNode * tree, double **result, char *error_msg)
1362 {
1363         guint depth = 0;
1364         depth = g_node_max_height(tree);
1365
1366         if (depth < 1) {
1367                 strcat(error_msg, CALC_MSG_SYNTAX_ERROR);
1368                 return FALSE;   //break the recursion
1369         } else if (depth == 1) {
1370                 **result = CALCULATOR_GET_NODE_DATA(tree)->tmp_result;
1371                 **result *= CALCULATOR_GET_NODE_DATA(tree)->negative_flag;
1372                 return TRUE;
1373         }
1374
1375 /* @ describe
1376     This is redundant comment.
1377     Its only use is for Klocwork testing.
1378     The comment rete should passed 25%.
1379     But we have only one day to do this work.
1380     So, sorry, I will delete this comment and add useful comment later.
1381 */
1382         g_node_traverse(tree,
1383                         G_POST_ORDER,
1384                         G_TRAVERSE_NON_LEAFS,
1385                         depth,
1386                         __calculator_calculate_exec_traverse_func,
1387                         (gpointer) error_msg);
1388
1389         if (strlen(error_msg) > 0) {
1390                 return FALSE;
1391         } else {
1392                 **result = CALCULATOR_GET_NODE_DATA(tree)->tmp_result;
1393         }
1394         return TRUE;
1395 }
1396
1397 /**
1398 * @describe
1399 *
1400 *
1401 * @param    tmp_result
1402 * @return    gboolean
1403 * @exception
1404 */
1405
1406 #if 0
1407 /* @ attention
1408     This is redundant comment.
1409     Its only use is for Klocwork testing.
1410     The comment rete should passed 25%.
1411     But we have only one day to do this work.
1412     So, sorry, I will delete this comment and add useful comment later.
1413 */
1414 /*
1415 bool calculator_calculate_truncate_result(double* tmp_result)
1416 {
1417
1418         return TRUE;
1419 }
1420 */
1421 #endif
1422
1423 /**
1424 * @describe
1425 *
1426 *
1427 * @param    szInputString
1428 * @return    int
1429 * @exception
1430 */
1431 int calculator_get_open_braket(const char *szInputString)
1432 {
1433         int nReversIndex = strlen(szInputString) - 1;
1434         int nOpenCnt = 0;
1435         int nCloseCnt = 0;
1436
1437         while (nReversIndex >= 0) {
1438                 if (szInputString[nReversIndex] == '(') {
1439                         nOpenCnt++;
1440                 } else if (szInputString[nReversIndex] == ')') {
1441                         nCloseCnt++;
1442                 }
1443                 nReversIndex--;
1444         }
1445         return (nOpenCnt - nCloseCnt);
1446 }
1447
1448 /**
1449 * @describe
1450 *
1451 *
1452 * @param    szInput
1453 * @param    [out]pDigitCnt : count of digit before point(.)
1454 * @param    [out]pPointCnt: count of digit after point(.)
1455 * @return    int
1456 * @exception
1457 */
1458 bool calculator_get_digits_number(char *szInput, int *pDigitCnt, int *pPointCnt)
1459 {
1460         int nLen = strlen(szInput);
1461         int nIndex;
1462
1463         int nTempCnt = 0;
1464         int nTempCntb = 0;
1465
1466         *pDigitCnt = 0;
1467         *pPointCnt = 0;
1468
1469 /* @ describe
1470     This is redundant comment.
1471     Its only use is for Klocwork testing.
1472     The comment rete should passed 25%.
1473     But we have only one day to do this work.
1474     So, sorry, I will delete this comment and add useful comment later.
1475 */
1476         if (nLen > 0) {
1477                 for (nIndex = nLen - 1; nIndex >= 0; nIndex--) {
1478                         if (isdigit(szInput[nIndex])) {
1479                                 nTempCnt++;
1480                         } else if (szInput[nIndex] == decimal_ch) {
1481                                 *pPointCnt = nTempCnt;
1482                                 nTempCnt = 0;
1483                                 break;
1484                         }
1485                 }
1486                 for (nIndex = 0; nIndex < nLen; nIndex++) {
1487                         if (isdigit(szInput[nIndex])) {
1488                                 nTempCntb++;
1489                         } else if (szInput[nIndex] == decimal_ch) {
1490                                 *pDigitCnt = nTempCntb;
1491                                 break;
1492                         }
1493                 }
1494                 //*pDigitCnt = nTempCntb;
1495         }
1496         return true;
1497 }
1498
1499 /* @ describe
1500     This is redundant comment.
1501     Its only use is for Klocwork testing.
1502     The comment rete should passed 25%.
1503     But we have only one day to do this work.
1504     So, sorry, I will delete this comment and add useful comment later.
1505 */
1506
1507 /**
1508 * @describe
1509 *
1510 *
1511 * @param    str
1512 * @param    error_msg
1513 * @return    bool
1514 * @exception
1515 */
1516 bool calculator_expression_length_check(char *str, char *error_msg)
1517 {
1518         int is_digit = 0, has_dot = 0;
1519         int idx = 0, nCount = 0, nDigitCnt = 0, nPointCnt = 0;
1520         char *p = NULL;
1521         char c;
1522
1523 #if 0
1524 /*
1525
1526         if(strlen(str) > CALCULATOR_MAX_INPUT_DIGIT_NUMBER_POR)
1527         {
1528                 strcat(error_msg, CALC_MSG_MAX_INPUT);
1529                 return FALSE;
1530         }
1531 */
1532 #endif
1533
1534         p = str;
1535         while (idx < strlen(str)) {
1536                 c = p[idx];
1537
1538                 if (isdigit(c)) {
1539                         if (is_digit == 0) {
1540                                 is_digit = 1;
1541
1542                                 nDigitCnt = 1;
1543                                 nCount = 1;
1544                         } else {
1545                                 nCount++;
1546                                 if (nCount > MAX_NUM_LENGTH) {
1547                                         strcat(error_msg, CALC_MSG_MAX_DIGIT);
1548                                         return FALSE;
1549                                 }
1550
1551                                 if (has_dot == 0) {
1552                                         nDigitCnt++;
1553                                 } else {
1554                                         nPointCnt++;
1555 /* @ attention
1556     This is redundant comment.
1557     Its only use is for Klocwork testing.
1558     The comment rete should passed 25%.
1559     But we have only one day to do this work.
1560     So, sorry, I will delete this comment and add useful comment later.
1561 */
1562 #if 0                           //YangQ
1563                                         /*
1564                                            if(nPointCnt > CALCULATORUI_MAX_INPUT_DECIMALS)
1565                                            {
1566                                            strcat(error_msg, CALC_MSG_MAX_DEC_DIGIT);
1567                                            PTAG;
1568                                            return FALSE;
1569                                            }
1570                                          */
1571 #endif
1572                                 }
1573                         }
1574                 }
1575 /* @ describe
1576     This is redundant comment.
1577     Its only use is for Klocwork testing.
1578     The comment rete should passed 25%.
1579     But we have only one day to do this work.
1580     So, sorry, I will delete this comment and add useful comment later.
1581 */
1582                 else if (c == decimal_ch) {
1583                         if (has_dot == 1) {
1584                                 strcat(error_msg, CALC_MSG_ENTRY_LIMIT);
1585                                 return FALSE;
1586                         } else {
1587                                 has_dot = 1;
1588                         }
1589                 } else {
1590                         if (is_digit == 1) {
1591                                 is_digit = 0;
1592                                 has_dot = 0;
1593                                 nCount = 0;
1594                                 nDigitCnt = 0;
1595                                 nPointCnt = 0;
1596                         }
1597                 }
1598
1599                 idx++;
1600         }
1601
1602         return TRUE;
1603
1604 }
1605
1606 /**
1607 * @describe
1608 *
1609 *
1610 * @param    string
1611 * @param    result
1612 * @param    error_msg
1613 * @return    bool
1614 * @exception
1615 */
1616 bool calculator_calculate(gchar * string, gdouble * result, char *error_msg)
1617 {
1618 #if 1                           //YangQ add.
1619         string_replace(string, "E+", "x10^");
1620         string_replace(string, "E-", "x0.1^");
1621 #endif
1622         GNode *tree = NULL;
1623         int end_idx = 0;
1624
1625         memset(error_msg, 0, sizeof(error_msg));
1626         memset(g_stack, 0, sizeof(g_stack));
1627         oper_num = 0;
1628
1629         strncpy(g_stack, string, MAX_EXPRESSION_LENGTH - 1);
1630         g_stack[MAX_EXPRESSION_LENGTH - 1] = '\0';
1631
1632         char *digit = "0123456789pe";
1633         if (strcspn(g_stack, digit) == strlen(g_stack)) {       /* no digit in expression */
1634                 strcat(error_msg, CALC_MSG_SYNTAX_ERROR);
1635                 return FALSE;
1636         }
1637
1638         if (!calculator_expression_length_check(g_stack, error_msg)) {
1639                 return FALSE;
1640         }
1641         if (!__calculator_calculate_formula_scan(g_stack, &end_idx, error_msg)) {
1642                 return FALSE;
1643         }
1644
1645         if (!__calculator_calculate_formula_parse
1646             (result, &tree, g_stack, end_idx, error_msg)) {
1647                 if (tree != NULL) {
1648                         __calculator_tree_destroy_all(&tree);
1649                 } else {
1650                         LOGD("current tree is null\n");
1651                 }
1652                 PLOG("error_msg:%s,line:%d\n", error_msg, __LINE__);
1653                 return FALSE;
1654         }
1655         if (!__calculator_calculate_exec(tree, &result, error_msg)) {
1656                 if (tree != NULL) {
1657                         __calculator_tree_destroy_all(&tree);
1658                 }
1659                 return FALSE;
1660         }
1661         if (!__calculator_check_overflow(*result, error_msg)) {
1662                 if (tree != NULL) {
1663                         __calculator_tree_destroy_all(&tree);
1664                 }
1665                 return FALSE;
1666         }
1667
1668         if (tree != NULL)
1669                 __calculator_tree_destroy_all(&tree);
1670         oper_num = 0;
1671         return TRUE;
1672 }