blob: 3032799b2963a2ddbff7113911a1e31feb88347c [file] [log] [blame]
Lev Walkinb45e0672004-08-18 05:42:05 +00001#include <asn1fix_internal.h>
2#include <asn1fix_constraint.h>
3#include <asn1fix_crange.h>
4
5#undef FATAL
6#define FATAL(fmt, args...) do { \
7 fprintf(stderr, "FATAL: "); \
8 fprintf(stderr, fmt, ##args); \
9 fprintf(stderr, "\n"); \
10 } while(0)
11
12void
13asn1constraint_range_free(asn1cnst_range_t *cr) {
14 if(cr) {
15 int i;
16 if(cr->elements) {
17 for(i = 0; i < cr->el_count; i++)
18 asn1constraint_range_free(cr->elements[i]);
19 free(cr->elements);
20 }
21 free(cr);
22 }
23}
24#define _range_free(foo) asn1constraint_range_free(foo)
25
26static asn1cnst_range_t *_range_new() {
27 asn1cnst_range_t *r;
28 r = calloc(1, sizeof(*r));
29 if(r) {
30 r->left.type = ARE_MIN;
31 r->right.type = ARE_MAX;
32 }
33 return r;
34}
35
36static void _range_remove_element(asn1cnst_range_t *range, int idx) {
37 assert(idx >= 0 && idx < range->el_count);
38
39 assert(!range->elements[idx]->elements);
40
41 _range_free(range->elements[idx]);
42
43 memmove(&range->elements[idx],
44 &range->elements[idx + 1],
45 (range->el_count - idx - 1)
46 * sizeof(range->elements[0])
47 );
48 range->el_count--;
49 range->elements[range->el_count] = 0; /* JIC */
50
51 if(range->el_count == 0) {
52 range->el_size = 0;
53 free(range->elements);
54 range->elements = 0;
55 }
56}
57
58static int _range_insert(asn1cnst_range_t *into, asn1cnst_range_t *cr) {
59
60 assert(!cr->elements);
61
62 if(into->el_count == into->el_size) {
63 void *p;
64 int n = into->el_size?(into->el_size << 1):4;
65 p = realloc(into->elements, n * sizeof(into->elements[0]));
66 if(p) {
67 into->el_size = n;
68 into->elements = p;
69 } else {
70 assert(p);
71 return -1;
72 }
73 }
74
75 into->elements[into->el_count++] = cr;
76 return 0;
77}
78
79static asn1cnst_range_t *_range_clone(const asn1cnst_range_t *range) {
80 asn1cnst_range_t *clone;
81 int i;
82
83 clone = _range_new();
84 if(!clone) return NULL;
85
86 *clone = *range;
87 clone->elements = 0;
88 clone->el_count = 0;
89 clone->el_size = 0;
90
91 for(i = 0; i < range->el_count; i++) {
92 asn1cnst_range_t *r = _range_clone(range->elements[i]);
93 if(!r || _range_insert(clone, r)) {
94 _range_free(clone);
95 _range_free(r);
96 return NULL;
97 }
98 }
99
100 return clone;
101}
102
103static int
104_edge_compare(const asn1cnst_edge_t *el, const asn1cnst_edge_t *er) {
105
106 switch(el->type) {
107 case ARE_MIN:
108 switch(er->type) {
109 case ARE_MIN: return 0;
110 case ARE_MAX: return -1;
111 case ARE_VALUE: return -1;
112 }
113 break;
114 case ARE_MAX:
115 switch(er->type) {
116 case ARE_MIN: return 1;
117 case ARE_MAX: return 0;
118 case ARE_VALUE: return 1;
119 }
120 break;
121 case ARE_VALUE:
122 switch(er->type) {
123 case ARE_MIN: return 1;
124 case ARE_MAX: return -1;
125 case ARE_VALUE:
126 if(el->value < er->value)
127 return -1;
128 if(el->value > er->value)
129 return 1;
130 return 0;
131 }
132 break;
133 }
134
135 return 0;
136}
137
138static int
139_range_compare(const void *a, const void *b) {
140 const asn1cnst_range_t *ra = *(const asn1cnst_range_t * const *)a;
141 const asn1cnst_range_t *rb = *(const asn1cnst_range_t * const *)b;
142 int ret;
143
144 ret = _edge_compare(&ra->left, &rb->left);
145 if(!ret) {
146 ret = _edge_compare(&ra->right, &rb->right);
147 }
148
149 return ret;
150}
151
152static char *
153_edge_value(const asn1cnst_edge_t *edge) {
154 static char buf[128];
155 *buf = '\0';
156 switch(edge->type) {
157 case ARE_MIN: strcpy(buf, "MIN"); break;
158 case ARE_MAX: strcpy(buf, "MAX"); break;
159 case ARE_VALUE:
160 snprintf(buf, sizeof(buf), "%lld", (long long)edge->value);
161 }
162 return buf;
163}
164
165static void
166_range_print(const asn1cnst_range_t *range) {
167
168 if(_edge_compare(&range->left, &range->right)) {
169 printf("(%s.", _edge_value(&range->left));
170 printf(".%s)", _edge_value(&range->right));
171 } else {
172 printf("(%s)", _edge_value(&range->left));
173 }
174
175 if(range->el_count) {
176 int i;
177 printf("-=>");
178 for(i = 0; i < range->el_count; i++)
179 _range_print(range->elements[i]);
180 }
181
182}
183
184static int
185_edge_is_within(const asn1cnst_range_t *range, const asn1cnst_edge_t *edge) {
186 int i;
187
188 for(i = -1; i < range->el_count; i++) {
189 const asn1cnst_range_t *r;
190 if(i == -1) {
191 if(range->el_count) continue;
192 r = range;
193 } else {
194 r = range->elements[i];
195 }
196 if(_edge_compare(&r->left, edge) <= 0
197 && _edge_compare(&r->right, edge) >= 0)
198 return 1;
199 }
200
201 return 0;
202}
203
204static int
205_check_edges_within(const asn1cnst_range_t *range, const asn1cnst_range_t *r) {
206
207 if(!_edge_is_within(range, &r->left)) {
208 FATAL("Constraint value %s at line %d "
209 "is not within "
210 "a parent constraint range",
211 _edge_value(&r->left),
212 r->left.lineno
213 );
214 return -1;
215 }
216
217 if(!_edge_is_within(range, &r->right)) {
218 FATAL("Constraint value %s at line %d "
219 "is not within "
220 "a parent constraint range",
221 _edge_value(&r->right),
222 r->right.lineno
223 );
224 return -1;
225 }
226
227 return 0;
228}
229
230static int _range_merge_in(asn1cnst_range_t *into, asn1cnst_range_t *cr) {
231 asn1cnst_range_t *r;
232 int prev_count = into->el_count;
233 int i;
234
235 /*
236 * Add the element OR all its children "into".
237 */
238 for(i = -1; i < cr->el_count; i++) {
239
240 if(i == -1) {
241 if(cr->el_count) continue;
242 r = cr;
243 } else {
244 r = cr->elements[i];
245 }
246
247 if(_range_insert(into, r)) {
248 into->el_count = prev_count; /* Undo */
249 return -1;
250 }
251 }
252
253 if(cr->el_count) {
254 cr->el_count = 0;
255 _range_free(cr);
256 } else {
257 /* This range is linked into "into". */
258 }
259
260 return 0;
261}
262
263static int _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) {
264 unsigned char *p, *pend;
265
266 edge->lineno = lineno;
267
268 switch(val->type) {
269 case ATV_INTEGER:
270 if(type != ACT_EL_RANGE && type != ACT_CT_SIZE) {
271 FATAL("Integer %lld value invalid "
272 "for %s constraint at line %d",
273 (long long)val->value.v_integer,
274 asn1p_constraint_type2str(type), lineno);
275 return -1;
276 }
277 edge->type = ARE_VALUE;
278 edge->value = val->value.v_integer;
279 return 0;
280 case ATV_MIN:
281 if(type != ACT_EL_RANGE && type != ACT_CT_SIZE) {
282 FATAL("MIN invalid for %s constraint at line %d",
283 asn1p_constraint_type2str(type), lineno);
284 return -1;
285 }
286 edge->type = ARE_MIN;
287 if(minmax) *edge = minmax->left;
288 edge->lineno = lineno; /* Restore lineno */
289 return 0;
290 case ATV_MAX:
291 if(type != ACT_EL_RANGE && type != ACT_CT_SIZE) {
292 FATAL("MAX invalid for %s constraint at line %d",
293 asn1p_constraint_type2str(type), lineno);
294 return -1;
295 }
296 edge->type = ARE_MAX;
297 if(minmax) *edge = minmax->right;
298 edge->lineno = lineno; /* Restore lineno */
299 return 0;
300 case ATV_FALSE:
301 case ATV_TRUE:
302 if(type != ACT_EL_RANGE) {
303 FATAL("%s is invalid for %s constraint at line %d",
304 val->type==ATV_TRUE?"TRUE":"FALSE",
305 asn1p_constraint_type2str(type),
306 lineno);
307 return -1;
308 }
309 edge->type = ARE_VALUE;
310 edge->value = (val->type==ATV_TRUE);
311 return 0;
312 case ATV_STRING:
313 if(type != ACT_CT_FROM)
314 return 0;
315 break;
Lev Walkin1ef05162004-08-25 00:42:25 +0000316 case ATV_REFERENCED:
317 FATAL("Unrecognized constraint element \"%s\" at line %d",
318 asn1f_printable_reference(val->value.reference),
319 lineno);
320 return -1;
Lev Walkinb45e0672004-08-18 05:42:05 +0000321 default:
322 FATAL("Unrecognized constraint element at line %d",
323 lineno);
324 return -1;
325 }
326
327 assert(val->type == ATV_STRING);
328
329 p = val->value.string.buf;
330 pend = p + val->value.string.size;
331 if(p == pend) return 0;
332
333 edge->type = ARE_VALUE;
334 if(val->value.string.size == 1) {
335 edge->value = *p;
336 } else {
337 /*
338 * Else this is a set:
339 * (FROM("abcdef"))
340 * However, (FROM("abc".."def")) is forbidden.
341 * See also 47.4.4.
342 */
343 asn1_integer_t vmin, vmax;
344 vmin = vmax = *p;
345 for(; p < pend; p++) {
346 asn1cnst_range_t *nr = _range_new();
347 int ret;
348 assert(nr);
349
350 if(*p < vmin) vmin = *p;
351 if(*p > vmax) vmax = *p;
352
353 ret = _range_insert(range, nr);
354 assert(ret == 0);
355
356 nr->left.type = ARE_VALUE;
357 nr->left.value = *p;
358 nr->left.lineno = lineno;
359 nr->right = nr->left;
360 }
361 edge->value = (edge == &range->right) ? vmin : vmax;
362 }
363
364 return 0;
365}
366
367/*
368 * Check if ranges contain common elements.
369 */
370static int
371_range_overlap(const asn1cnst_range_t *ra, const asn1cnst_range_t *rb) {
372 int lr, rl;
373 const asn1cnst_edge_t *ra_l = &ra->left;
374 const asn1cnst_edge_t *ra_r = &ra->right;
375 const asn1cnst_edge_t *rb_l = &rb->left;
376 const asn1cnst_edge_t *rb_r = &rb->right;
377
378 assert(_edge_compare(ra_l, ra_r) <= 0);
379 assert(_edge_compare(rb_l, rb_r) <= 0);
380
381 lr = _edge_compare(ra_l, rb_r);
382 rl = _edge_compare(ra_r, rb_l);
383
384 /*
385 * L: |---|
386 * R: |---|
387 */
388 if(lr > 0) return 0;
389
390 /*
391 * L: |---|
392 * R: |---|
393 */
394 if(rl < 0) return 0;
395
396 return 1;
397}
398
399/*
400 * (MIN..20) x (10..15) = (MIN..9,10..15,16..20)
401 */
402static asn1cnst_range_t *
403_range_split(asn1cnst_range_t *ra, const asn1cnst_range_t *rb) {
404 asn1cnst_range_t *range, *nr;
405 int ll, rr;
406
407 assert(ra);
408 assert(rb);
409 assert(!ra->el_count);
410 assert(!rb->el_count);
411
412 if(!_range_overlap(ra, rb)) {
413 errno = 0;
414 return 0;
415 }
416
417 ll = _edge_compare(&ra->left, &rb->left);
418 rr = _edge_compare(&ra->right, &rb->right);
419
420 /*
421 * L: |---|
422 * R: |-------|
423 */
424 if(ll >= 0 && rr <= 0) {
425 errno = 0;
426 return 0;
427 }
428
429 range = _range_new();
430 assert(range);
431
432 nr = _range_new();
433 assert(nr);
434
435 /*
436 * L: |---...
437 * R: |--..
438 */
439 if(ll < 0) {
440 nr->left = ra->left;
441 nr->right = rb->left;
442 if(nr->right.type == ARE_VALUE)
443 nr->right.value--;
444 _range_insert(range, nr);
445 nr = _range_new();
446 assert(nr);
447 }
448
449 /*
450 * L: ...---|
451 * R: ..--|
452 */
453 if(rr > 0) {
454 nr->left = rb->right;
455 nr->right = ra->right;
456 if(nr->left.type == ARE_VALUE)
457 nr->left.value++;
458 _range_insert(range, nr);
459 nr = _range_new();
460 assert(nr);
461 }
462
463 /*
464 * L: |---|
465 * R: |-----|
466 */
467 nr->left = ra->left;
468 nr->right = ra->right;
469 if(_edge_compare(&ra->left, &rb->left) < 0)
470 nr->left = rb->left;
471 if(_edge_compare(&ra->right, &rb->right) > 0)
472 nr->right = rb->right;
473
474 _range_insert(range, nr);
475
476 return range;
477}
478
479static int
480_range_intersection(asn1cnst_range_t *range, const asn1cnst_range_t *with, int strict_edge_check) {
481 int ret;
482 int i, j;
483
484 if(with->empty_constraint || range->empty_constraint) {
485 range->empty_constraint = 1; /* Propagate error */
486 return 0;
487 }
488
489 /*
490 * This is an AND operation.
491 */
492
493 /* If this is the only element, insert it into itself as a child */
494 if(range->el_count == 0) {
495 asn1cnst_range_t *r = _range_new();
496 r->left = range->left;
497 r->right = range->right;
498 _range_insert(range, r);
499 assert(range->el_count == 1);
500 }
501
502 /*
503 * Make sure we're dealing with sane data.
504 * G.4.2.3
505 */
506 if(strict_edge_check) {
507 for(j = -1; j < with->el_count; j++) {
508
509 if(j == -1) {
510 if(with->el_count) continue;
511 if(_check_edges_within(range, with))
512 return -1;
513 } else {
514 if(_check_edges_within(range,
515 with->elements[j]))
516 return -1;
517 }
518 }
519 }
520
521 /*
522 * Split range in pieces.
523 */
524
525 for(i = 0; i < range->el_count; i++) {
526 for(j = -1; j < with->el_count; j++) {
527 const asn1cnst_range_t *wel;
528 asn1cnst_range_t *r;
529
530 if(j == -1) {
531 if(with->el_count) continue;
532 wel = with;
533 } else {
534 wel = with->elements[j];
535 }
536
537 r = _range_split(range->elements[i], wel);
538 if(r) {
539 int ec;
540 /* Substitute the current element with a split */
541 _range_remove_element(range, i);
542 assert(r->el_count);
543 for(ec = 0; ec < r->el_count; ec++) {
544 ret = _range_insert(range, r->elements[ec]);
545 assert(ret == 0);
546 }
547 r->el_count = 0;
548 _range_free(r);
549 i--;
550 break; /* Try again from this point */
551 }
552 }
553 }
554
555 assert(range->el_count);
556
557 /*
558 * Remove pieces which aren't AND-compatible "with" range.
559 */
560
561 for(i = 0; i < range->el_count; i++) {
562 for(j = -1; j < with->el_count; j++) {
563 const asn1cnst_range_t *wel;
564
565 if(j == -1) {
566 if(with->el_count) continue;
567 wel = with;
568 } else {
569 wel = with->elements[j];
570 }
571
572 if(_range_overlap(range->elements[i], wel))
573 break;
574 }
575 if(j == with->el_count) {
576 _range_remove_element(range, i);
577 i--;
578 }
579 }
580
581 if(range->el_count == 0)
582 range->empty_constraint = 1;
583
584 return 0;
585}
586
587static int
588_range_union(asn1cnst_range_t *range) {
589 int i;
590
591 qsort(range->elements, range->el_count, sizeof(range->elements[0]),
592 _range_compare);
593
594 /*
595 * The range is sorted by the start values.
596 */
597 for(i = 1; i < range->el_count; i++) {
598 asn1cnst_range_t *ra = range->elements[i - 1];
599 asn1cnst_range_t *rb = range->elements[i];
600
601 if(_range_overlap(ra, rb)) {
602 if(_edge_compare(&ra->left, &rb->left) < 0)
603 rb->left = ra->left;
604
605 if(_edge_compare(&ra->right, &rb->right) > 0)
606 rb->right = ra->right;
607 } else {
608 /*
609 * Still, range may be joined: (1..4)(5..10).
610 * This logic is valid only for whole numbers
611 * (i.e., not REAL type, but REAL constraints
612 * are not PER-visible (X.691, 9.3.12).
613 */
614 if(ra->right.type == ARE_VALUE
615 && rb->left.type == ARE_VALUE
616 && (rb->left.value - ra->right.value) == 1) {
617 /* (1..10) */
618 rb->left = ra->left;
619 } else {
620 continue;
621 }
622 }
623
624 /*
625 * Squeeze the array by removing the ra.
626 */
627 _range_remove_element(range, i - 1);
628
629 i--; /* Retry from the current point */
630 }
631
632 return 0;
633}
634
635static int
636_range_canonicalize(asn1cnst_range_t *range) {
637
638 if(range->el_count == 0) {
639 /*
640 * Switch left and right edges, make them sorted.
641 * It might be a mild warning though.
642 */
643 if(_edge_compare(&range->left, &range->right) > 0) {
644 asn1cnst_edge_t tmp = range->left;
645 range->left = range->right;
646 range->right = tmp;
647 }
648
649 if(range->elements) {
650 free(range->elements);
651 range->elements = 0;
652 }
653 range->el_size = 0;
654 return 0;
655 }
656
657 /*
658 * Remove duplicates and overlaps by merging them in.
659 */
660 _range_union(range);
661
662 /* Refine the left edge of a parent */
663 range->left = range->elements[0]->left;
664
665 /* Refine the right edge of a parent */
666 range->right = range->elements[range->el_count - 1]->right;
667
668 /* Remove the child, if it's a single one */
669 if(range->el_count == 1) {
670 _range_remove_element(range, 0);
671 }
672
673 return 0;
674}
675
676asn1cnst_range_t *
677asn1constraint_compute_PER_range(asn1p_expr_type_e expr_type, const asn1p_constraint_t *ct, enum asn1p_constraint_type_e type, const asn1cnst_range_t *minmax, int *exmet) {
678 asn1cnst_range_t *range;
679 asn1cnst_range_t *tmp;
680 asn1p_value_t *vmin;
681 asn1p_value_t *vmax;
682 int expectation_met;
683 int ret;
684 int i;
685
686 if(!exmet) {
687 exmet = &expectation_met;
688 *exmet = 0;
689 }
690
691 /*
692 * Check if the requested constraint is compatible with expression type.
693 */
694 if(asn1constraint_compatible(expr_type, type) != 1) {
695 errno = EINVAL;
696 return 0;
697 }
698
699 /* Check arguments' validity. */
700 switch(type) {
701 case ACT_EL_RANGE:
702 if(exmet == &expectation_met)
703 *exmet = 1;
704 break;
705 case ACT_CT_FROM:
706 if(!minmax) {
707 minmax = asn1constraint_default_alphabet(expr_type);
708 if(minmax) {
709 break;
710 }
711 }
712 /* Fall through */
713 case ACT_CT_SIZE:
714 if(!minmax) {
715 static asn1cnst_range_t mm;
716 mm.left.type = ARE_VALUE;
717 mm.left.value = 0;
718 mm.right.type = ARE_MAX;
719 minmax = &mm;
720 }
721 break;
722 default:
723 errno = EINVAL;
724 return 0;
725 }
726
727 if(minmax) {
728 range = _range_clone(minmax);
729 } else {
730 range = _range_new();
731 }
732
733 if(!ct || range->not_PER_visible)
734 return range;
735
736 switch(ct->type) {
737 case ACT_EL_VALUE:
738 vmin = vmax = ct->value;
739 break;
740 case ACT_EL_RANGE:
741 case ACT_EL_LLRANGE:
742 case ACT_EL_RLRANGE:
743 case ACT_EL_ULRANGE:
744 vmin = ct->range_start;
745 vmax = ct->range_stop;
746 break;
747 case ACT_EL_EXT:
748 if(!*exmet) {
749 range->not_PER_visible = 1;
750 } else {
751 range->extensible = 1;
752 }
753 return range;
754 case ACT_CT_SIZE:
755 case ACT_CT_FROM:
756 if(type == ct->type) {
757 *exmet = 1;
758 } else {
759 range->not_PER_visible = 1;
760 return range;
761 }
762 assert(ct->el_count == 1);
763 return asn1constraint_compute_PER_range(expr_type,
764 ct->elements[0], type, minmax, exmet);
765 case ACT_CA_SET: /* (10..20)(15..17) */
766 case ACT_CA_INT: /* SIZE(1..2) ^ FROM("ABCD") */
767
768 /* AND constraints, one after another. */
769 for(i = 0; i < ct->el_count; i++) {
770 tmp = asn1constraint_compute_PER_range(expr_type,
771 ct->elements[i], type,
772 ct->type==ACT_CA_SET?range:minmax, exmet);
773 if(!tmp) {
774 _range_free(range);
775 return NULL;
776 }
777
778 if(tmp->not_PER_visible) {
779 if(ct->type == ACT_CA_SET) {
780 /*
781 * X.691, #9.3.18:
782 * Ignore this separate component.
783 */
784 } else {
785 /*
786 * X.691, #9.3.19:
787 * Ignore not PER-visible INTERSECTION
788 */
789 }
790 _range_free(tmp);
791 continue;
792 }
793
794 range->extensible |= tmp->extensible;
795
796 if(tmp->extensible && type == ACT_CT_FROM) {
797 /*
798 * X.691, #9.3.10:
799 * Extensible permitted alphabet constraints
800 * are not PER-visible.
801 */
802 range->not_PER_visible = 1;
803 }
804
805 ret = _range_intersection(range, tmp,
806 ct->type == ACT_CA_SET);
807 _range_free(tmp);
808 if(ret) {
809 _range_free(range);
810 errno = EPERM;
811 return NULL;
812 }
813 _range_canonicalize(range);
814 }
815
816 return range;
817 case ACT_CA_CSV: /* SIZE(1..2, 3..4) */
818 case ACT_CA_UNI: /* SIZE(1..2) | FROM("ABCD") */
819
820 /* Merge everything. Canonicalizator will do union magic */
821 for(i = 0; i < ct->el_count; i++) {
822 tmp = asn1constraint_compute_PER_range(expr_type,
823 ct->elements[i], type, minmax, exmet);
824 if(!tmp) {
825 _range_free(range);
826 return NULL;
827 }
828
829 if(tmp->empty_constraint) {
830 /* Ignore empty constraints */
831 _range_free(tmp);
832 continue;
833 }
834
835 range->not_PER_visible |= tmp->not_PER_visible;
836 range->extensible |= tmp->extensible;
837
838 _range_merge_in(range, tmp);
839 }
840
841 _range_canonicalize(range);
842
843 if(range->not_PER_visible) {
844 /*
845 * X.691, #9.3.19:
846 * If not PER-visible constraint is part of UNION,
847 * the resulting constraint is not PER-visible.
848 */
849 _range_free(range);
850 if(minmax)
851 range = _range_clone(minmax);
852 else
853 range = _range_new();
854 }
855
856 return range;
857 case ACT_CA_EXC: /* FROM("ABCD") EXCEPT FROM("AB") */
858 /*
859 * X.691, #9.3.19:
860 * EXCEPT and the following value set is completely ignored.
861 */
862 assert(ct->el_count >= 1);
863 _range_free(range);
864 range = asn1constraint_compute_PER_range(expr_type,
865 ct->elements[0], type, minmax, exmet);
866 return range;
867 default:
868 range->not_PER_visible = 1;
869 return range;
870 }
871
872
873 if(!*exmet) {
874 /*
875 * Expectation is not met. Return the default range.
876 */
877 range->not_PER_visible = 1;
878 return range;
879 }
880
881 _range_free(range);
882 range = _range_new();
883
884 ret = _range_fill(vmin, minmax, &range->left,
885 range, type, ct->_lineno);
Lev Walkin1ef05162004-08-25 00:42:25 +0000886 if(!ret)
887 ret = _range_fill(vmax, minmax, &range->right,
Lev Walkinb45e0672004-08-18 05:42:05 +0000888 range, type, ct->_lineno);
889 if(ret) {
890 _range_free(range);
891 errno = EPERM;
892 return NULL;
893 }
894
895 if(minmax) {
896 asn1cnst_range_t *clone;
897
898 clone = _range_clone(minmax);
899
900 /* Constrain parent type with given data. */
901 ret = _range_intersection(clone, range, 1);
902 _range_free(range);
903 if(ret) {
904 _range_free(clone);
905 errno = EPERM;
906 return NULL;
907 }
908 range = clone;
909 }
910
911 /*
912 * Recompute elements's min/max, remove duplicates, etc.
913 */
914 _range_canonicalize(range);
915
916 return range;
917}
918