1 #include "asn1fix_internal.h"
2 #include "asn1fix_constraint.h"
3 #include "asn1fix_crange.h"
6 #define FATAL(fmt, args...) do { \
7 fprintf(stderr, "FATAL: "); \
8 fprintf(stderr, fmt, ##args); \
9 fprintf(stderr, "\n"); \
13 asn1constraint_range_free_outer(asn1cnst_range_t *cr) {
17 for(i = 0; i < cr->el_count; i++)
18 asn1constraint_range_free(cr->elements[i]);
21 memset(cr, 0, sizeof(*cr));
26 asn1constraint_range_free(asn1cnst_range_t *cr) {
27 asn1constraint_range_free_outer(cr);
31 #define _range_free(foo) asn1constraint_range_free(foo)
33 static asn1cnst_range_t *_range_new() {
35 r = calloc(1, sizeof(*r));
37 r->left.type = ARE_MIN;
38 r->right.type = ARE_MAX;
43 static void _range_remove_element(asn1cnst_range_t *range, int idx) {
44 assert(idx >= 0 && idx < range->el_count);
46 assert(!range->elements[idx]->elements);
48 _range_free(range->elements[idx]);
50 memmove(&range->elements[idx],
51 &range->elements[idx + 1],
52 (range->el_count - idx - 1)
53 * sizeof(range->elements[0])
56 range->elements[range->el_count] = 0; /* JIC */
58 if(range->el_count == 0) {
60 free(range->elements);
65 static int _range_insert(asn1cnst_range_t *into, asn1cnst_range_t *cr) {
67 assert(!cr->elements);
69 if(into->el_count == into->el_size) {
71 int n = into->el_size?(into->el_size << 1):4;
72 p = realloc(into->elements, n * sizeof(into->elements[0]));
82 into->elements[into->el_count++] = cr;
86 static asn1cnst_range_t *_range_clone(const asn1cnst_range_t *range) {
87 asn1cnst_range_t *clone;
91 if(!clone) return NULL;
98 for(i = 0; i < range->el_count; i++) {
99 asn1cnst_range_t *r = _range_clone(range->elements[i]);
100 if(!r || _range_insert(clone, r)) {
111 _edge_compare(const asn1cnst_edge_t *el, const asn1cnst_edge_t *er) {
116 case ARE_MIN: return 0;
117 case ARE_MAX: return -1;
118 case ARE_VALUE: return -1;
123 case ARE_MIN: return 1;
124 case ARE_MAX: return 0;
125 case ARE_VALUE: return 1;
130 case ARE_MIN: return 1;
131 case ARE_MAX: return -1;
133 if(el->value < er->value)
135 if(el->value > er->value)
146 _range_compare(const void *a, const void *b) {
147 const asn1cnst_range_t *ra = *(const asn1cnst_range_t * const *)a;
148 const asn1cnst_range_t *rb = *(const asn1cnst_range_t * const *)b;
151 ret = _edge_compare(&ra->left, &rb->left);
153 ret = _edge_compare(&ra->right, &rb->right);
160 _edge_print(const asn1cnst_edge_t *edge, char *buf, size_t size) {
164 case ARE_MIN: strcpy(buf, "MIN"); break;
165 case ARE_MAX: strcpy(buf, "MAX"); break;
167 snprintf(buf, size, "%s", asn1p_itoa(edge->value));
170 assert(!"edge->type");
176 _edge_string(const asn1cnst_edge_t *edge) {
177 static char buf[128];
178 return _edge_print(edge, buf, sizeof(buf));
182 _range_string(const asn1cnst_range_t *range) {
183 static char buf[128];
186 snprintf(buf, sizeof(buf), "(%s..%s)",
187 _edge_print(&range->left, buf0, sizeof(buf0)),
188 _edge_print(&range->right, buf1, sizeof(buf1)));
193 _edge_is_within(const asn1cnst_range_t *range, const asn1cnst_edge_t *edge) {
196 for(i = -1; i < range->el_count; i++) {
197 const asn1cnst_range_t *r;
199 if(range->el_count) continue;
202 r = range->elements[i];
204 if(_edge_compare(&r->left, edge) <= 0
205 && _edge_compare(&r->right, edge) >= 0)
213 _check_edges_within(const asn1cnst_range_t *range, const asn1cnst_range_t *r) {
215 if(!_edge_is_within(range, &r->left)) {
216 FATAL("Constraint value %s at line %d "
218 "a parent constraint range %s",
219 _edge_string(&r->left),
226 if(!_edge_is_within(range, &r->right)) {
227 FATAL("Constraint value %s at line %d "
229 "a parent constraint range %s",
230 _edge_string(&r->right),
241 * Combine narrowings to get the strongest (most specific).
243 static enum asn1cnst_range_narrowing
244 _strongest_narrowing(const asn1cnst_range_t *ar, const asn1cnst_range_t *br) {
245 enum asn1cnst_range_narrowing an = ar->narrowing;
246 enum asn1cnst_range_narrowing bn = br->narrowing;
253 return an > bn ? an : bn;
258 * Combine narrowings to get the softest one.
260 static enum asn1cnst_range_narrowing
261 _softest_narrowing(const asn1cnst_range_t *ar, const asn1cnst_range_t *br) {
262 enum asn1cnst_range_narrowing an = ar->narrowing;
263 enum asn1cnst_range_narrowing bn = br->narrowing;
267 return an < bn ? an : bn;
269 assert(bn == NOT_NARROW);
270 if(br->left.type == ARE_VALUE && br->right.type == ARE_VALUE) {
277 if(ar->left.type == ARE_VALUE && ar->right.type == ARE_VALUE) {
287 static int _range_merge_in(asn1cnst_range_t *into, asn1cnst_range_t *cr) {
289 int prev_count = into->el_count;
292 into->not_OER_visible |= cr->not_OER_visible;
293 into->not_PER_visible |= cr->not_PER_visible;
294 into->extensible |= cr->extensible;
296 into->not_OER_visible = 1;
298 into->narrowing = _softest_narrowing(into, cr);
301 * Add the element OR all its children "into".
303 for(i = -1; i < cr->el_count; i++) {
306 if(cr->el_count) continue;
312 if(_range_insert(into, r)) {
313 into->el_count = prev_count; /* Undo */
322 /* This range is linked into "into". */
328 enum range_fill_result {
333 static enum range_fill_result _range_fill(asn1p_value_t *val, const asn1cnst_range_t *minmax, asn1cnst_edge_t *edge, asn1cnst_range_t *range, enum asn1p_constraint_type_e type, int lineno) {
334 unsigned char *p, *pend;
336 edge->lineno = lineno;
340 if(type != ACT_EL_RANGE && type != ACT_CT_SIZE) {
341 FATAL("Integer %s value invalid "
342 "for %s constraint at line %d",
343 asn1p_itoa(val->value.v_integer),
344 asn1p_constraint_type2str(type), lineno);
347 edge->type = ARE_VALUE;
348 edge->value = val->value.v_integer;
351 if(type != ACT_EL_RANGE && type != ACT_CT_SIZE) {
352 FATAL("MIN invalid for %s constraint at line %d",
353 asn1p_constraint_type2str(type), lineno);
356 edge->type = ARE_MIN;
357 if(minmax) *edge = minmax->left;
358 edge->lineno = lineno; /* Restore lineno */
361 if(type != ACT_EL_RANGE && type != ACT_CT_SIZE) {
362 FATAL("MAX invalid for %s constraint at line %d",
363 asn1p_constraint_type2str(type), lineno);
366 edge->type = ARE_MAX;
367 if(minmax) *edge = minmax->right;
368 edge->lineno = lineno; /* Restore lineno */
372 if(type != ACT_EL_RANGE) {
373 FATAL("%s is invalid for %s constraint at line %d",
374 val->type==ATV_TRUE?"TRUE":"FALSE",
375 asn1p_constraint_type2str(type),
379 edge->type = ARE_VALUE;
380 edge->value = (val->type==ATV_TRUE);
384 edge->type = ARE_VALUE;
385 edge->value = val->value.v_integer;
388 if(type != ACT_CT_FROM)
392 FATAL("Unresolved constraint element \"%s\" at line %d",
393 asn1f_printable_reference(val->value.reference),
397 /* Value constraint... not supported yet. */
398 /* OER: X.696 (08/2015) #8.2.2i */
399 return RFR_INCOMPATIBLE;
401 FATAL("Unrecognized constraint range element type %d at line %d",
406 assert(val->type == ATV_STRING);
408 p = val->value.string.buf;
409 pend = p + val->value.string.size;
410 if(p == pend) return RFR_OK;
412 edge->type = ARE_VALUE;
413 if(val->value.string.size == 1) {
417 * Else this is a set:
419 * However, (FROM("abc".."def")) is forbidden.
422 asn1c_integer_t vmin, vmax;
424 for(; p < pend; p++) {
425 asn1cnst_range_t *nr = _range_new();
429 if(*p < vmin) vmin = *p;
430 if(*p > vmax) vmax = *p;
432 ret = _range_insert(range, nr);
435 nr->left.type = ARE_VALUE;
437 nr->left.lineno = lineno;
438 nr->right = nr->left;
440 edge->value = (edge == &range->right) ? vmin : vmax;
447 * Check if ranges contain common elements.
450 _range_overlap(const asn1cnst_range_t *ra, const asn1cnst_range_t *rb) {
452 const asn1cnst_edge_t *ra_l = &ra->left;
453 const asn1cnst_edge_t *ra_r = &ra->right;
454 const asn1cnst_edge_t *rb_l = &rb->left;
455 const asn1cnst_edge_t *rb_r = &rb->right;
457 assert(_edge_compare(ra_l, ra_r) <= 0);
458 assert(_edge_compare(rb_l, rb_r) <= 0);
460 lr = _edge_compare(ra_l, rb_r);
461 rl = _edge_compare(ra_r, rb_l);
479 static int _range_partial_compare(const void *pa, const void *pb) {
480 const asn1cnst_range_t *ra = *(const void * const *)pa;
481 const asn1cnst_range_t *rb = *(const void * const *)pb;
483 return _edge_compare(&ra->left, &rb->left);
486 static void _range_partial_sort_elements(asn1cnst_range_t *r) {
487 qsort(r->elements, r->el_count, sizeof(r->elements[0]),
488 _range_partial_compare);
492 * (MIN..20) x (10..15) = (MIN..9,10..15,16..20)
494 static asn1cnst_range_t *
495 _range_split(asn1cnst_range_t *ra, const asn1cnst_range_t *rb) {
496 asn1cnst_range_t *range, *nr;
501 assert(!ra->el_count);
502 assert(!rb->el_count);
504 if(!_range_overlap(ra, rb)) {
509 ll = _edge_compare(&ra->left, &rb->left);
510 rr = _edge_compare(&ra->right, &rb->right);
516 if(ll >= 0 && rr <= 0) {
521 range = _range_new();
533 nr->right = rb->left;
534 if(nr->right.type == ARE_VALUE) {
535 if(nr->right.value == INTMAX_MIN) {
536 /* We've hit the limit here. */
541 _range_insert(range, nr);
552 nr->left = rb->right;
553 nr->right = ra->right;
554 if(nr->left.type == ARE_VALUE) {
555 if(nr->left.value == INTMAX_MAX) {
556 /* We've hit the limit here. */
561 _range_insert(range, nr);
572 nr->right = ra->right;
573 if(_edge_compare(&ra->left, &rb->left) < 0)
575 if(_edge_compare(&ra->right, &rb->right) > 0)
576 nr->right = rb->right;
578 _range_insert(range, nr);
580 _range_partial_sort_elements(range);
586 _range_intersection(asn1cnst_range_t *range, const asn1cnst_range_t *with, int strict_edge_check, int is_oer) {
590 assert(!range->incompatible);
593 assert(range->extensible == 0);
594 assert(range->not_OER_visible == 0);
595 assert(with->extensible == 0);
596 assert(with->not_OER_visible == 0);
597 if(range->extensible) {
598 assert(range->not_OER_visible);
600 if(range->extensible || range->not_OER_visible) {
601 /* X.696 #8.2.4 Completely ignore the extensible constraints */
602 /* (XXX)(YYY,...) Retain the first one (XXX). */
603 asn1cnst_range_t *tmp = _range_new();
610 if(with->extensible) {
611 assert(with->not_OER_visible);
613 if(with->extensible || with->not_OER_visible) {
614 /* X.696 #8.2.4 Completely ignore the extensible constraints */
618 /* Propagate errors */
619 range->extensible |= with->extensible;
621 range->not_OER_visible = 1;
622 range->not_PER_visible |= with->not_PER_visible;
624 range->empty_constraint |= with->empty_constraint;
626 range->narrowing = _strongest_narrowing(range, with);
628 if(range->empty_constraint) {
629 /* No use in intersecting empty constraints */
634 * This is an AND operation.
637 /* If this is the only element, insert it into itself as a child */
638 if(range->el_count == 0) {
639 asn1cnst_range_t *r = _range_new();
640 r->left = range->left;
641 r->right = range->right;
642 _range_insert(range, r);
643 assert(range->el_count == 1);
647 * Make sure we're dealing with sane data.
650 if(strict_edge_check) {
651 for(j = -1; j < with->el_count; j++) {
654 if(with->el_count) continue;
655 if(_check_edges_within(range, with))
658 if(_check_edges_within(range,
666 * Split range in pieces.
669 for(i = 0; i < range->el_count; i++) {
670 for(j = -1; j < with->el_count; j++) {
671 const asn1cnst_range_t *wel;
675 if(with->el_count) continue;
678 wel = with->elements[j];
679 assert(!wel->el_count); /* non-compound item! */
682 r = _range_split(range->elements[i], wel);
685 /* Substitute the current element with a split */
686 _range_remove_element(range, i);
688 for(ec = 0; ec < r->el_count; ec++) {
689 ret = _range_insert(range, r->elements[ec]);
695 break; /* Try again from this point */
700 assert(range->el_count);
703 * Remove pieces which aren't AND-compatible "with" range.
706 for(i = 0; i < range->el_count; i++) {
707 for(j = -1; j < with->el_count; j++) {
708 const asn1cnst_range_t *wel;
711 if(with->el_count) continue;
714 wel = with->elements[j];
717 if(_range_overlap(range->elements[i], wel))
720 if(j == with->el_count) {
721 _range_remove_element(range, i);
726 if(range->el_count == 0)
727 range->empty_constraint = 1;
733 _range_union(asn1cnst_range_t *range) {
736 qsort(range->elements, range->el_count, sizeof(range->elements[0]),
740 * The range is sorted by the start values.
742 for(i = 1; i < range->el_count; i++) {
743 asn1cnst_range_t *ra = range->elements[i - 1];
744 asn1cnst_range_t *rb = range->elements[i];
746 if(_range_overlap(ra, rb)) {
747 if(_edge_compare(&ra->left, &rb->left) < 0)
750 if(_edge_compare(&ra->right, &rb->right) > 0)
751 rb->right = ra->right;
754 * Still, range may be joined: (1..4)(5..10).
755 * This logic is valid only for whole numbers
756 * (i.e., not REAL type, but REAL constraints
757 * are not PER-visible (X.691, #9.3.12).
759 if(ra->right.type == ARE_VALUE
760 && rb->left.type == ARE_VALUE
761 && (rb->left.value - ra->right.value) == 1) {
770 * Squeeze the array by removing the ra.
772 _range_remove_element(range, i - 1);
774 i--; /* Retry from the current point */
781 _range_canonicalize(asn1cnst_range_t *range) {
783 if(range->el_count == 0) {
785 * Switch left and right edges, make them sorted.
786 * It might be a mild warning though.
788 if(_edge_compare(&range->left, &range->right) > 0) {
789 asn1cnst_edge_t tmp = range->left;
790 range->left = range->right;
794 free(range->elements);
801 * Remove duplicates and overlaps by merging them in.
805 /* Refine the left edge of a parent */
806 range->left = range->elements[0]->left;
808 /* Refine the right edge of a parent */
809 range->right = range->elements[range->el_count - 1]->right;
811 /* Remove the child, if it's a single one */
812 if(range->el_count == 1) {
813 _range_remove_element(range, 0);
820 asn1constraint_compute_OER_range(const char *dbg_name, asn1p_expr_type_e expr_type, const asn1p_constraint_t *ct, enum asn1p_constraint_type_e requested_ct_type, const asn1cnst_range_t *minmax, int *exmet, enum cpr_flags cpr_flags) {
821 return asn1constraint_compute_constraint_range(dbg_name, expr_type, ct, requested_ct_type, minmax, exmet, cpr_flags | CPR_strict_OER_visibility);
825 asn1constraint_compute_PER_range(const char *dbg_name, asn1p_expr_type_e expr_type, const asn1p_constraint_t *ct, enum asn1p_constraint_type_e requested_ct_type, const asn1cnst_range_t *minmax, int *exmet, enum cpr_flags cpr_flags) {
826 if(0) return asn1constraint_compute_constraint_range(dbg_name, expr_type, ct, requested_ct_type, minmax, exmet, cpr_flags | CPR_strict_PER_visibility);
827 /* Due to pecularities of PER constraint handling, we don't enable strict PER visibility upfront here. */
828 return asn1constraint_compute_constraint_range(dbg_name, expr_type, ct, requested_ct_type, minmax, exmet, cpr_flags);
831 static asn1cnst_range_t *
832 asn1f_real_range_from_WCOMPS(const char *dbg_name,
833 const asn1p_constraint_t *ct) {
834 asn1cnst_range_t two = {
835 {ARE_VALUE, 0, 2}, {ARE_VALUE, 0, 2}, 0, NULL, 0, 0, 0, 0, 0, 0, 0};
836 asn1cnst_range_t ten = {
837 {ARE_VALUE, 0, 10}, {ARE_VALUE, 0, 10}, 0, NULL, 0, 0, 0, 0, 0, 0, 0};
838 asn1cnst_range_t *two_ten[] = {&two, &ten};
839 /* Interpretation of X.680 #21.5 */
840 asn1cnst_range_t mantissa_default_range = {
841 {ARE_MIN, 0, 0}, {ARE_MAX, 0, 0}, 0, NULL, 0, 0, 0, 0, 0, 0, 0};
842 asn1cnst_range_t exponent_default_range = {
843 {ARE_MIN, 0, 0}, {ARE_MAX, 0, 0}, 0, NULL, 0, 0, 0, 0, 0, 0, 0};
844 asn1cnst_range_t base_default_range = {
845 {ARE_VALUE, 0, 2}, {ARE_MAX, 0, 10}, 0, two_ten, 2, 0, 0, 0, 0, 0, 0};
847 asn1cnst_range_t *mantissa = _range_clone(&mantissa_default_range);
848 asn1cnst_range_t *exponent = _range_clone(&exponent_default_range);
849 asn1cnst_range_t *base = _range_clone(&base_default_range);
850 asn1cnst_range_t *range;
854 _range_free(mantissa); \
855 _range_free(exponent); \
861 assert(ct->type == ACT_CT_WCOMPS);
863 range = _range_new();
864 range->incompatible = 1;
866 for(unsigned i = 0; i < ct->el_count; i++) {
867 struct asn1p_constraint_s *el = ct->elements[i];
868 asn1p_value_t *value = 0;
869 asn1cnst_range_t **dst_range = 0;
873 /* Some components might not be defined. */
874 assert(range->incompatible);
878 assert(range->incompatible);
883 if(value->type != ATV_REFERENCED) {
890 if(strcmp(asn1p_ref_string(value->value.reference), "mantissa") == 0) {
891 dst_range = &mantissa;
892 } else if(strcmp(asn1p_ref_string(value->value.reference), "exponent")
894 dst_range = &exponent;
895 } else if(strcmp(asn1p_ref_string(value->value.reference), "base")
899 FATAL("Invalid specification \"%s\" for REAL",
900 asn1p_ref_string(value->value.reference));
905 switch(el->el_count) {
909 FATAL("Too many constraints (%u) for \"%s\" for REAL", el->el_count,
910 asn1p_ref_string(value->value.reference));
915 asn1cnst_range_t *tmprange = asn1constraint_compute_constraint_range(
916 dbg_name, ASN_BASIC_INTEGER, el->elements[0], ACT_EL_RANGE,
917 *dst_range, 0, CPR_noflags);
919 if(tmprange->incompatible) {
920 _range_free(tmprange);
924 asn1constraint_range_free(*dst_range);
925 *dst_range = tmprange;
928 range->incompatible = 0;
931 if(mantissa->left.type == ARE_VALUE && mantissa->right.type == ARE_VALUE
932 && mantissa->left.value >= -16777215 && mantissa->right.value <= 16777215
933 && base->left.type == ARE_VALUE && base->right.type == ARE_VALUE
934 && base->left.value == 2 && base->right.value == 2
935 && exponent->left.type == ARE_VALUE && exponent->right.type == ARE_VALUE
936 && exponent->left.value >= -149 && exponent->right.value <= 104) {
937 range->narrowing = NARROW_FLOAT32;
938 } else /* X.696 #12.3 */
939 if(mantissa->left.type == ARE_VALUE && mantissa->right.type == ARE_VALUE
940 && mantissa->left.value >= -9007199254740991ll
941 && mantissa->right.value <= 9007199254740991ull
942 && base->left.type == ARE_VALUE && base->right.type == ARE_VALUE
943 && base->left.value == 2 && base->right.value == 2
944 && exponent->left.type == ARE_VALUE && exponent->right.type == ARE_VALUE
945 && exponent->left.value >= -1074 && exponent->right.value <= 971) {
946 range->narrowing = NARROW_DOUBLE64;
954 asn1constraint_compute_constraint_range(
955 const char *dbg_name, asn1p_expr_type_e expr_type,
956 const asn1p_constraint_t *ct,
957 enum asn1p_constraint_type_e requested_ct_type,
958 const asn1cnst_range_t *minmax, int *exmet, enum cpr_flags cpr_flags) {
959 asn1cnst_range_t *range;
960 asn1cnst_range_t *tmp;
968 exmet = &expectation_met;
973 * Check if the requested constraint is theoretically compatible
974 * with the given expression type.
976 if(asn1constraint_compatible(expr_type, requested_ct_type,
977 cpr_flags & CPR_simulate_fbless_SIZE) != 1) {
983 * Check arguments' validity.
985 switch(requested_ct_type) {
987 if(exmet == &expectation_met)
991 if(cpr_flags & CPR_strict_OER_visibility) {
996 minmax = asn1constraint_default_alphabet(expr_type);
1004 static asn1cnst_range_t mm;
1005 mm.left.type = ARE_VALUE;
1007 mm.right.type = ARE_MAX;
1017 range = _range_clone(minmax);
1019 range = _range_new();
1024 * Constraints on restricted character string types
1025 * which are not known-multiplier are not PER-visible.
1027 if((expr_type & ASN_STRING_NKM_MASK))
1028 range->not_PER_visible = 1;
1031 || (range->not_PER_visible && (cpr_flags & CPR_strict_PER_visibility)))
1035 * X.696 (08/2015), #8.2.2
1036 * SIZE constraints on restricted character string types
1037 * which are not known-multiplier are not OER-visible.
1039 if(requested_ct_type == ACT_CT_SIZE && (expr_type & ASN_STRING_NKM_MASK))
1040 range->not_OER_visible = 1;
1043 || (range->not_OER_visible && (cpr_flags & CPR_strict_OER_visibility))) {
1049 vmin = vmax = ct->value;
1052 case ACT_EL_LLRANGE:
1053 case ACT_EL_RLRANGE:
1054 case ACT_EL_ULRANGE:
1055 vmin = ct->range_start;
1056 vmax = ct->range_stop;
1060 range->extensible = 1;
1061 range->not_OER_visible = 1;
1070 if(requested_ct_type == ct->type) {
1072 * Specifically requested to process SIZE() or FROM() constraint.
1076 range->incompatible = 1;
1079 assert(ct->el_count == 1);
1080 tmp = asn1constraint_compute_constraint_range(
1081 dbg_name, expr_type, ct->elements[0], requested_ct_type, minmax,
1086 if(errno == ERANGE) {
1087 range->empty_constraint = 1;
1088 range->extensible = 1;
1089 if(range->extensible)
1090 range->not_OER_visible = 1;
1097 case ACT_CA_SET: /* (10..20)(15..17) */
1098 case ACT_CA_INT: /* SIZE(1..2) ^ FROM("ABCD") */
1100 /* AND constraints, one after another. */
1101 for(i = 0; i < ct->el_count; i++) {
1102 tmp = asn1constraint_compute_constraint_range(dbg_name, expr_type,
1103 ct->elements[i], requested_ct_type,
1104 ct->type==ACT_CA_SET?range:minmax, exmet,
1107 if(errno == ERANGE) {
1108 range->extensible = 1;
1109 if(range->extensible)
1110 range->not_OER_visible = 1;
1118 if(tmp->incompatible) {
1120 * Ignore constraints
1121 * incompatible with arguments:
1122 * SIZE(1..2) ^ FROM("ABCD")
1123 * either SIZE or FROM will be ignored.
1129 if(tmp->not_OER_visible
1130 && (cpr_flags & CPR_strict_OER_visibility)) {
1132 * Ignore not OER-visible
1138 if(tmp->not_PER_visible
1139 && (cpr_flags & CPR_strict_PER_visibility)) {
1140 if(ct->type == ACT_CA_SET) {
1143 * Ignore this separate component.
1148 * Ignore not PER-visible INTERSECTION
1155 ret = _range_intersection(range, tmp,
1156 ct->type == ACT_CA_SET, cpr_flags & CPR_strict_OER_visibility);
1164 _range_canonicalize(range);
1168 case ACT_CA_CSV: /* SIZE(1..2, 3..4) */
1169 case ACT_CA_UNI: /* SIZE(1..2) | FROM("ABCD") */
1172 * Grab the first valid constraint.
1175 for(i = 0; i < ct->el_count; i++) {
1176 tmp = asn1constraint_compute_constraint_range(dbg_name, expr_type,
1177 ct->elements[i], requested_ct_type, minmax, exmet,
1180 if(errno == ERANGE) {
1181 range->extensible = 1;
1182 range->not_OER_visible = 1;
1189 if(tmp->incompatible) {
1196 tmp->extensible |= range->extensible;
1197 tmp->not_OER_visible |= range->not_OER_visible;
1198 tmp->empty_constraint |= range->empty_constraint;
1202 range->incompatible = 1;
1207 * Merge with the rest of them.
1208 * Canonicalizator will do the union magic.
1210 for(; i < ct->el_count; i++) {
1211 tmp = asn1constraint_compute_constraint_range(dbg_name, expr_type,
1212 ct->elements[i], requested_ct_type, minmax, exmet,
1215 if(errno == ERANGE) {
1216 range->extensible = 1;
1217 range->not_OER_visible = 1;
1225 if(tmp->incompatible) {
1227 _range_canonicalize(range);
1228 range->incompatible = 1;
1232 if(tmp->empty_constraint) {
1234 * Ignore empty constraints in OR logic.
1236 range->extensible |= tmp->extensible;
1237 range->not_OER_visible |= tmp->not_OER_visible;
1242 _range_merge_in(range, tmp);
1245 _range_canonicalize(range);
1247 if(requested_ct_type == ACT_CT_FROM) {
1249 * X.696 permitted alphabet constraints are not OER-visible.
1251 range->not_OER_visible = 1;
1252 if(range->extensible) {
1255 * Extensible permitted alphabet constraints
1256 * are not PER-visible.
1258 range->not_PER_visible = 1;
1262 if(range->not_PER_visible
1263 && (cpr_flags & CPR_strict_PER_visibility)) {
1266 * If not PER-visible constraint is part of UNION,
1267 * the whole resulting constraint is not PER-visible.
1271 range = _range_clone(minmax);
1273 range = _range_new();
1274 range->not_PER_visible = 1;
1275 range->incompatible = 1;
1279 case ACT_CA_EXC: /* FROM("ABCD") EXCEPT FROM("AB") */
1281 * X.691 (PER), #9.3.19:
1282 * EXCEPT and the following value set is completely ignored.
1283 * X.696 (OER), #8.2.6:
1284 * EXCEPT keyword and the following value set is completely ignored.
1286 assert(ct->el_count >= 1);
1288 range = asn1constraint_compute_constraint_range(dbg_name, expr_type,
1289 ct->elements[0], requested_ct_type, minmax, exmet, cpr_flags);
1292 if(expr_type == ASN_BASIC_REAL) {
1293 return asn1f_real_range_from_WCOMPS(dbg_name, ct);
1295 range->incompatible = 1;
1298 range->incompatible = 1;
1304 * Expectation is not met. Return the default range.
1306 range->incompatible = 1;
1310 if(expr_type == ASN_BASIC_REAL
1311 && (vmin->type == ATV_REAL || vmax->type == ATV_REAL)) {
1312 range->incompatible = 1;
1317 range = _range_new();
1319 enum range_fill_result rfr;
1320 rfr = _range_fill(vmin, minmax, &range->left,
1321 range, requested_ct_type, ct->_lineno);
1323 rfr = _range_fill(vmax, minmax, &range->right,
1324 range, requested_ct_type, ct->_lineno);
1333 case RFR_INCOMPATIBLE:
1334 range->incompatible = 1;
1339 asn1cnst_range_t *clone;
1341 clone = _range_clone(minmax);
1343 /* Constrain parent type with given data. */
1344 ret = _range_intersection(clone, range, 1,
1345 cpr_flags & CPR_strict_OER_visibility);
1356 * Recompute elements's min/max, remove duplicates, etc.
1358 _range_canonicalize(range);
1365 asn1cnst_range_t *ra = _range_new();
1366 asn1cnst_range_t *rb = _range_new();
1368 fprintf(stderr, "Testing (MIN..20) x (10..15) => (MIN..9,10..15,16..20)\n");
1371 ra->left.type = ARE_MIN;
1372 ra->right.type = ARE_VALUE; ra->right.value = 20;
1375 rb->left.type = ARE_VALUE; rb->left.value = 10;
1376 rb->right.type = ARE_VALUE; rb->right.value = 15;
1379 * (MIN..20) x (10..15) = (MIN..9,10..15,16..20)
1381 asn1cnst_range_t *r = _range_split(ra, rb);
1383 assert(r->left.type == ARE_MIN);
1384 assert(r->right.type == ARE_MAX);
1386 assert(r->el_count == 3);
1387 assert(r->elements[0]->elements == NULL);
1388 assert(r->elements[1]->elements == NULL);
1389 assert(r->elements[2]->elements == NULL);
1392 fprintf(stderr, "[0].left = %s\n", _edge_string(&r->elements[0]->left));
1393 fprintf(stderr, "[0].right = %s\n", _edge_string(&r->elements[0]->right));
1394 assert(r->elements[0]->left.type == ARE_MIN);
1395 assert(r->elements[0]->right.type == ARE_VALUE);
1396 assert(r->elements[0]->right.value == 9);
1399 fprintf(stderr, "[1].left = %s\n", _edge_string(&r->elements[1]->left));
1400 fprintf(stderr, "[1].right = %s\n", _edge_string(&r->elements[1]->right));
1401 assert(r->elements[1]->left.type == ARE_VALUE);
1402 assert(r->elements[1]->left.value == 10);
1403 assert(r->elements[1]->right.type == ARE_VALUE);
1404 assert(r->elements[1]->right.value == 15);
1407 fprintf(stderr, "[2].left = %s\n", _edge_string(&r->elements[2]->left));
1408 fprintf(stderr, "[2].right = %s\n", _edge_string(&r->elements[2]->right));
1409 assert(r->elements[2]->left.type == ARE_VALUE);
1410 assert(r->elements[2]->left.value == 16);
1411 assert(r->elements[2]->right.type == ARE_VALUE);
1412 assert(r->elements[2]->right.value == 20);
1418 fprintf(stderr, "Testing (MIN..20) x (<min>..15) => (<min>..15,16..20)\n");
1421 ra->left.type = ARE_MIN;
1422 ra->right.type = ARE_VALUE; ra->right.value = 20;
1424 /* (<INTMAX_MIN>..15) */
1425 rb->left.type = ARE_VALUE; rb->left.value = INTMAX_MIN;
1426 rb->right.type = ARE_VALUE; rb->right.value = 15;
1428 r = _range_split(ra, rb);
1430 assert(r->left.type == ARE_MIN);
1431 assert(r->right.type == ARE_MAX);
1433 assert(r->el_count == 2);
1434 assert(r->elements[0]->elements == NULL);
1435 assert(r->elements[1]->elements == NULL);
1438 fprintf(stderr, "[0].left = %s\n", _edge_string(&r->elements[0]->left));
1439 fprintf(stderr, "[0].right = %s\n", _edge_string(&r->elements[0]->right));
1440 assert(r->elements[0]->left.type == ARE_VALUE);
1441 assert(r->elements[0]->left.value == INTMAX_MIN);
1442 assert(r->elements[0]->right.type == ARE_VALUE);
1443 assert(r->elements[0]->right.value == 15);
1446 fprintf(stderr, "[1].left = %s\n", _edge_string(&r->elements[1]->left));
1447 fprintf(stderr, "[1].right = %s\n", _edge_string(&r->elements[1]->right));
1448 assert(r->elements[1]->left.type == ARE_VALUE);
1449 assert(r->elements[1]->left.value == 16);
1450 assert(r->elements[1]->right.type == ARE_VALUE);
1451 assert(r->elements[1]->right.value == 20);