4 * Date: Sat Jan 9 20:28:43 2010
6 * GNU recutils - Record Selection Expressions.
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/>.
31 #include <parse-datetime.h>
34 #include <rec-utils.h>
35 #include <rec-sex-ast.h>
36 #include <rec-sex-parser.h>
37 #include <rec-sex-tab.h>
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
62 /* Static functions declarations. */
63 static struct rec_sex_val_s
rec_sex_eval_node (rec_sex_t sex
,
65 rec_sex_ast_node_t node
,
67 static bool rec_sex_op_real_p (struct rec_sex_val_s op1
,
68 struct rec_sex_val_s op2
);
75 rec_sex_new (bool case_insensitive
)
79 new = malloc (sizeof (struct rec_sex_s
));
82 /* Initialize a new parser. */
83 new->parser
= rec_sex_parser_new ();
84 rec_sex_parser_set_case_insensitive (new->parser
,
87 /* Initialize a new AST. */
95 rec_sex_destroy (rec_sex_t sex
)
101 rec_sex_parser_destroy (sex
->parser
);
106 rec_sex_ast_destroy (sex
->ast
);
109 free (sex
); /* yeah! :D */
114 rec_sex_compile (rec_sex_t sex
,
119 res
= rec_sex_parser_run (sex
->parser
, expr
);
122 sex
->ast
= rec_sex_parser_ast (sex
->parser
);
127 #define EXEC_AST(RECORD) \
130 val = rec_sex_eval_node (sex, \
132 rec_sex_ast_top (sex->ast), \
137 case REC_SEX_VAL_INT: \
139 res = (val.int_val != 0); \
142 case REC_SEX_VAL_REAL: \
143 case REC_SEX_VAL_STR: \
153 rec_sex_eval_str (rec_sex_t sex
,
157 struct rec_sex_val_s val
;
160 rec_sex_ast_node_unfix (rec_sex_ast_top (sex
->ast
));
161 val
= rec_sex_eval_node (sex
,
163 rec_sex_ast_top (sex
->ast
),
168 /* Error evaluating the expression. */
175 case REC_SEX_VAL_INT
:
177 asprintf (&res
, "%d", val
.int_val
);
180 case REC_SEX_VAL_REAL
:
182 asprintf (&res
, "%f", val
.real_val
);
185 case REC_SEX_VAL_STR
:
187 res
= strdup (val
.str_val
);
196 rec_sex_eval (rec_sex_t sex
,
204 rec_mset_iterator_t iter
;
206 struct rec_sex_val_s val
;
211 rec_sex_ast_node_unfix (rec_sex_ast_top (sex
->ast
));
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
));
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
),
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
);
251 rec_record_destroy (wrec
);
258 rec_mset_iterator_free (&iter
);
271 rec_sex_print_ast (rec_sex_t sex
)
273 rec_sex_parser_print_ast (sex
->parser
);
280 #define GET_CHILD_VAL(DEST,NUM) \
283 (DEST) = rec_sex_eval_node (sex, \
285 rec_sex_ast_node_child (node, (NUM)), \
295 #define ATOI_VAL(DEST, VAL) \
298 switch ((VAL).type) \
300 case REC_SEX_VAL_INT: \
302 (DEST) = (VAL).int_val; \
305 case REC_SEX_VAL_STR: \
307 if (strcmp ((VAL).str_val, "") == 0) \
313 if (!rec_atoi ((VAL).str_val, &(DEST))) \
325 #define ATOD_VAL(DEST, VAL) \
328 switch ((VAL).type) \
330 case REC_SEX_VAL_REAL: \
332 (DEST) = (VAL).real_val; \
335 case REC_SEX_VAL_INT: \
337 (DEST) = (VAL).int_val; \
340 case REC_SEX_VAL_STR: \
342 if (strcmp ((VAL).str_val, "") == 0) \
348 if (!rec_atod ((VAL).str_val, &(DEST))) \
360 #define ATOTS_VAL(DEST, VAL) \
363 switch ((VAL).type) \
365 case REC_SEX_VAL_REAL: \
371 case REC_SEX_VAL_INT: \
377 case REC_SEX_VAL_STR: \
379 if (!parse_datetime (&(DEST), (VAL).str_val, NULL))\
392 rec_sex_eval_node (rec_sex_t sex
,
394 rec_sex_ast_node_t node
,
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
};
404 switch (rec_sex_ast_node_type (node
))
408 fprintf (stderr
, "Application bug: REC_SEX_NOVAL node found.\nPlease report this!\n");
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
;
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
;
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
;
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
;
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
;
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
;
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
;
529 /* Integer operation. */
530 ATOI_VAL (op1
, child_val1
);
531 ATOI_VAL (op2
, child_val2
);
533 res
.type
= REC_SEX_VAL_INT
;
537 res
.int_val
= op1
/ op2
;
541 /* Error: division by zero */
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
;
565 res
.int_val
= op1
% op2
;
569 /* Error: division by zero */
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);
599 res
.int_val
= (strcmp (child_val1
.str_val
,
600 child_val2
.str_val
) == 0);
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
;
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
;
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);
650 res
.int_val
= (strcmp (child_val1
.str_val
,
651 child_val2
.str_val
) != 0);
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
;
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
;
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
))
687 res
.type
= REC_SEX_VAL_INT
;
689 if (rec_sex_parser_case_insensitive (sex
->parser
))
692 rec_match_insensitive (child_val1
.str_val
, child_val2
.str_val
);
697 rec_match (child_val1
.str_val
, child_val2
.str_val
);
709 case REC_SEX_OP_BEFORE
:
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
);
725 case REC_SEX_OP_AFTER
:
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)));
742 case REC_SEX_OP_SAMETIME
:
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));
760 case REC_SEX_OP_IMPLIES
:
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
);
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
;
801 res
.int_val
= op1_real
<= op2_real
;
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
;
818 res
.int_val
= op1
<= op2
;
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
;
849 res
.int_val
= op1_real
>= op2_real
;
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
;
866 res
.int_val
= op1
>= 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
;
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
;
904 case REC_SEX_OP_CONCAT
:
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';
936 GET_CHILD_VAL (child_val1
, 0);
937 ATOI_VAL (op
, child_val1
);
939 res
.type
= REC_SEX_VAL_INT
;
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))
960 field_name
= rec_sex_ast_node_name (child
);
961 field_subname
= rec_sex_ast_node_subname (child
);
965 /* Compound a field name from the name/subname pair in the
969 = rec_concat_strings (field_name
, "_", field_subname
);
971 n
= rec_record_get_num_fields_by_name (record
,
973 free (effective_name
);
977 n
= rec_record_get_num_fields_by_name (record
, field_name
);
980 res
.type
= REC_SEX_VAL_INT
;
984 case REC_SEX_OP_COND
:
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
1011 res
.type
= REC_SEX_VAL_INT
;
1012 res
.int_val
= rec_sex_ast_node_int (node
);
1017 res
.type
= REC_SEX_VAL_REAL
;
1018 res
.real_val
= rec_sex_ast_node_real (node
);
1023 res
.type
= REC_SEX_VAL_STR
;
1024 res
.str_val
= rec_sex_ast_node_str (node
);
1030 const char *field_name
;
1031 const char *field_subname
;
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
);
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);
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. */
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
);
1068 field
= rec_record_get_field_by_name (record
, field_name
, index
);
1072 res
.type
= REC_SEX_VAL_STR
;
1075 res
.str_val
= strdup (rec_field_value (field
));
1079 /* No field => "" */
1085 /* Make this node fixed. */
1086 rec_sex_ast_node_fix (node
, res
.str_val
);
1098 rec_sex_op_real_p (struct rec_sex_val_s op1
,
1099 struct rec_sex_val_s op2
)
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. */
1114 case REC_SEX_VAL_INT
:
1119 case REC_SEX_VAL_REAL
:
1124 case REC_SEX_VAL_STR
:
1126 ret
= (rec_atod (op2
.str_val
, &real
)
1127 && (!rec_atoi (op2
.str_val
, &integer
)));
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. */
1146 case REC_SEX_VAL_INT
:
1151 case REC_SEX_VAL_REAL
:
1156 case REC_SEX_VAL_STR
:
1158 ret
= rec_atod (op2
.str_val
, &real
);
1172 /* End of rec-sex.c */