update devspec.en_US/1.0.general.md.
[devspec.git] / devspec.en_US / project / recutils / src / rec-sex.c
blob27f152b50b12004e68a0d8aca2086e04de0f7787
1 /* -*- mode: C -*-
3 * File: rec-sex.c
4 * Date: Sat Jan 9 20:28:43 2010
6 * GNU recutils - Record Selection Expressions.
8 */
10 /* Copyright (C) 2010-2019 Jose E. Marchesi */
12 /* This program is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation, either version 3 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include <config.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <regex.h>
31 #include <parse-datetime.h>
33 #include <rec.h>
34 #include <rec-utils.h>
35 #include <rec-sex-ast.h>
36 #include <rec-sex-parser.h>
37 #include <rec-sex-tab.h>
40 * Data structures
43 struct rec_sex_s
45 rec_sex_ast_t ast;
46 rec_sex_parser_t parser;
49 #define REC_SEX_VAL_INT 0
50 #define REC_SEX_VAL_REAL 1
51 #define REC_SEX_VAL_STR 2
53 struct rec_sex_val_s
55 int type;
57 int int_val;
58 double real_val;
59 char *str_val;
62 /* Static functions declarations. */
63 static struct rec_sex_val_s rec_sex_eval_node (rec_sex_t sex,
64 rec_record_t record,
65 rec_sex_ast_node_t node,
66 bool *status);
67 static bool rec_sex_op_real_p (struct rec_sex_val_s op1,
68 struct rec_sex_val_s op2);
71 * Public functions.
74 rec_sex_t
75 rec_sex_new (bool case_insensitive)
77 rec_sex_t new;
79 new = malloc (sizeof (struct rec_sex_s));
80 if (new)
82 /* Initialize a new parser. */
83 new->parser = rec_sex_parser_new ();
84 rec_sex_parser_set_case_insensitive (new->parser,
85 case_insensitive);
87 /* Initialize a new AST. */
88 new->ast = NULL;
91 return new;
94 void
95 rec_sex_destroy (rec_sex_t sex)
97 if (sex)
99 if (sex->parser)
101 rec_sex_parser_destroy (sex->parser);
104 if (sex->ast)
106 rec_sex_ast_destroy (sex->ast);
109 free (sex); /* yeah! :D */
113 bool
114 rec_sex_compile (rec_sex_t sex,
115 const char *expr)
117 bool res;
119 res = rec_sex_parser_run (sex->parser, expr);
120 if (res)
122 sex->ast = rec_sex_parser_ast (sex->parser);
124 return res;
127 #define EXEC_AST(RECORD) \
128 do \
130 val = rec_sex_eval_node (sex, \
131 (RECORD), \
132 rec_sex_ast_top (sex->ast), \
133 status); \
135 switch (val.type) \
137 case REC_SEX_VAL_INT: \
139 res = (val.int_val != 0); \
140 break; \
142 case REC_SEX_VAL_REAL: \
143 case REC_SEX_VAL_STR: \
145 res = false; \
146 break; \
150 while (0)
152 char *
153 rec_sex_eval_str (rec_sex_t sex,
154 rec_record_t record)
156 char *res;
157 struct rec_sex_val_s val;
158 bool status;
160 rec_sex_ast_node_unfix (rec_sex_ast_top (sex->ast));
161 val = rec_sex_eval_node (sex,
162 record,
163 rec_sex_ast_top (sex->ast),
164 &status);
166 if (!status)
168 /* Error evaluating the expression. */
169 return NULL;
172 res = NULL;
173 switch (val.type)
175 case REC_SEX_VAL_INT:
177 asprintf (&res, "%d", val.int_val);
178 break;
180 case REC_SEX_VAL_REAL:
182 asprintf (&res, "%f", val.real_val);
183 break;
185 case REC_SEX_VAL_STR:
187 res = strdup (val.str_val);
188 break;
192 return res;
195 bool
196 rec_sex_eval (rec_sex_t sex,
197 rec_record_t record,
198 bool *status)
200 bool res;
201 rec_field_t field;
202 rec_field_t wfield;
203 rec_record_t wrec;
204 rec_mset_iterator_t iter;
205 int j, nf;
206 struct rec_sex_val_s val;
208 res = false;
209 wrec = NULL;
211 rec_sex_ast_node_unfix (rec_sex_ast_top (sex->ast));
212 EXEC_AST (record);
213 if (res)
215 goto exit;
218 rec_record_reset_marks (record);
220 iter = rec_mset_iterator (rec_record_mset (record));
221 while (rec_mset_iterator_next (&iter, MSET_FIELD, (const void**) &field, NULL))
223 nf = rec_record_get_num_fields_by_name (record, rec_field_name (field));
224 if ((nf > 1)
225 && (rec_record_field_mark (record, field) == 0)
226 && (rec_sex_ast_name_p (sex->ast, rec_field_name (field), nf))
227 && (!rec_sex_ast_hash_name_p (sex->ast, rec_field_name (field))))
229 for (j = 0; j < nf; j++)
231 wfield = rec_record_get_field_by_name (record,
232 rec_field_name (field),
234 if (wrec)
236 rec_record_destroy (wrec);
239 rec_record_mark_field (record, wfield, 1);
241 wrec = rec_record_dup (record);
242 rec_record_remove_field_by_name (wrec,
243 rec_field_name (field),
244 -1); /* Delete all. */
245 rec_mset_append (rec_record_mset (wrec), MSET_FIELD, (void *) rec_field_dup (wfield), MSET_ANY);
247 EXEC_AST(wrec);
249 if (res)
251 rec_record_destroy (wrec);
252 goto exit;
258 rec_mset_iterator_free (&iter);
260 exit:
262 if (!*status)
264 res = false;
267 return res;
270 void
271 rec_sex_print_ast (rec_sex_t sex)
273 rec_sex_parser_print_ast (sex->parser);
277 * Private functions.
280 #define GET_CHILD_VAL(DEST,NUM) \
281 do \
283 (DEST) = rec_sex_eval_node (sex, \
284 record, \
285 rec_sex_ast_node_child (node, (NUM)), \
286 status); \
287 if (!*status) \
289 return res; \
292 while (0)
295 #define ATOI_VAL(DEST, VAL) \
296 do \
298 switch ((VAL).type) \
300 case REC_SEX_VAL_INT: \
302 (DEST) = (VAL).int_val; \
303 break; \
305 case REC_SEX_VAL_STR: \
307 if (strcmp ((VAL).str_val, "") == 0) \
309 (DEST) = 0; \
311 else \
313 if (!rec_atoi ((VAL).str_val, &(DEST))) \
315 *status = false; \
316 return res; \
319 break; \
323 while (0)
325 #define ATOD_VAL(DEST, VAL) \
326 do \
328 switch ((VAL).type) \
330 case REC_SEX_VAL_REAL: \
332 (DEST) = (VAL).real_val; \
333 break; \
335 case REC_SEX_VAL_INT: \
337 (DEST) = (VAL).int_val; \
338 break; \
340 case REC_SEX_VAL_STR: \
342 if (strcmp ((VAL).str_val, "") == 0) \
344 (DEST) = 0.0; \
346 else \
348 if (!rec_atod ((VAL).str_val, &(DEST))) \
350 *status = false; \
351 return res; \
354 break; \
358 while (0)
360 #define ATOTS_VAL(DEST, VAL) \
361 do \
363 switch ((VAL).type) \
365 case REC_SEX_VAL_REAL: \
367 *status = false; \
368 return res; \
369 break; \
371 case REC_SEX_VAL_INT: \
373 *status = false; \
374 return res; \
375 break; \
377 case REC_SEX_VAL_STR: \
379 if (!parse_datetime (&(DEST), (VAL).str_val, NULL))\
381 *status = false; \
382 return res; \
385 break; \
389 while (0)
391 struct rec_sex_val_s
392 rec_sex_eval_node (rec_sex_t sex,
393 rec_record_t record,
394 rec_sex_ast_node_t node,
395 bool *status)
397 struct rec_sex_val_s res = {0, 0, 0, NULL};
398 struct rec_sex_val_s child_val1 = {0, 0, 0, NULL};
399 struct rec_sex_val_s child_val2 = {0, 0, 0, NULL};
400 struct rec_sex_val_s child_val3 = {0, 0, 0, NULL};
402 *status = true;
404 switch (rec_sex_ast_node_type (node))
406 case REC_SEX_NOVAL:
408 fprintf (stderr, "Application bug: REC_SEX_NOVAL node found.\nPlease report this!\n");
409 exit (EXIT_FAILURE);
410 break;
412 /* Operations. */
413 case REC_SEX_OP_NEG:
414 case REC_SEX_OP_ADD:
416 int op1;
417 int op2;
418 double op1_real;
419 double op2_real;
421 GET_CHILD_VAL (child_val1, 0);
422 GET_CHILD_VAL (child_val2, 1);
424 if (rec_sex_op_real_p (child_val1, child_val2))
426 /* Real operation. */
427 ATOD_VAL (op1_real, child_val1);
428 ATOD_VAL (op2_real, child_val2);
430 res.type = REC_SEX_VAL_REAL;
431 res.real_val = op1_real + op2_real;
433 else
435 /* Integer operation. */
436 ATOI_VAL (op1, child_val1);
437 ATOI_VAL (op2, child_val2);
439 res.type = REC_SEX_VAL_INT;
440 res.int_val = op1 + op2;
443 break;
445 case REC_SEX_OP_SUB:
447 int op1;
448 int op2;
449 double op1_real;
450 double op2_real;
452 GET_CHILD_VAL (child_val1, 0);
453 GET_CHILD_VAL (child_val2, 1);
455 if (rec_sex_op_real_p (child_val1, child_val2))
457 /* Real operation. */
458 ATOD_VAL (op1_real, child_val1);
459 ATOD_VAL (op2_real, child_val2);
461 res.type = REC_SEX_VAL_REAL;
462 res.real_val = op1 - op2;
464 else
466 /* Integer operation. */
468 ATOI_VAL (op1, child_val1);
469 ATOI_VAL (op2, child_val2);
471 res.type = REC_SEX_VAL_INT;
472 res.int_val = op1 - op2;
475 break;
477 case REC_SEX_OP_MUL:
479 int op1;
480 int op2;
481 double op1_real;
482 double op2_real;
484 GET_CHILD_VAL (child_val1, 0);
485 GET_CHILD_VAL (child_val2, 1);
487 if (rec_sex_op_real_p (child_val1, child_val2))
489 /* Real operation. */
490 ATOD_VAL (op1_real, child_val1);
491 ATOD_VAL (op2_real, child_val2);
493 res.type = REC_SEX_VAL_REAL;
494 res.real_val = op1_real * op2_real;
496 else
498 /* Integer operation. */
499 ATOI_VAL (op1, child_val1);
500 ATOI_VAL (op2, child_val2);
502 res.type = REC_SEX_VAL_INT;
503 res.int_val = op1 * op2;
506 break;
508 case REC_SEX_OP_DIV:
510 int op1;
511 int op2;
512 double op1_real;
513 double op2_real;
515 GET_CHILD_VAL (child_val1, 0);
516 GET_CHILD_VAL (child_val2, 1);
518 if (rec_sex_op_real_p (child_val1, child_val2))
520 /* Real operation. */
521 ATOD_VAL (op1_real, child_val1);
522 ATOD_VAL (op2_real, child_val2);
524 res.type = REC_SEX_VAL_REAL;
525 res.real_val = op1_real / op2_real;
527 else
529 /* Integer operation. */
530 ATOI_VAL (op1, child_val1);
531 ATOI_VAL (op2, child_val2);
533 res.type = REC_SEX_VAL_INT;
535 if (op2 != 0)
537 res.int_val = op1 / op2;
539 else
541 /* Error: division by zero */
542 *status = false;
543 return res;
547 break;
549 case REC_SEX_OP_MOD:
551 int op1;
552 int op2;
554 GET_CHILD_VAL (child_val1, 0);
555 GET_CHILD_VAL (child_val2, 1);
557 /* Integer operation. */
558 ATOI_VAL (op1, child_val1);
559 ATOI_VAL (op2, child_val2);
561 res.type = REC_SEX_VAL_INT;
563 if (op2 != 0)
565 res.int_val = op1 % op2;
567 else
569 /* Error: division by zero */
570 *status = false;
571 return res;
574 break;
576 case REC_SEX_OP_EQL:
578 int op1;
579 int op2;
580 double op1_real;
581 double op2_real;
583 GET_CHILD_VAL (child_val1, 0);
584 GET_CHILD_VAL (child_val2, 1);
586 if ((child_val1.type == REC_SEX_VAL_STR)
587 && (child_val2.type == REC_SEX_VAL_STR))
589 /* String comparison. */
590 res.type = REC_SEX_VAL_INT;
592 if (rec_sex_parser_case_insensitive (sex->parser))
594 res.int_val = (strcasecmp (child_val1.str_val,
595 child_val2.str_val) == 0);
597 else
599 res.int_val = (strcmp (child_val1.str_val,
600 child_val2.str_val) == 0);
603 else
605 if (rec_sex_op_real_p (child_val1, child_val2))
607 /* Real comparison. */
608 ATOD_VAL (op1_real, child_val1);
609 ATOD_VAL (op2_real, child_val2);
611 res.type = REC_SEX_VAL_INT;
612 res.int_val = op1_real == op2_real;
614 else
616 /* Integer comparison. */
617 ATOI_VAL (op1, child_val1);
618 ATOI_VAL (op2, child_val2);
620 res.type = REC_SEX_VAL_INT;
621 res.int_val = op1 == op2;
625 break;
627 case REC_SEX_OP_NEQ:
629 int op1;
630 int op2;
631 double op1_real;
632 double op2_real;
634 GET_CHILD_VAL (child_val1, 0);
635 GET_CHILD_VAL (child_val2, 1);
637 if ((child_val1.type == REC_SEX_VAL_STR)
638 && (child_val2.type == REC_SEX_VAL_STR))
640 /* String comparison. */
641 res.type = REC_SEX_VAL_INT;
643 if (rec_sex_parser_case_insensitive (sex->parser))
645 res.int_val = (strcasecmp (child_val1.str_val,
646 child_val2.str_val) != 0);
648 else
650 res.int_val = (strcmp (child_val1.str_val,
651 child_val2.str_val) != 0);
654 else
656 if (rec_sex_op_real_p (child_val1, child_val2))
658 /* Real comparison. */
659 ATOD_VAL (op1_real, child_val1);
660 ATOD_VAL (op2_real, child_val2);
662 res.type = REC_SEX_VAL_INT;
663 res.int_val = op1_real != op2_real;
665 else
667 /* Integer comparison. */
668 ATOI_VAL (op1, child_val1);
669 ATOI_VAL (op2, child_val2);
671 res.type = REC_SEX_VAL_INT;
672 res.int_val = op1 != op2;
676 break;
678 case REC_SEX_OP_MAT:
680 GET_CHILD_VAL (child_val1, 0);
681 GET_CHILD_VAL (child_val2, 1);
683 if ((child_val1.type == REC_SEX_VAL_STR)
684 && (child_val2.type == REC_SEX_VAL_STR))
686 /* String match. */
687 res.type = REC_SEX_VAL_INT;
689 if (rec_sex_parser_case_insensitive (sex->parser))
691 res.int_val =
692 rec_match_insensitive (child_val1.str_val, child_val2.str_val);
694 else
696 res.int_val =
697 rec_match (child_val1.str_val, child_val2.str_val);
700 else
702 /* Error. */
703 *status = false;
704 return res;
707 break;
709 case REC_SEX_OP_BEFORE:
711 struct timespec op1;
712 struct timespec op2;
713 struct timespec diff;
715 GET_CHILD_VAL (child_val1, 0);
716 GET_CHILD_VAL (child_val2, 1);
718 ATOTS_VAL (op1, child_val1);
719 ATOTS_VAL (op2, child_val2);
721 res.type = REC_SEX_VAL_INT;
722 res.int_val = rec_timespec_subtract (&diff, &op1, &op2);
723 break;
725 case REC_SEX_OP_AFTER:
727 struct timespec op1;
728 struct timespec op2;
729 struct timespec diff;
731 GET_CHILD_VAL (child_val1, 0);
732 GET_CHILD_VAL (child_val2, 1);
734 ATOTS_VAL (op1, child_val1);
735 ATOTS_VAL (op2, child_val2);
737 res.type = REC_SEX_VAL_INT;
738 res.int_val = (!rec_timespec_subtract (&diff, &op1, &op2)
739 && ((diff.tv_sec != 0) || (diff.tv_nsec != 0)));
740 break;
742 case REC_SEX_OP_SAMETIME:
744 struct timespec op1;
745 struct timespec op2;
746 struct timespec diff;
748 GET_CHILD_VAL (child_val1, 0);
749 GET_CHILD_VAL (child_val2, 1);
751 ATOTS_VAL (op1, child_val1);
752 ATOTS_VAL (op2, child_val2);
754 rec_timespec_subtract (&diff, &op1, &op2);
756 res.type = REC_SEX_VAL_INT;
757 res.int_val = ((diff.tv_sec == 0) && (diff.tv_nsec == 0));
758 break;
760 case REC_SEX_OP_IMPLIES:
762 int op1;
763 int op2;
765 GET_CHILD_VAL (child_val1, 0);
766 GET_CHILD_VAL (child_val2, 1);
768 ATOI_VAL (op1, child_val1);
769 ATOI_VAL (op2, child_val2);
771 res.type = REC_SEX_VAL_INT;
772 res.int_val = !op1 || (op1 && op2);
774 break;
776 case REC_SEX_OP_LT:
777 case REC_SEX_OP_LTE:
779 int op1;
780 int op2;
781 double op1_real;
782 double op2_real;
784 GET_CHILD_VAL (child_val1, 0);
785 GET_CHILD_VAL (child_val2, 1);
787 if (rec_sex_op_real_p (child_val1, child_val2))
789 /* Real comparison. */
790 ATOD_VAL (op1_real, child_val1);
791 ATOD_VAL (op2_real, child_val2);
793 res.type = REC_SEX_VAL_INT;
795 if (rec_sex_ast_node_type (node) == REC_SEX_OP_LT)
797 res.int_val = op1_real < op2_real;
799 else
801 res.int_val = op1_real <= op2_real;
804 else
806 /* Integer comparison. */
807 ATOI_VAL (op1, child_val1);
808 ATOI_VAL (op2, child_val2);
810 res.type = REC_SEX_VAL_INT;
812 if (rec_sex_ast_node_type (node) == REC_SEX_OP_LT)
814 res.int_val = op1 < op2;
816 else
818 res.int_val = op1 <= op2;
822 break;
824 case REC_SEX_OP_GT:
825 case REC_SEX_OP_GTE:
827 int op1;
828 int op2;
829 double op1_real;
830 double op2_real;
832 GET_CHILD_VAL (child_val1, 0);
833 GET_CHILD_VAL (child_val2, 1);
835 if (rec_sex_op_real_p (child_val1, child_val2))
837 /* Real comparison. */
838 ATOD_VAL (op1_real, child_val1);
839 ATOD_VAL (op2_real, child_val2);
841 res.type = REC_SEX_VAL_INT;
843 if (rec_sex_ast_node_type (node) == REC_SEX_OP_GT)
845 res.int_val = op1_real > op2_real;
847 else
849 res.int_val = op1_real >= op2_real;
852 else
854 /* Integer comparison. */
855 ATOI_VAL (op1, child_val1);
856 ATOI_VAL (op2, child_val2);
858 res.type = REC_SEX_VAL_INT;
860 if (rec_sex_ast_node_type (node) == REC_SEX_OP_GT)
862 res.int_val = op1 > op2;
864 else
866 res.int_val = op1 >= op2;
870 break;
872 case REC_SEX_OP_AND:
874 int op1;
875 int op2;
877 GET_CHILD_VAL (child_val1, 0);
878 GET_CHILD_VAL (child_val2, 1);
880 ATOI_VAL (op1, child_val1);
881 ATOI_VAL (op2, child_val2);
883 res.type = REC_SEX_VAL_INT;
884 res.int_val = op1 && op2;
886 break;
888 case REC_SEX_OP_OR:
890 int op1;
891 int op2;
893 GET_CHILD_VAL (child_val1, 0);
894 GET_CHILD_VAL (child_val2, 1);
896 ATOI_VAL (op1, child_val1);
897 ATOI_VAL (op2, child_val2);
899 res.type = REC_SEX_VAL_INT;
900 res.int_val = op1 || op2;
902 break;
904 case REC_SEX_OP_CONCAT:
906 size_t str1_size;
907 size_t str2_size;
909 GET_CHILD_VAL (child_val1, 0);
910 GET_CHILD_VAL (child_val2, 1);
912 if ((child_val1.type == REC_SEX_VAL_STR)
913 && (child_val2.type == REC_SEX_VAL_STR))
915 str1_size = strlen (child_val1.str_val);
916 str2_size = strlen (child_val2.str_val);
918 res.type = REC_SEX_VAL_STR;
919 res.str_val = malloc (str1_size + str2_size + 1);
920 memcpy (res.str_val, child_val1.str_val, str1_size);
921 memcpy (res.str_val + str1_size, child_val2.str_val, str2_size);
922 res.str_val[str1_size + str2_size] = '\0';
924 else
926 *status = false;
927 return res;
930 break;
932 case REC_SEX_OP_NOT:
934 int op;
936 GET_CHILD_VAL (child_val1, 0);
937 ATOI_VAL (op, child_val1);
939 res.type = REC_SEX_VAL_INT;
940 res.int_val = !op;
942 break;
944 case REC_SEX_OP_SHA:
946 int n;
947 const char *field_name = NULL;
948 const char *field_subname = NULL;
949 rec_sex_ast_node_t child;
951 /* The child should be a Name. */
952 child = rec_sex_ast_node_child (node, 0);
953 if (rec_sex_ast_node_type (rec_sex_ast_node_child(node, 0))
954 != REC_SEX_NAME)
956 *status = false;
957 return res;
960 field_name = rec_sex_ast_node_name (child);
961 field_subname = rec_sex_ast_node_subname (child);
963 if (field_subname)
965 /* Compound a field name from the name/subname pair in the
966 AST node. */
968 char *effective_name
969 = rec_concat_strings (field_name, "_", field_subname);
971 n = rec_record_get_num_fields_by_name (record,
972 effective_name);
973 free (effective_name);
975 else
977 n = rec_record_get_num_fields_by_name (record, field_name);
980 res.type = REC_SEX_VAL_INT;
981 res.int_val = n;
982 break;
984 case REC_SEX_OP_COND:
986 int op1;
988 GET_CHILD_VAL (child_val1, 0);
989 GET_CHILD_VAL (child_val2, 1);
990 GET_CHILD_VAL (child_val3, 2);
992 /* Get the boolean value of the first operand. */
993 ATOI_VAL (op1, child_val1);
995 /* Return the first or the second operand, depending on the
996 value of op1. */
997 if (op1)
999 res = child_val2;
1001 else
1003 res = child_val3;
1006 break;
1008 /* Values. */
1009 case REC_SEX_INT:
1011 res.type = REC_SEX_VAL_INT;
1012 res.int_val = rec_sex_ast_node_int (node);
1013 break;
1015 case REC_SEX_REAL:
1017 res.type = REC_SEX_VAL_REAL;
1018 res.real_val = rec_sex_ast_node_real (node);
1019 break;
1021 case REC_SEX_STR:
1023 res.type = REC_SEX_VAL_STR;
1024 res.str_val = rec_sex_ast_node_str (node);
1025 break;
1027 case REC_SEX_NAME:
1029 rec_field_t field;
1030 const char *field_name;
1031 const char *field_subname;
1032 int index;
1033 bool tofix;
1035 if (rec_sex_ast_node_fixed (node))
1037 res.type = REC_SEX_VAL_STR;
1038 res.str_val = rec_sex_ast_node_fixed_val (node);
1040 else
1042 field_name = rec_sex_ast_node_name (node);
1043 field_subname = rec_sex_ast_node_subname (node);
1044 index = rec_sex_ast_node_index (node);
1045 tofix = (index != -1);
1046 if (index == -1)
1048 index = 0;
1051 /* If there is a subname then the effective field name is
1052 the concatenation of the name and the subname separated
1053 by a '_' character. Otherwise it is just the name. */
1056 if (field_subname)
1058 char *effective_field_name = malloc (sizeof (char) *
1059 (strlen (field_name) + strlen (field_subname) + 2));
1060 memcpy (effective_field_name, field_name, strlen(field_name));
1061 effective_field_name[strlen(field_name)] = '_';
1062 memcpy (effective_field_name + strlen(field_name) + 1, field_subname, strlen(field_subname) + 1);
1064 field = rec_record_get_field_by_name (record, effective_field_name, index);
1066 else
1068 field = rec_record_get_field_by_name (record, field_name, index);
1072 res.type = REC_SEX_VAL_STR;
1073 if (field)
1075 res.str_val = strdup (rec_field_value (field));
1077 else
1079 /* No field => "" */
1080 res.str_val = "";
1083 if (tofix)
1085 /* Make this node fixed. */
1086 rec_sex_ast_node_fix (node, res.str_val);
1090 break;
1094 return res;
1097 static bool
1098 rec_sex_op_real_p (struct rec_sex_val_s op1,
1099 struct rec_sex_val_s op2)
1101 bool ret;
1102 int integer;
1103 double real;
1105 ret = true;
1107 if ((op1.type == REC_SEX_VAL_INT)
1108 || ((op1.type == REC_SEX_VAL_STR)
1109 && rec_atoi (op1.str_val, &integer)))
1111 /* Operand 1 is an integer. */
1112 switch (op2.type)
1114 case REC_SEX_VAL_INT:
1116 ret = false;
1117 break;
1119 case REC_SEX_VAL_REAL:
1121 ret = true;
1122 break;
1124 case REC_SEX_VAL_STR:
1126 ret = (rec_atod (op2.str_val, &real)
1127 && (!rec_atoi (op2.str_val, &integer)));
1128 break;
1130 default:
1132 ret = false;
1133 break;
1138 if ((op1.type == REC_SEX_VAL_REAL)
1139 || ((op1.type == REC_SEX_VAL_STR)
1140 && rec_atod (op1.str_val, &real)
1141 && (!rec_atoi (op1.str_val, &integer))))
1143 /* Operand 1 is a real. */
1144 switch (op2.type)
1146 case REC_SEX_VAL_INT:
1148 ret = true;
1149 break;
1151 case REC_SEX_VAL_REAL:
1153 ret = true;
1154 break;
1156 case REC_SEX_VAL_STR:
1158 ret = rec_atod (op2.str_val, &real);
1159 break;
1161 default:
1163 ret = false;
1164 break;
1169 return ret;
1172 /* End of rec-sex.c */