1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2015 Ericsson Telecom AB
3 // All rights reserved. This program and the accompanying materials
4 // are made available under the terms of the Eclipse Public License v1.0
5 // which accompanies this distribution, and is available at
6 // http://www.eclipse.org/legal/epl-v10.html
7 ///////////////////////////////////////////////////////////////////////////////
8 #include "SimpleType.hh"
10 #include "GeneralFunctions.hh"
12 #include "TTCN3ModuleInventory.hh"
13 #include "TTCN3Module.hh"
14 #include "ComplexType.hh"
16 extern bool g_flag_used
;
17 extern bool h_flag_used
;
19 SimpleType::SimpleType(XMLParser
* a_parser
, TTCN3Module
* a_module
, ConstructType a_construct
)
20 : RootType(a_parser
, a_module
, a_construct
)
27 , element_form_as(notset
)
28 , attribute_form_as(notset
)
35 , substitutionGroup(empty_string
)
38 , addedToTypeSubstitution(false)
43 SimpleType::SimpleType(const SimpleType
& other
)
45 , builtInBase(other
.builtInBase
)
46 , length(other
.length
)
47 , pattern(other
.pattern
)
48 , enumeration(other
.enumeration
)
49 , whitespace(other
.whitespace
)
51 , element_form_as(other
.element_form_as
)
52 , attribute_form_as(other
.attribute_form_as
)
54 , outside_reference(other
.outside_reference
)
55 , in_name_only(other
.in_name_only
)
56 , fromRef(other
.fromRef
)
57 , xsdtype(other
.xsdtype
)
58 , isOptional(other
.isOptional
)
59 , substitutionGroup(other
.substitutionGroup
)
60 , subsGroup(other
.subsGroup
)
61 , typeSubsGroup(other
.typeSubsGroup
)
62 , addedToTypeSubstitution(other
.addedToTypeSubstitution
)
66 pattern
.parent
= this;
67 enumeration
.parent
= this;
68 whitespace
.p_parent
= this;
72 void SimpleType::loadWithValues() {
73 const XMLParser::TagAttributes
& atts
= parser
->getActualTagAttributes();
74 switch (parser
->getActualTagName()) {
76 type
.upload(atts
.base
);
77 setReference(atts
.base
);
78 mode
= restrictionMode
;
81 type
.upload(atts
.itemType
);
82 setReference(atts
.itemType
);
84 maxOccurs
= ULLONG_MAX
;
89 { // generating complextype from simpletype
90 ComplexType
* new_complextype
= new ComplexType(*this, ComplexType::fromTagUnion
);
91 new_complextype
->loadWithValues();
95 name
.upload(atts
.name
);
96 type
.upload(atts
.type
);
97 setReference(atts
.type
, true);
99 applyDefaultAttribute(atts
.default_
);
100 applyFixedAttribute(atts
.fixed
);
102 applyAbstractAttribute(atts
.abstract
);
103 applySubstitionGroupAttribute(atts
.substitionGroup
);
104 applyBlockAttribute(atts
.block
);
105 //This shall be the last instruction always
106 applyNillableAttribute(atts
.nillable
);
109 name
.upload(atts
.name
);
110 type
.upload(atts
.type
);
111 xsdtype
= n_attribute
;
112 setReference(atts
.type
, true);
113 applyDefaultAttribute(atts
.default_
);
114 applyFixedAttribute(atts
.fixed
);
117 name
.upload(atts
.name
);
120 { // generating complextype from simpletype
121 ComplexType
* new_complextype
= new ComplexType(*this, ComplexType::fromTagComplexType
);
122 new_complextype
->loadWithValues();
126 if (mode
== listMode
) {
127 minOccurs
= strtoull(atts
.value
.c_str(), NULL
, 0);
128 maxOccurs
= strtoull(atts
.value
.c_str(), NULL
, 0);
131 length
.facet_minLength
= strtoull(atts
.value
.c_str(), NULL
, 0);
132 length
.facet_maxLength
= strtoull(atts
.value
.c_str(), NULL
, 0);
133 length
.modified
= true;
136 if (mode
== listMode
) {
137 minOccurs
= strtoull(atts
.value
.c_str(), NULL
, 0);
140 length
.facet_minLength
= strtoull(atts
.value
.c_str(), NULL
, 0);
141 length
.modified
= true;
144 if (mode
== listMode
) {
145 maxOccurs
= strtoull(atts
.value
.c_str(), NULL
, 0);
148 length
.facet_maxLength
= strtoull(atts
.value
.c_str(), NULL
, 0);
149 length
.modified
= true;
152 pattern
.facet
= atts
.value
;
153 pattern
.modified
= true;
156 enumeration
.facets
.push_back(atts
.value
);
157 enumeration
.modified
= true;
160 whitespace
.facet
= atts
.value
;
161 whitespace
.modified
= true;
164 if (atts
.value
== "NaN") {
165 value
.not_a_number
= true;
166 } else if (atts
.value
== "-INF") {
167 value
.facet_minInclusive
= -DBL_MAX
;
168 } else if (atts
.value
== "INF") {
169 value
.facet_minInclusive
= DBL_MAX
;
171 value
.facet_minInclusive
= stringToLongDouble(atts
.value
.c_str());
173 value
.modified
= true;
176 if (atts
.value
== "NaN") {
177 value
.not_a_number
= true;
178 } else if (atts
.value
== "-INF") {
179 value
.facet_maxInclusive
= -DBL_MAX
;
180 } else if (atts
.value
== "INF") {
181 value
.facet_maxInclusive
= DBL_MAX
;
183 value
.facet_maxInclusive
= stringToLongDouble(atts
.value
.c_str());
185 value
.modified
= true;
188 if (atts
.value
== "NaN") {
190 } else if (atts
.value
== "-INF") {
191 value
.facet_minExclusive
= -DBL_MAX
;
192 } else if (atts
.value
== "INF") {
195 value
.facet_minExclusive
= stringToLongDouble(atts
.value
.c_str());
197 value
.modified
= true;
198 value
.lowerExclusive
= true;
201 if (atts
.value
== "NaN") {
203 } else if (atts
.value
== "-INF") {
205 } else if (atts
.value
== "INF") {
206 value
.facet_maxExclusive
= DBL_MAX
;
208 value
.facet_maxExclusive
= stringToLongDouble(atts
.value
.c_str());
210 value
.modified
= true;
211 value
.upperExclusive
= true;
214 value
.facet_totalDigits
= strtoul(atts
.value
.c_str(), NULL
, 0);
215 value
.modified
= true;
217 case n_fractionDigits
:
218 //addVariant(V_fractionDigits, atts.value);
221 addComment(Mstring("LABEL:"));
224 addComment(Mstring("DEFINITION:"));
231 void SimpleType::applyDefaultAttribute(const Mstring
& default_value
) {
232 if (!default_value
.empty()) {
233 value
.default_value
= default_value
;
234 const Mstring nameT
= type
.originalValueWoPrefix
.getValueWithoutPrefix(':');
235 //Not supported for hexBinary and base64Binary
236 if (nameT
!= "hexBinary" && nameT
!= "base64Binary") {
237 addVariant(V_defaultForEmpty
, default_value
);
242 void SimpleType::applyFixedAttribute(const Mstring
& fixed_value
) {
243 if (!fixed_value
.empty()) {
244 value
.fixed_value
= fixed_value
;
245 value
.modified
= true;
246 const Mstring nameT
= type
.originalValueWoPrefix
.getValueWithoutPrefix(':');
247 //Not supported for hexBinary and base64Binary
248 if (nameT
!= "hexBinary" && nameT
!= "base64Binary") {
249 addVariant(V_defaultForEmpty
, fixed_value
);
254 void SimpleType::applyNillableAttribute(const bool nillable
) {
256 ComplexType
* new_complextype
= new ComplexType(*this, ComplexType::fromTagNillable
); // generating complextype from simpletype
257 new_complextype
->loadWithValues();
261 void SimpleType::applyAbstractAttribute(const bool abstract_value
) {
262 if (abstract_value
) {
263 addVariant(V_abstract
);
267 void SimpleType::applySubstitionGroupAttribute(const Mstring
& substitution_group
){
268 if(!substitution_group
.empty()){
269 substitutionGroup
= substitution_group
;
273 void SimpleType::applyBlockAttribute(const BlockValue block_
){
274 if(block_
== not_set
){
275 block
= getModule()->getBlockDefault();
281 void SimpleType::addToSubstitutions(){
282 if(!g_flag_used
|| substitutionGroup
.empty()){
285 SimpleType
* st_
= (SimpleType
*) TTCN3ModuleInventory::getInstance().lookup(this, substitutionGroup
, want_BOTH
);
287 printError(module
->getSchemaname(), name
.convertedValue
,
288 "Reference for a non-defined type: " + substitutionGroup
);
289 TTCN3ModuleInventory::getInstance().incrNumErrors();
292 SimpleType
* st
= (SimpleType
*)st_
;
293 if(st
->getSubstitution() != NULL
){
294 st
= st
->getSubstitution();
297 st
->referenceResolving();
298 substitutionGroup
= empty_string
;
300 if(st
->subsGroup
== NULL
){
301 ComplexType
* head_element
= new ComplexType(*st
, ComplexType::fromTagSubstitution
);
302 for(List
<SimpleType
*>::iterator simpletype
= st
->nameDepList
.begin(); simpletype
; simpletype
= simpletype
->Next
){
303 head_element
->getNameDepList().push_back(simpletype
->Data
);
305 st
->nameDepList
.clear();
306 st
->getModule()->addMainType(head_element
);
307 head_element
->addVariant(V_untagged
);
308 head_element
->addSubstitution(st
);
309 head_element
->addSubstitution(this);
310 //if st->subsGroup == this, then it is a generated subs group
311 st
->subsGroup
= head_element
;
314 st
->subsGroup
->addSubstitution(this);
318 void SimpleType::addToTypeSubstitutions() {
319 //If the user did not request type substitution generation or
320 //the type is already added to type substitution
321 if(!h_flag_used
|| addedToTypeSubstitution
){
324 //Only available if it is a restricion or extension
325 if(mode
!= extensionMode
&& mode
!= restrictionMode
){
328 //Only top level complexTypes or simpleTypes, ergo no elements
329 if(parent
!= NULL
|| hasVariant(Mstring("\"element\""))){
333 //It would be nice if here outside_reference.resolved to everything
335 SimpleType
* st
= (SimpleType
*)outside_reference
.get_ref();
336 if(st
== NULL
&& !isBuiltInType(type
.convertedValue
)){
337 //Not even a reference, and not a built in type
339 }else if(st
== NULL
&& isBuiltInType(type
.convertedValue
)){
340 st
= new SimpleType(parser
, module
, construct
);
341 st
->type
.upload(type
.convertedValue
);
342 st
->name
.upload(type
.convertedValue
);
343 st
->typeSubsGroup
= findBuiltInTypeInStoredTypeSubstitutions(type
.convertedValue
);
344 outside_reference
.set_resolved(st
);
345 //Add this decoy type to the maintypes -> module will free st
346 //st->setInvisible();
347 module
->addMainType(st
);
351 addedToTypeSubstitution
= true;
352 st
->addToTypeSubstitutions();
353 //If type substitution is NULL then we need to create the union
354 if(st
->getTypeSubstitution() == NULL
){
355 ComplexType
* head_element
= new ComplexType(*st
, ComplexType::fromTypeSubstitution
);
356 head_element
->getNameDepList().clear();
357 for(List
<SimpleType
*>::iterator simpletype
= st
->nameDepList
.begin(), nextST
; simpletype
; simpletype
= nextST
){
358 nextST
= simpletype
->Next
;
359 //Don't add if it is in a type substitution
360 if(simpletype
->Data
->getTypeSubstitution() == NULL
){
361 head_element
->getNameDepList().push_back(simpletype
->Data
);
362 st
->getNameDepList().remove(simpletype
);
366 st
->getModule()->addMainType(head_element
);
367 head_element
->addVariant(V_useType
);
368 //For cascading type substitution
369 if(st
->outside_reference
.get_ref() != NULL
&& ((ComplexType
*)st
->outside_reference
.get_ref())->getTypeSubstitution() != NULL
){
370 head_element
->setParentTypeSubsGroup(((ComplexType
*)st
->outside_reference
.get_ref())->getTypeSubstitution());
372 head_element
->addTypeSubstitution(st
);
373 head_element
->addTypeSubstitution(this);
375 //Check to find if there was already an element reference with this type
376 for(List
<typeNameDepList
>::iterator str
= module
->getElementTypes().begin(); str
; str
= str
->Next
){
377 Mstring prefix
= str
->Data
.type
.getPrefix(':');
378 Mstring value_
= str
->Data
.type
.getValueWithoutPrefix(':');
380 if((value_
== st
->getName().convertedValue
.getValueWithoutPrefix(':') && prefix
== module
->getTargetNamespaceConnector()) ||
381 (isBuiltInType(value_
) && !isBuiltInType(st
->getType().convertedValue
) && value_
== st
->getType().convertedValue
&& prefix
== module
->getTargetNamespaceConnector())){
382 //Push the namedeplist
383 for(List
<SimpleType
*>::iterator simpletype
= str
->Data
.nameDepList
.begin(); simpletype
; simpletype
= simpletype
->Next
){
384 head_element
->getNameDepList().push_back(simpletype
->Data
);
387 str
->Data
.typeSubsGroup
= head_element
;
392 head_element
->setInvisible();
394 st
->typeSubsGroup
= head_element
;
395 st
->getModule()->addStoredTypeSubstitution(head_element
);
397 st
->getTypeSubstitution()->addTypeSubstitution(this);
400 //Make the decoy invisible
405 void SimpleType::collectElementTypes(SimpleType
* found_ST
, ComplexType
* found_CT
){
406 //Only if type substitution is enabled and it is a top level(simpletype) element or
407 //it is a not top level element(complextype)
408 if(h_flag_used
&& (hasVariant(Mstring("\"element\"")) || xsdtype
== n_element
)){
409 SimpleType
* st
= NULL
, *nameDep
= NULL
;
410 Mstring uri
, value_
, type_
;
411 if(found_ST
!= NULL
|| found_CT
!= NULL
){
412 // st := found_ST or found_CT, which is not null
413 st
= found_ST
!= NULL
? found_ST
: found_CT
;
414 uri
= outside_reference
.get_uri();
415 value_
= outside_reference
.get_val();
417 }else if(isBuiltInType(type
.convertedValue
)){
419 uri
= module
->getTargetNamespace();
420 value_
= type
.convertedValue
;
421 if(outside_reference
.empty()){
425 type_
= outside_reference
.get_val();
428 //It is not possible to reach here (should be)
431 type_
= type_
.getValueWithoutPrefix(':');
433 const Mstring typeSubsName
= value_
+ Mstring("_derivations");
434 //Find if we already have a substitution type to this element reference
435 for(List
<ComplexType
*>::iterator
complex = st
->getModule()->getStoredTypeSubstitutions().begin(); complex; complex = complex->Next
){
437 if(uri
== st
->getModule()->getTargetNamespace() && typeSubsName
== complex->Data
->getName().convertedValue
){
438 complex->Data
->setVisible();
439 if(st
->getXsdtype() != n_NOTSET
&& this == st
){ //otherwise records would be renamed too
440 complex->Data
->addToNameDepList(st
);
441 ((ComplexType
*)st
)->setNameDep(nameDep
);
447 //Add the reference, to future possible type substitution
449 Mstring prefix
= st
->getModule()->getTargetNamespaceConnector();
450 if(prefix
!= empty_string
){
453 st
->getModule()->addElementType(prefix
+ type_
, nameDep
);
458 ComplexType
* SimpleType::findBuiltInTypeInStoredTypeSubstitutions(const Mstring
& builtInType
){
459 const Mstring typeSubsName
= builtInType
.getValueWithoutPrefix(':') + Mstring("_derivations");
460 for(List
<ComplexType
*>::iterator
complex = module
->getStoredTypeSubstitutions().begin(); complex; complex = complex->Next
){
461 if(typeSubsName
== complex->Data
->getName().convertedValue
){
462 return complex->Data
;
469 void SimpleType::setReference(const Mstring
& ref
, bool only_name_dependency
) {
473 if (isBuiltInType(ref
)) {
474 builtInBase
= ref
.getValueWithoutPrefix(':');
475 if (name
.convertedValue
.empty()) {
478 if (type
.convertedValue
.empty() || type
.convertedValue
== "anySimpleType") {
479 type
.upload(ref
.getValueWithoutPrefix(':'));
485 Mstring refPrefix
= ref
.getPrefix(':');
486 Mstring refValue
= ref
.getValueWithoutPrefix(':');
488 // Find the URI amongst the known namespace URIs
489 List
<NamespaceType
>::iterator declNS
;
490 for (declNS
= module
->getDeclaredNamespaces().begin(); declNS
; declNS
= declNS
->Next
) {
491 if (refPrefix
== declNS
->Data
.prefix
) {
492 refUri
= declNS
->Data
.uri
;
497 // FIXME: can this part be moved above the search ?
498 if (refUri
.empty()) { // not found
499 if (refPrefix
== "xml") {
500 refUri
= "http://www.w3.org/XML/1998/namespace";
501 } else if (refPrefix
== "xmlns") {
502 refUri
= "http://www.w3.org/2000/xmlns";
503 } else if (refPrefix
.empty() && module
->getTargetNamespace() == "NoTargetNamespace") {
504 refUri
= "NoTargetNamespace";
508 if (refUri
.empty()) { // something is incorrect - unable to find the uri to the given prefix
509 if (refPrefix
.empty()) {
510 printError(module
->getSchemaname(), parser
->getActualLineNumber(),
511 Mstring("The absent namespace must be imported because "
512 "it is not the same as the target namespace of the current schema."));
513 parser
->incrNumErrors();
516 printError(module
->getSchemaname(), parser
->getActualLineNumber(),
517 "The value \'" + ref
+ "\' is incorrect: "
518 "A namespace prefix does not denote any URI.");
519 parser
->incrNumErrors();
524 if (only_name_dependency
) {
528 outside_reference
.load(refUri
, refValue
, &declNS
->Data
);
531 void SimpleType::referenceResolving() {
532 if (outside_reference
.empty() || outside_reference
.is_resolved()){
533 addToTypeSubstitutions();
534 collectElementTypes();
536 if(outside_reference
.empty() && substitutionGroup
.empty()) return;
537 if (outside_reference
.is_resolved()) return;
539 if(!outside_reference
.empty()){
540 SimpleType
* found_ST
= static_cast<SimpleType
*> (
541 TTCN3ModuleInventory::getInstance().lookup(this, want_ST
));
542 ComplexType
* found_CT
= static_cast<ComplexType
*> (
543 TTCN3ModuleInventory::getInstance().lookup(this, want_CT
));
544 // It _is_ possible to find both
545 collectElementTypes(found_ST
, found_CT
);
546 if (found_ST
!= NULL
) {
547 if (!found_ST
->outside_reference
.empty() && !found_ST
->outside_reference
.is_resolved() && found_ST
!= this) {
548 found_ST
->referenceResolving();
549 if(!found_ST
->outside_reference
.is_resolved()){
550 found_ST
->outside_reference
.set_resolved(NULL
);
553 referenceForST(found_ST
);
554 addToTypeSubstitutions();
555 if (!isBuiltInType(type
.convertedValue
)) {
556 found_ST
->addToNameDepList(this);
558 } else if (found_CT
!= NULL
) {
559 referenceForCT(found_CT
);
560 addToTypeSubstitutions();
561 if (!isBuiltInType(type
.convertedValue
)) {
562 found_CT
->addToNameDepList(this);
565 printError(module
->getSchemaname(), name
.convertedValue
,
566 "Reference for a non-defined type: " + outside_reference
.repr());
567 TTCN3ModuleInventory::getInstance().incrNumErrors();
568 outside_reference
.set_resolved(NULL
);
570 addToSubstitutions();
572 addToSubstitutions();
576 void SimpleType::referenceForST(SimpleType
* found_ST
) {
577 outside_reference
.set_resolved(found_ST
);
582 if (construct
== c_element
)
585 if (mode
== listMode
)
588 if (!found_ST
->builtInBase
.empty()) {
589 builtInBase
= found_ST
->builtInBase
;
592 length
.applyReference(found_ST
->length
);
593 pattern
.applyReference(found_ST
->pattern
);
594 enumeration
.applyReference(found_ST
->enumeration
);
595 whitespace
.applyReference(found_ST
->whitespace
);
596 value
.applyReference(found_ST
->value
);
598 mode
= found_ST
->mode
;
599 if (found_ST
->mode
!= listMode
) {
600 type
.upload(found_ST
->getType().convertedValue
);
604 void SimpleType::referenceForCT(ComplexType
* found_CT
) {
605 outside_reference
.set_resolved(found_CT
);
610 // Section 7.5.3 Example5
611 if (found_CT
->getType().convertedValue
== Mstring("union") && mode
== restrictionMode
) {
612 for (List
<Mstring
>::iterator facet
= enumeration
.facets
.begin(); facet
; facet
= facet
->Next
) {
613 enumeration
.items_misc
.push_back(facet
->Data
);
616 size_t value_size
= value
.items_with_value
.size(); //Used to check changes
617 enumeration
.modified
= false;
618 for (List
<Mstring
>::iterator itemMisc
= enumeration
.items_misc
.begin(); itemMisc
; itemMisc
= itemMisc
->Next
) {
619 size_t act_size
= value
.items_with_value
.size(); //Used to detect if field did not match any field
620 for (List
<ComplexType
*>::iterator field
= found_CT
->complexfields
.begin(); field
; field
= field
->Next
) {
621 if (isIntegerType(field
->Data
->getType().convertedValue
)) {
624 sscanf(itemMisc
->Data
.c_str(), "%d%n", &val
, &read_chars
);
625 if ((size_t) read_chars
== itemMisc
->Data
.size()) {
626 expstring_t tmp_string
= mprintf("{%s:=%d}",
627 field
->Data
->getName().convertedValue
.c_str(), val
);
628 value
.items_with_value
.push_back(Mstring(tmp_string
));
633 if (isFloatType(field
->Data
->getType().convertedValue
)) {
636 sscanf(itemMisc
->Data
.c_str(), "%f%n", &val
, &read_chars
);
637 if ((size_t) read_chars
== itemMisc
->Data
.size()) {
638 expstring_t tmp_string
= mprintf("{%s:=%f}",
639 field
->Data
->getName().convertedValue
.c_str(), val
);
640 value
.items_with_value
.push_back(Mstring(tmp_string
));
645 if (isTimeType(field
->Data
->getType().convertedValue
)) {
646 if (matchDates(itemMisc
->Data
.c_str(), field
->Data
->getType().originalValueWoPrefix
.c_str())) {
647 expstring_t tmp_string
= mprintf("{%s:=\"%s\"}",
648 field
->Data
->getName().convertedValue
.c_str(), itemMisc
->Data
.c_str());
649 value
.items_with_value
.push_back(Mstring(tmp_string
));
654 if (isStringType(field
->Data
->getType().convertedValue
)) {
655 expstring_t tmp_string
= mprintf("{%s:=\"%s\"}",
656 field
->Data
->getName().convertedValue
.c_str(), itemMisc
->Data
.c_str());
657 value
.items_with_value
.push_back(Mstring(tmp_string
));
662 if (act_size
== value
.items_with_value
.size()) {
663 printWarning(getModule()->getSchemaname(), getName().convertedValue
,
664 Mstring("The following enumeration did not match any field: ") + itemMisc
->Data
+ Mstring("."));
665 TTCN3ModuleInventory::getInstance().incrNumWarnings();
669 if (value_size
!= value
.items_with_value
.size()) {
670 value
.modified
= true;
674 void SimpleType::nameConversion(NameConversionMode conversion_mode
, const List
<NamespaceType
> & ns
) {
676 switch (conversion_mode
) {
678 nameConversion_names();
681 nameConversion_types(ns
);
688 void SimpleType::nameConversion_names() {
689 Mstring res
, var(module
->getTargetNamespace());
690 XSDName2TTCN3Name(name
.convertedValue
, TTCN3ModuleInventory::getInstance().getTypenames(), type_name
, res
, var
);
691 name
.convertedValue
= res
;
692 addVariant(V_onlyValue
, var
);
693 for (List
<SimpleType
*>::iterator st
= nameDepList
.begin(); st
; st
= st
->Next
) {
694 st
->Data
->setTypeValue(res
);
698 void SimpleType::nameConversion_types(const List
<NamespaceType
> & ns
) {
699 if (type
.convertedValue
== "record" || type
.convertedValue
== "set"
700 || type
.convertedValue
== "union" || type
.convertedValue
== "enumerated") return;
702 Mstring prefix
= type
.convertedValue
.getPrefix(':');
703 Mstring value_str
= type
.convertedValue
.getValueWithoutPrefix(':');
706 for (List
<NamespaceType
>::iterator namesp
= ns
.begin(); namesp
; namesp
= namesp
->Next
) {
707 if (prefix
== namesp
->Data
.prefix
) {
708 uri
= namesp
->Data
.uri
;
713 QualifiedName
tmp(uri
, value_str
);
715 QualifiedNames::iterator origTN
= TTCN3ModuleInventory::getInstance().getTypenames().begin();
716 for (; origTN
; origTN
= origTN
->Next
) {
717 if (tmp
== origTN
->Data
) {
718 QualifiedName
tmp_name(module
->getTargetNamespace(), name
.convertedValue
);
719 if (tmp_name
== origTN
->Data
)
720 continue; // get a new type name
725 if (origTN
!= NULL
) {
726 setTypeValue(origTN
->Data
.name
);
727 // This ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ is always value_str
728 // The only effect here is to remove the "xs:" prefix from type.convertedValue,
729 // otherwise the new value is always the same as the old.
732 XSDName2TTCN3Name(value_str
, TTCN3ModuleInventory::getInstance().getTypenames(), type_reference_name
, res
, var
);
737 void SimpleType::finalModification() {
739 length
.applyFacets();
740 pattern
.applyFacet();
741 whitespace
.applyFacet();
742 enumeration
.applyFacets();
744 if (module
->getElementFormDefault() == qualified
&&
745 element_form_as
== unqualified
) {
746 addVariant(V_formAs
, Mstring("unqualified"));
747 } else if (module
->getElementFormDefault() != qualified
&&
748 element_form_as
== qualified
) {
749 addVariant(V_formAs
, Mstring("qualified"));
752 if (module
->getAttributeFormDefault() == qualified
&&
753 attribute_form_as
== unqualified
) {
754 addVariant(V_formAs
, Mstring("unqualified"));
755 } else if (module
->getAttributeFormDefault() != qualified
&&
756 attribute_form_as
== qualified
) {
757 addVariant(V_formAs
, Mstring("qualified"));
760 if (type
.originalValueWoPrefix
== Mstring("boolean")) {
761 addVariant(V_onlyValueHidden
, Mstring("\"text 'false' as '0'\""));
762 addVariant(V_onlyValueHidden
, Mstring("\"text 'true' as '1'\""));
765 isOptional
= isOptional
|| (minOccurs
== 0 && maxOccurs
== 0);
767 // If the type name is the same as the identifier then we have to prefix it
768 // with the module identifier.
769 if (type
.convertedValue
== name
.convertedValue
&& !outside_reference
.empty()) {
770 List
<const TTCN3Module
*>::iterator import_module
= module
->getImportedModules().begin();
771 for (; import_module
; import_module
= import_module
->Next
) {
772 if (import_module
->Data
->getTargetNamespace() == outside_reference
.get_uri()) {
773 type
.upload(import_module
->Data
->getModulename() + Mstring(".") + type
.convertedValue
);
780 bool SimpleType::hasUnresolvedReference() {
781 if (!outside_reference
.empty() && !outside_reference
.is_resolved()) {
788 void SimpleType::applyRefAttribute(const Mstring
& ref_value
) {
789 if (!ref_value
.empty()) {
790 setReference(ref_value
);
795 void SimpleType::printToFile(FILE * file
) {
802 fputs("type ", file
);
803 if(enumeration
.modified
&& hasVariant(Mstring("\"list\""))){
804 printMinOccursMaxOccurs(file
, false);
805 fprintf(file
, "enumerated\n{\n");
806 enumeration
.sortFacets();
807 enumeration
.printToFile(file
);
808 fprintf(file
, "\n} %s", name
.convertedValue
.c_str());
809 } else if (enumeration
.modified
) {
810 if (isFloatType(builtInBase
)) {
811 fprintf(file
, "%s %s (", type
.convertedValue
.c_str(), name
.convertedValue
.c_str());
812 enumeration
.sortFacets();
813 enumeration
.printToFile(file
);
816 fprintf(file
, "enumerated %s\n{\n", name
.convertedValue
.c_str());
817 enumeration
.sortFacets();
818 enumeration
.printToFile(file
);
822 printMinOccursMaxOccurs(file
, false);
824 int multiplicity
= multi(module
, outside_reference
, this);
825 const RootType
*type_ref
= outside_reference
.get_ref();
826 if ((multiplicity
> 1) && type_ref
827 && type_ref
->getModule() != module
) {
828 fprintf(file
, "%s.", type_ref
->getModule()->getModulename().c_str());
831 fprintf(file
, "%s %s",
832 type
.convertedValue
.c_str(), name
.convertedValue
.c_str());
833 pattern
.printToFile(file
);
834 value
.printToFile(file
);
835 length
.printToFile(file
);
837 enumeration
.insertVariants();
839 fputs(";\n\n\n", file
);
842 void SimpleType::dump(unsigned int depth
) const {
843 static const char *modes
[] = {
844 "", "restriction", "extension", "list"
846 fprintf(stderr
, "%*s SimpleType '%s' -> '%s' at %p\n", depth
* 2, "",
847 name
.originalValueWoPrefix
.c_str(), name
.convertedValue
.c_str(),
849 fprintf(stderr
, "%*s type '%s' -> '%s'\n", depth
* 2, "",
850 type
.originalValueWoPrefix
.c_str(), type
.convertedValue
.c_str());
852 if (mode
!= noMode
) {
853 fprintf(stderr
, "%*s %s, base='%s'\n", depth
* 2, "", modes
[mode
], builtInBase
.c_str());
856 // fprintf (stderr, "%*s rfo='%s' n_d='%s'\n", depth * 2, "",
857 // reference_for_other.c_str(), name_dependency.c_str());
860 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
862 LengthType::LengthType(SimpleType
* a_simpleType
)
863 : parent(a_simpleType
)
866 , facet_maxLength(ULLONG_MAX
)
868 , upper(ULLONG_MAX
) {
871 void LengthType::applyReference(const LengthType
& other
) {
872 if (!modified
) modified
= other
.modified
;
873 if (other
.facet_minLength
> facet_minLength
) facet_minLength
= other
.facet_minLength
;
874 if (other
.facet_maxLength
< facet_maxLength
) facet_maxLength
= other
.facet_maxLength
;
877 void LengthType::applyFacets() // only for string types and list types without QName
879 if (!modified
) return;
881 switch (parent
->getMode()) {
882 case SimpleType::restrictionMode
:
884 const Mstring
& base
= parent
->getBuiltInBase();
885 if ((isStringType(base
) || (isSequenceType(base
) && base
!= "QName") || isAnyType(base
)) || base
.empty()) {
886 lower
= facet_minLength
;
887 upper
= facet_maxLength
;
889 printWarning(parent
->getModule()->getSchemaname(), parent
->getName().convertedValue
,
890 Mstring("Length restriction is not supported on type '") + base
+ Mstring("'."));
891 TTCN3ModuleInventory::getInstance().incrNumWarnings();
895 case SimpleType::extensionMode
:
896 case SimpleType::listMode
:
897 lower
= facet_minLength
;
898 upper
= facet_maxLength
;
900 case SimpleType::noMode
:
904 printError(parent
->getModule()->getSchemaname(), parent
->getName().convertedValue
,
905 Mstring("The upper boundary of length restriction cannot be smaller than the lower boundary."));
906 TTCN3ModuleInventory::getInstance().incrNumErrors();
911 void LengthType::printToFile(FILE * file
) const {
912 if (!modified
) return;
913 if (parent
->getEnumeration().modified
) return;
915 if (lower
== upper
) {
916 fprintf(file
, " length(%llu)", lower
);
918 fprintf(file
, " length(%llu .. ", lower
);
920 if (upper
== ULLONG_MAX
) {
921 fputs("infinity", file
);
923 fprintf(file
, "%llu", upper
);
930 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
932 PatternType::PatternType(SimpleType
* a_simpleType
)
933 : parent(a_simpleType
)
939 void PatternType::applyReference(const PatternType
& other
) {
940 if (!modified
) modified
= other
.modified
;
941 if (facet
.empty()) facet
= other
.facet
;
944 void PatternType::applyFacet() // only for time types and string types without hexBinary
946 if (!modified
) return;
948 const Mstring
& base
= parent
->getBuiltInBase();
949 if (((isStringType(base
) && base
!= "hexBinary") || isTimeType(base
) || isAnyType(base
)) || base
.empty()) {
950 // XSD pattern to TTCN-3 pattern; ETSI ES 201 873-9 clause 6.1.4
951 // FIXME a proper scanner is needed, e.g. from flex
953 for (size_t i
= 0; i
!= facet
.size(); ++i
) {
957 value
+= charclass
? "\\("
961 value
+= charclass
? "\\)"
968 value
+= charclass
? "\\^"
979 case '.': // any character
980 value
+= charclass
? '.'
983 case '*': // 0 or more
984 value
+= '*'; //#(0,)
987 value
+= '+'; //#(1,)
990 value
+= charclass
? "?"
998 if (charclass
== 0) {
1001 while (facet
[i
+ k
] != '}') {
1006 match
= sscanf(s
.c_str(), "%i,%i", &a
, &b
);
1007 if (match
== 1 || match
== 2) {
1021 value
+= charclass
? "\\}"
1026 // Appendix G1.1 of XML Schema Datatypes: Character class escapes;
1027 // specifically, http://www.w3.org/TR/xmlschema11-2/#nt-MultiCharEsc
1028 char cn
= facet
[i
+ 1];
1031 value
+= charclass
? "\\w\\d.\\-_:"
1035 value
+= charclass
? "^\\w\\d.\\-_:"
1036 : "[^\\w\\d.\\-_:]";
1039 value
+= charclass
? "^\\d"
1043 value
+= charclass
? "\\w\\d:"
1047 value
+= charclass
? "^\\w\\d:"
1051 value
+= charclass
? "\\q{0,0,0,20}\\q{0,0,0,10}\\t\\r"
1052 : "[\\q{0,0,0,20}\\q{0,0,0,10}\\t\\r]";
1055 value
+= charclass
? "^\\q{0,0,0,20}\\q{0,0,0,10}\\t\\r"
1056 : "[^\\q{0,0,0,20}\\q{0,0,0,10}\\t\\r]";
1059 value
+= charclass
? "^\\w"
1063 printWarning(parent
->getModule()->getSchemaname(), parent
->getName().convertedValue
,
1064 Mstring("Character categories and blocks are not supported."));
1065 TTCN3ModuleInventory::getInstance().incrNumWarnings();
1067 Mstring("Pattern is not converted due to using character categories and blocks in patterns is not supported."));
1075 // backslash + another: pass unmodified; this also handles \d and \w
1084 if (facet
[i
+ 1] == '#') { // &#....;
1087 while (facet
[i
+ k
] != ';') {
1091 long long int d
= atoll(s
.c_str());
1092 if (d
< 0 || d
> 2147483647) {
1093 printError(parent
->getModule()->getSchemaname(), parent
->getName().convertedValue
,
1094 Mstring("Invalid unicode character."));
1095 TTCN3ModuleInventory::getInstance().incrNumErrors();
1097 unsigned char group
= (d
>> 24) & 0xFF;
1098 unsigned char plane
= (d
>> 16) & 0xFF;
1099 unsigned char row
= (d
>> 8) & 0xFF;
1100 unsigned char cell
= d
& 0xFF;
1102 expstring_t res
= mprintf("\\q{%d, %d, %d, %d}", group
, plane
, row
, cell
);
1107 // else fall through
1108 default: //just_copy:
1114 printWarning(parent
->getModule()->getSchemaname(), parent
->getName().convertedValue
,
1115 Mstring("Pattern restriction is not supported on type '") + base
+ Mstring("'."));
1116 TTCN3ModuleInventory::getInstance().incrNumWarnings();
1120 void PatternType::printToFile(FILE * file
) const {
1121 if (!modified
|| value
.empty()) return;
1122 if (parent
->getEnumeration().modified
) return;
1124 fprintf(file
, " (pattern \"%s\")", value
.c_str());
1127 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1129 EnumerationType::EnumerationType(SimpleType
* a_simpleType
)
1130 : parent(a_simpleType
)
1141 void EnumerationType::applyReference(const EnumerationType
& other
) {
1142 if (!modified
) modified
= other
.modified
;
1143 for (List
<Mstring
>::iterator facet
= other
.facets
.begin(); facet
; facet
= facet
->Next
) {
1144 facets
.push_back(facet
->Data
);
1148 void EnumerationType::applyFacets() // string types, integer types, float types, time types
1150 if (!modified
) return;
1152 facets
.remove_dups();
1154 const Mstring
& base
= parent
->getBuiltInBase();
1156 if (isStringType(base
)) // here length restriction is applicable
1158 List
<Mstring
> text_variants
;
1159 for (List
<Mstring
>::iterator facet
= facets
.begin(); facet
; facet
= facet
->Next
) {
1160 const LengthType
& length
= parent
->getLength();
1161 if (length
.lower
<= facet
->Data
.size() && facet
->Data
.size() <= length
.upper
) {
1163 XSDName2TTCN3Name(facet
->Data
, items_string
, enum_id_name
, res
, var
);
1164 text_variants
.push_back(var
);
1167 text_variants
.sort();
1168 for (List
<Mstring
>::iterator var
= text_variants
.end(); var
; var
= var
->Prev
) {
1169 variants
.push_back(var
->Data
);
1171 } else if (isIntegerType(base
)) // here value restriction is applicable
1173 for (List
<Mstring
>::iterator facet
= facets
.begin(); facet
; facet
= facet
->Next
) {
1174 int int_value
= atoi(facet
->Data
.c_str());
1175 const ValueType
& value
= parent
->getValue();
1176 if (value
.lower
<= int_value
&& int_value
<= value
.upper
) {
1178 for (List
<int>::iterator itemInt
= items_int
.begin(); itemInt
; itemInt
= itemInt
->Next
) {
1179 if (int_value
== itemInt
->Data
) {
1184 if (!found
) items_int
.push_back(int_value
);
1186 if (variants
.empty() || variants
.back() != "\"useNumber\"") {
1187 variants
.push_back(Mstring("\"useNumber\""));
1191 } else if (isFloatType(base
)) // here value restriction is applicable
1193 for (List
<Mstring
>::iterator facet
= facets
.begin(); facet
; facet
= facet
->Next
) {
1194 double float_value
= atof(facet
->Data
.c_str());
1195 const ValueType
& value
= parent
->getValue();
1196 if (value
.lower
<= float_value
&& float_value
<= value
.upper
) {
1198 for (List
<double>::iterator itemFloat
= items_float
.begin(); itemFloat
; itemFloat
= itemFloat
->Next
) {
1199 if (float_value
== itemFloat
->Data
) {
1205 items_float
.push_back(float_value
);
1209 } else if (isTimeType(base
)) {
1210 List
<Mstring
> text_variants
;
1211 for (List
<Mstring
>::iterator facet
= facets
.begin(); facet
; facet
= facet
->Next
) {
1213 XSDName2TTCN3Name(facet
->Data
, items_time
, enum_id_name
, res
, var
);
1214 text_variants
.push_back(var
);
1216 text_variants
.sort();
1217 for (List
<Mstring
>::iterator var
= text_variants
.end(); var
; var
= var
->Prev
) {
1218 variants
.push_back(var
->Data
);
1220 } else if (isAnyType(base
)) {
1221 } else if (base
.empty()) {
1223 printWarning(parent
->getModule()->getSchemaname(), parent
->getName().convertedValue
,
1224 Mstring("Enumeration restriction is not supported on type '") + base
+ Mstring("'."));
1225 TTCN3ModuleInventory::getInstance().incrNumWarnings();
1226 parent
->setInvisible();
1230 void EnumerationType::sortFacets() {
1231 items_string
.sort();
1237 void EnumerationType::printToFile(FILE * file
, unsigned int indent_level
) const {
1238 if (!modified
) return;
1240 const Mstring
& base
= parent
->getBuiltInBase();
1241 if (isStringType(base
)) {
1242 for (QualifiedNames::iterator itemString
= items_string
.begin(); itemString
; itemString
= itemString
->Next
) {
1243 if (itemString
!= items_string
.begin()) fputs(",\n", file
);
1244 for (unsigned int l
= 0; l
!= indent_level
; ++l
) fputs("\t", file
);
1245 fprintf(file
, "\t%s", itemString
->Data
.name
.c_str());
1247 } else if (isIntegerType(base
)) {
1248 for (List
<int>::iterator itemInt
= items_int
.begin(); itemInt
; itemInt
= itemInt
->Next
) {
1249 if (itemInt
!= items_int
.begin()) fputs(",\n", file
);
1250 for (unsigned int l
= 0; l
!= indent_level
; ++l
) fputs("\t", file
);
1251 if (itemInt
->Data
< 0) {
1252 fprintf(file
, "\tint_%d(%d)", abs(itemInt
->Data
), itemInt
->Data
);
1254 fprintf(file
, "\tint%d(%d)", itemInt
->Data
, itemInt
->Data
);
1257 } else if (isFloatType(base
)) {
1258 for (List
<double>::iterator itemFloat
= items_float
.begin(); itemFloat
; itemFloat
= itemFloat
->Next
) {
1259 if (itemFloat
!= items_float
.begin()) fputs(", ", file
);
1262 double fracpart
= 0;
1263 fracpart
= modf(itemFloat
->Data
, &intpart
);
1264 if (fracpart
== 0) {
1265 fprintf(file
, "%lld.0", (long long int) (itemFloat
->Data
));
1267 fprintf(file
, "%g", itemFloat
->Data
);
1270 } else if (isTimeType(base
)) {
1271 for (QualifiedNames::iterator itemTime
= items_time
.begin(); itemTime
; itemTime
= itemTime
->Next
) {
1272 if (itemTime
!= items_time
.begin()) fputs(",\n", file
);
1273 for (unsigned int l
= 0; l
!= indent_level
; ++l
) fputs("\t", file
);
1274 fprintf(file
, "\t%s", itemTime
->Data
.name
.c_str());
1279 void EnumerationType::insertVariants(){
1280 if(!modified
) return;
1282 Mstring pre_connector
= empty_string
;
1283 if(parent
->getMinOccurs() == 0 && parent
->getMaxOccurs() == ULLONG_MAX
){
1284 pre_connector
= "([-]) ";
1286 for(List
<Mstring
>::iterator var
= variants
.begin(); var
; var
= var
->Next
){
1287 parent
->addVariant(V_onlyValue
, pre_connector
+ var
->Data
);
1291 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1293 WhitespaceType::WhitespaceType(SimpleType
* a_simpleType
)
1294 : p_parent(a_simpleType
)
1300 void WhitespaceType::applyReference(const WhitespaceType
& other
) {
1301 if (!modified
) modified
= other
.modified
;
1302 if (facet
.empty()) facet
= other
.facet
;
1305 void WhitespaceType::applyFacet() // only for string types: string, normalizedString, token, Name, NCName, language
1307 if (!modified
) return;
1309 const Mstring
& base
= p_parent
->getBuiltInBase();
1310 if (base
== "string" || base
== "normalizedString" || base
== "token" || base
== "language" ||
1311 base
== "Name" || base
== "NCName" || isAnyType(base
) || base
.empty()) {
1312 p_parent
->addVariant(V_whiteSpace
, facet
);
1314 printWarning(p_parent
->getModule()->getSchemaname(), p_parent
->getName().convertedValue
,
1315 Mstring("Facet 'whiteSpace' is not applicable for type '") + base
+ Mstring("'."));
1316 TTCN3ModuleInventory::getInstance().incrNumWarnings();
1320 ValueType::ValueType(SimpleType
* a_simpleType
)
1321 : parent(a_simpleType
)
1323 , facet_minInclusive(-DBL_MAX
)
1324 , facet_maxInclusive(DBL_MAX
)
1325 , facet_minExclusive(-DBL_MAX
)
1326 , facet_maxExclusive(DBL_MAX
)
1327 , facet_totalDigits(-1)
1330 , lowerExclusive(false)
1331 , upperExclusive(false)
1332 , not_a_number(false)
1335 , items_with_value() {
1338 void ValueType::applyReference(const ValueType
& other
) {
1340 modified
= other
.modified
;
1345 if (other
.not_a_number
) not_a_number
= true;
1346 if (other
.facet_minInclusive
> facet_minInclusive
) facet_minInclusive
= other
.facet_minInclusive
;
1347 if (other
.facet_maxInclusive
< facet_maxInclusive
) facet_maxInclusive
= other
.facet_maxInclusive
;
1348 if (other
.facet_minExclusive
> facet_minExclusive
) facet_minExclusive
= other
.facet_minExclusive
;
1349 if (other
.facet_maxExclusive
< facet_maxExclusive
) facet_maxExclusive
= other
.facet_maxExclusive
;
1350 if (other
.upperExclusive
) upperExclusive
= other
.upperExclusive
;
1351 if (other
.lowerExclusive
) lowerExclusive
= other
.lowerExclusive
;
1352 //-1 in case when it is not modified
1353 if (other
.facet_totalDigits
< facet_totalDigits
|| facet_totalDigits
== -1) facet_totalDigits
= other
.facet_totalDigits
;
1354 if (!other
.default_value
.empty()) {
1355 default_value
= other
.default_value
;
1356 parent
->addVariant(V_defaultForEmpty
, default_value
);
1358 if (!other
.fixed_value
.empty()) {
1359 fixed_value
= other
.fixed_value
;
1360 parent
->addVariant(V_defaultForEmpty
, fixed_value
);
1364 void ValueType::applyFacets() // only for integer and float types
1374 const Mstring
& base
= parent
->getBuiltInBase();
1376 * Setting of default value range of built-in types
1378 if (base
== "positiveInteger") {
1380 } else if (base
== "nonPositiveInteger") {
1382 } else if (base
== "negativeInteger") {
1384 } else if (base
== "nonNegativeInteger") {
1386 } else if (base
== "unsignedLong") {
1389 } else if (base
== "int") {
1392 } else if (base
== "unsignedInt") {
1395 } else if (base
== "short") {
1398 } else if (base
== "unsignedShort") {
1401 } else if (base
== "byte") {
1404 } else if (base
== "unsignedByte") {
1409 if (isIntegerType(base
)) {
1410 if (facet_minInclusive
!= -DBL_MAX
&& facet_minInclusive
> lower
) lower
= facet_minInclusive
;
1411 if (facet_maxInclusive
!= DBL_MAX
&& upper
> facet_maxInclusive
) upper
= facet_maxInclusive
;
1412 if (facet_minExclusive
!= -DBL_MAX
&& lower
< facet_minExclusive
) lower
= facet_minExclusive
;
1413 if (facet_maxExclusive
!= DBL_MAX
&& upper
> facet_maxExclusive
) upper
= facet_maxExclusive
;
1414 } else if (isFloatType(base
)) {
1415 if (facet_minInclusive
!= -DBL_MAX
&& lower
< facet_minInclusive
) lower
= facet_minInclusive
;
1416 if (facet_maxInclusive
!= DBL_MAX
&& upper
> facet_maxInclusive
) upper
= facet_maxInclusive
;
1417 if (facet_minExclusive
!= -DBL_MAX
&& lower
< facet_minExclusive
) lower
= facet_minExclusive
;
1418 if (facet_maxExclusive
!= DBL_MAX
&& upper
> facet_maxExclusive
) upper
= facet_maxExclusive
;
1419 } else if (isAnyType(base
) || isTimeType(base
) || isBooleanType(base
)) {
1420 } else if (isStringType(base
) && (
1421 base
.getValueWithoutPrefix(':') != "hexBinary" && base
.getValueWithoutPrefix(':') != "base64Binary")) {
1422 } else if (base
.empty()) {
1424 printWarning(parent
->getModule()->getSchemaname(), parent
->getName().convertedValue
,
1425 Mstring("Value restriction is not supported on type '") + base
+ Mstring("'."));
1426 TTCN3ModuleInventory::getInstance().incrNumWarnings();
1429 // totalDigits facet is only for integer types and decimal
1430 if (facet_totalDigits
> 0) // if this facet is used
1432 double r
= pow(10.0, facet_totalDigits
);
1434 if (base
== "integer") {
1435 lower
= (int) -(r
- 1);
1436 upper
= (int) (r
- 1);
1437 } else if (base
== "positiveInteger") {
1439 upper
= (int) (r
- 1);
1440 } else if (base
== "nonPositiveInteger") {
1441 lower
= (int) -(r
- 1);
1443 } else if (base
== "negativeInteger") {
1444 lower
= (int) -(r
- 1);
1446 } else if (base
== "nonNegativeInteger") {
1448 upper
= (int) (r
- 1);
1449 } else if (base
== "long" ||
1450 base
== "unsignedLong" ||
1452 base
== "unsignedInt" ||
1454 base
== "unsignedShort" ||
1456 base
== "unsignedByte") {
1457 lower
= (int) -(r
- 1);
1458 upper
= (int) (r
- 1);
1459 } else if (base
== "decimal") {
1460 lower
= (int) -(r
- 1);
1461 upper
= (int) (r
- 1);
1463 printWarning(parent
->getModule()->getSchemaname(), parent
->getName().convertedValue
,
1464 Mstring("Facet 'totalDigits' is not applicable for type '") + base
+ Mstring("'."));
1465 TTCN3ModuleInventory::getInstance().incrNumWarnings();
1468 items_with_value
.sort();
1471 void ValueType::printToFile(FILE * file
) const {
1472 if (!modified
) return;
1473 if (parent
->getEnumeration().modified
) return;
1476 fprintf(file
, " ( not_a_number )");
1479 if (!fixed_value
.empty()) {
1480 //Base64binary and hexbyte does not supported
1482 if(isBuiltInType(parent
->getType().originalValueWoPrefix
)){
1483 type
= parent
->getType().originalValueWoPrefix
;
1485 type
= getPrefixByNameSpace(parent
, parent
->getReference().get_uri()) + Mstring(":") + parent
->getReference().get_val();
1487 if(!isBuiltInType(type
)){
1488 type
= findBuiltInType(parent
, type
);
1490 if (isStringType(type
) || isTimeType(type
) || isQNameType(type
) || isAnyType(type
)) {
1491 const Mstring
& name
= type
.getValueWithoutPrefix(':');
1492 if (name
!= "hexBinary" && name
!= "base64Binary") {
1493 fprintf(file
, " (\"%s\")", fixed_value
.c_str());
1495 } else if (isBooleanType(type
)) {
1497 if (fixed_value
== "1") {
1499 } else if (fixed_value
== "0") {
1504 fprintf(file
, " (%s)", val
.c_str());
1506 fprintf(file
, " (%s)", fixed_value
.c_str());
1510 if (!items_with_value
.empty()) {
1511 fputs(" (\n", file
);
1512 for (List
<Mstring
>::iterator itemWithValue
= items_with_value
.begin(); itemWithValue
; itemWithValue
= itemWithValue
->Next
) {
1513 fprintf(file
, "\t%s", itemWithValue
->Data
.c_str());
1514 if (itemWithValue
!= items_with_value
.end()) {
1524 if (lower
== -DBL_MAX
&& upper
== DBL_MAX
) return;
1528 if (isIntegerType(parent
->getBuiltInBase())) {
1529 if (lowerExclusive
) {
1533 if (lower
== -DBL_MAX
) {
1534 fputs("-infinity", file
);
1535 } else if (lower
< 0) {
1536 long double temp_lower
= -lower
;
1537 fprintf(file
, "-%.0Lf", temp_lower
);
1539 fprintf(file
, "%.0Lf", lower
);
1542 fputs(" .. ", file
);
1543 if (upperExclusive
) {
1547 if (upper
== DBL_MAX
) {
1548 fputs("infinity", file
);
1549 } else if (upper
< 0) {
1550 long double temp_upper
= -upper
;
1551 fprintf(file
, "-%.0Lf", temp_upper
);
1553 fprintf(file
, "%.0Lf", upper
);
1555 } else if (isFloatType(parent
->getBuiltInBase())) {
1556 if (lowerExclusive
) {
1560 if (lower
== -DBL_MAX
) {
1561 fputs("-infinity", file
);
1564 double fracpart
= 0;
1565 fracpart
= modf(lower
, &intpart
);
1566 if (fracpart
== 0) {
1567 fprintf(file
, "%.1Lf", lower
);
1569 fprintf(file
, "%Lg", lower
);
1573 fputs(" .. ", file
);
1574 if (upperExclusive
) {
1578 if (upper
== DBL_MAX
) {
1579 fputs("infinity", file
);
1582 double fracpart
= 0;
1583 fracpart
= modf(upper
, &intpart
);
1584 if (fracpart
== 0) {
1585 fprintf(file
, "%.1Lf", upper
);
1587 fprintf(file
, "%Lg", upper
);