1 /******************************************************************************
2 * Copyright (c) 2000-2016 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
16 ******************************************************************************/
17 #include "SimpleType.hh"
19 #include "GeneralFunctions.hh"
21 #include "TTCN3ModuleInventory.hh"
22 #include "TTCN3Module.hh"
23 #include "ComplexType.hh"
25 extern bool g_flag_used
;
26 extern bool h_flag_used
;
28 SimpleType::SimpleType(XMLParser
* a_parser
, TTCN3Module
* a_module
, ConstructType a_construct
)
29 : RootType(a_parser
, a_module
, a_construct
)
36 , element_form_as(notset
)
37 , attribute_form_as(notset
)
44 , substitutionGroup(empty_string
)
47 , addedToTypeSubstitution(false)
52 SimpleType::SimpleType(const SimpleType
& other
)
54 , builtInBase(other
.builtInBase
)
55 , length(other
.length
)
56 , pattern(other
.pattern
)
57 , enumeration(other
.enumeration
)
58 , whitespace(other
.whitespace
)
60 , element_form_as(other
.element_form_as
)
61 , attribute_form_as(other
.attribute_form_as
)
63 , outside_reference(other
.outside_reference
)
64 , in_name_only(other
.in_name_only
)
65 , fromRef(other
.fromRef
)
66 , xsdtype(other
.xsdtype
)
67 , isOptional(other
.isOptional
)
68 , substitutionGroup(other
.substitutionGroup
)
69 , subsGroup(other
.subsGroup
)
70 , typeSubsGroup(other
.typeSubsGroup
)
71 , addedToTypeSubstitution(other
.addedToTypeSubstitution
)
75 pattern
.parent
= this;
76 enumeration
.parent
= this;
77 whitespace
.p_parent
= this;
81 void SimpleType::loadWithValues() {
82 const XMLParser::TagAttributes
& atts
= parser
->getActualTagAttributes();
83 switch (parser
->getActualTagName()) {
85 type
.upload(atts
.base
);
86 setReference(atts
.base
);
87 mode
= restrictionMode
;
90 type
.upload(atts
.itemType
);
91 setReference(atts
.itemType
);
93 maxOccurs
= ULLONG_MAX
;
98 { // generating complextype from simpletype
99 ComplexType
* new_complextype
= new ComplexType(*this, ComplexType::fromTagUnion
);
100 new_complextype
->loadWithValues();
104 name
.upload(atts
.name
);
105 type
.upload(atts
.type
);
106 setReference(atts
.type
, true);
107 if (!atts
.nillable
) {
108 applyDefaultAttribute(atts
.default_
);
109 applyFixedAttribute(atts
.fixed
);
111 applyAbstractAttribute(atts
.abstract
);
112 applySubstitionGroupAttribute(atts
.substitionGroup
);
113 applyBlockAttribute(atts
.block
);
114 //This shall be the last instruction always
115 applyNillableAttribute(atts
.nillable
);
118 name
.upload(atts
.name
);
119 type
.upload(atts
.type
);
120 xsdtype
= n_attribute
;
121 setReference(atts
.type
, true);
122 applyDefaultAttribute(atts
.default_
);
123 applyFixedAttribute(atts
.fixed
);
126 name
.upload(atts
.name
);
129 { // generating complextype from simpletype
130 ComplexType
* new_complextype
= new ComplexType(*this, ComplexType::fromTagComplexType
);
131 new_complextype
->loadWithValues();
135 if (mode
== listMode
) {
136 minOccurs
= strtoull(atts
.value
.c_str(), NULL
, 0);
137 maxOccurs
= strtoull(atts
.value
.c_str(), NULL
, 0);
140 length
.facet_minLength
= strtoull(atts
.value
.c_str(), NULL
, 0);
141 length
.facet_maxLength
= strtoull(atts
.value
.c_str(), NULL
, 0);
142 length
.modified
= true;
145 if (mode
== listMode
) {
146 minOccurs
= strtoull(atts
.value
.c_str(), NULL
, 0);
149 length
.facet_minLength
= strtoull(atts
.value
.c_str(), NULL
, 0);
150 length
.modified
= true;
153 if (mode
== listMode
) {
154 maxOccurs
= strtoull(atts
.value
.c_str(), NULL
, 0);
157 length
.facet_maxLength
= strtoull(atts
.value
.c_str(), NULL
, 0);
158 length
.modified
= true;
161 pattern
.facet
= atts
.value
;
162 pattern
.modified
= true;
165 enumeration
.facets
.push_back(atts
.value
);
166 enumeration
.modified
= true;
169 whitespace
.facet
= atts
.value
;
170 whitespace
.modified
= true;
173 if (atts
.value
== "NaN") {
174 value
.not_a_number
= true;
175 } else if (atts
.value
== "-INF") {
176 value
.facet_minInclusive
= -DBL_MAX
;
177 } else if (atts
.value
== "INF") {
178 value
.facet_minInclusive
= DBL_MAX
;
180 value
.facet_minInclusive
= stringToLongDouble(atts
.value
.c_str());
182 value
.modified
= true;
185 if (atts
.value
== "NaN") {
186 value
.not_a_number
= true;
187 } else if (atts
.value
== "-INF") {
188 value
.facet_maxInclusive
= -DBL_MAX
;
189 } else if (atts
.value
== "INF") {
190 value
.facet_maxInclusive
= DBL_MAX
;
192 value
.facet_maxInclusive
= stringToLongDouble(atts
.value
.c_str());
194 value
.modified
= true;
197 if (atts
.value
== "NaN") {
199 } else if (atts
.value
== "-INF") {
200 value
.facet_minExclusive
= -DBL_MAX
;
201 } else if (atts
.value
== "INF") {
204 value
.facet_minExclusive
= stringToLongDouble(atts
.value
.c_str());
206 value
.modified
= true;
207 value
.lowerExclusive
= true;
210 if (atts
.value
== "NaN") {
212 } else if (atts
.value
== "-INF") {
214 } else if (atts
.value
== "INF") {
215 value
.facet_maxExclusive
= DBL_MAX
;
217 value
.facet_maxExclusive
= stringToLongDouble(atts
.value
.c_str());
219 value
.modified
= true;
220 value
.upperExclusive
= true;
223 value
.facet_totalDigits
= strtoul(atts
.value
.c_str(), NULL
, 0);
224 value
.modified
= true;
226 case n_fractionDigits
:
227 //addVariant(V_fractionDigits, atts.value);
230 addComment(Mstring("LABEL:"));
233 addComment(Mstring("DEFINITION:"));
240 void SimpleType::applyDefaultAttribute(const Mstring
& default_value
) {
241 if (!default_value
.empty()) {
242 value
.default_value
= default_value
;
243 const Mstring nameT
= type
.originalValueWoPrefix
.getValueWithoutPrefix(':');
244 //Not supported for hexBinary and base64Binary
245 if (nameT
!= "hexBinary" && nameT
!= "base64Binary") {
246 addVariant(V_defaultForEmpty
, default_value
);
251 void SimpleType::applyFixedAttribute(const Mstring
& fixed_value
) {
252 if (!fixed_value
.empty()) {
253 value
.fixed_value
= fixed_value
;
254 value
.modified
= true;
255 const Mstring nameT
= type
.originalValueWoPrefix
.getValueWithoutPrefix(':');
256 //Not supported for hexBinary and base64Binary
257 if (nameT
!= "hexBinary" && nameT
!= "base64Binary") {
258 addVariant(V_defaultForEmpty
, fixed_value
);
263 void SimpleType::applyNillableAttribute(const bool nillable
) {
265 ComplexType
* new_complextype
= new ComplexType(*this, ComplexType::fromTagNillable
); // generating complextype from simpletype
266 new_complextype
->loadWithValues();
270 void SimpleType::applyAbstractAttribute(const bool abstract_value
) {
271 if (abstract_value
) {
272 addVariant(V_abstract
);
276 void SimpleType::applySubstitionGroupAttribute(const Mstring
& substitution_group
){
277 if(!substitution_group
.empty()){
278 substitutionGroup
= substitution_group
;
282 void SimpleType::applyBlockAttribute(const BlockValue block_
){
283 if(block_
== not_set
){
284 block
= getModule()->getBlockDefault();
290 void SimpleType::addToSubstitutions(){
291 if(!g_flag_used
|| substitutionGroup
.empty()){
294 SimpleType
* st_
= (SimpleType
*) TTCN3ModuleInventory::getInstance().lookup(this, substitutionGroup
, want_BOTH
);
296 printError(module
->getSchemaname(), name
.convertedValue
,
297 "Reference for a non-defined type: " + substitutionGroup
);
298 TTCN3ModuleInventory::getInstance().incrNumErrors();
301 SimpleType
* st
= (SimpleType
*)st_
;
302 if(st
->getSubstitution() != NULL
){
303 st
= st
->getSubstitution();
306 st
->referenceResolving();
307 substitutionGroup
= empty_string
;
309 if(st
->subsGroup
== NULL
){
310 ComplexType
* head_element
= new ComplexType(*st
, ComplexType::fromTagSubstitution
);
311 for(List
<SimpleType
*>::iterator simpletype
= st
->nameDepList
.begin(); simpletype
; simpletype
= simpletype
->Next
){
312 head_element
->getNameDepList().push_back(simpletype
->Data
);
314 st
->nameDepList
.clear();
315 st
->getModule()->addMainType(head_element
);
316 head_element
->addVariant(V_untagged
);
317 head_element
->addSubstitution(st
);
318 head_element
->addSubstitution(this);
319 //if st->subsGroup == this, then it is a generated subs group
320 st
->subsGroup
= head_element
;
323 st
->subsGroup
->addSubstitution(this);
327 void SimpleType::addToTypeSubstitutions() {
328 //If the user did not request type substitution generation or
329 //the type is already added to type substitution
330 if(!h_flag_used
|| addedToTypeSubstitution
){
333 //Only available if it is a restricion or extension
334 if(mode
!= extensionMode
&& mode
!= restrictionMode
){
337 //Only top level complexTypes or simpleTypes, ergo no elements
338 if(parent
!= NULL
|| hasVariant(Mstring("\"element\""))){
342 //It would be nice if here outside_reference.resolved to everything
344 SimpleType
* st
= (SimpleType
*)outside_reference
.get_ref();
345 if(st
== NULL
&& !isBuiltInType(type
.convertedValue
)){
346 //Not even a reference, and not a built in type
348 }else if(st
== NULL
&& isBuiltInType(type
.convertedValue
)){
349 st
= new SimpleType(parser
, module
, construct
);
350 st
->type
.upload(type
.convertedValue
);
351 st
->name
.upload(type
.convertedValue
);
352 st
->typeSubsGroup
= findBuiltInTypeInStoredTypeSubstitutions(type
.convertedValue
);
353 outside_reference
.set_resolved(st
);
354 //Add this decoy type to the maintypes -> module will free st
355 //st->setInvisible();
356 module
->addMainType(st
);
360 addedToTypeSubstitution
= true;
361 st
->addToTypeSubstitutions();
362 //If type substitution is NULL then we need to create the union
363 if(st
->getTypeSubstitution() == NULL
){
364 ComplexType
* head_element
= new ComplexType(*st
, ComplexType::fromTypeSubstitution
);
365 head_element
->getNameDepList().clear();
366 for(List
<SimpleType
*>::iterator simpletype
= st
->nameDepList
.begin(), nextST
; simpletype
; simpletype
= nextST
){
367 nextST
= simpletype
->Next
;
368 //Don't add if it is in a type substitution
369 if(simpletype
->Data
->getTypeSubstitution() == NULL
){
370 head_element
->getNameDepList().push_back(simpletype
->Data
);
371 st
->getNameDepList().remove(simpletype
);
375 st
->getModule()->addMainType(head_element
);
376 head_element
->addVariant(V_useType
);
377 //For cascading type substitution
378 if(st
->outside_reference
.get_ref() != NULL
&& ((ComplexType
*)st
->outside_reference
.get_ref())->getTypeSubstitution() != NULL
){
379 head_element
->setParentTypeSubsGroup(((ComplexType
*)st
->outside_reference
.get_ref())->getTypeSubstitution());
381 head_element
->addTypeSubstitution(st
);
382 head_element
->addTypeSubstitution(this);
384 //Check to find if there was already an element reference with this type
385 for(List
<typeNameDepList
>::iterator str
= module
->getElementTypes().begin(); str
; str
= str
->Next
){
386 Mstring prefix
= str
->Data
.type
.getPrefix(':');
387 Mstring value_
= str
->Data
.type
.getValueWithoutPrefix(':');
389 if((value_
== st
->getName().convertedValue
.getValueWithoutPrefix(':') && prefix
== module
->getTargetNamespaceConnector()) ||
390 (isBuiltInType(value_
) && !isBuiltInType(st
->getType().convertedValue
) && value_
== st
->getType().convertedValue
&& prefix
== module
->getTargetNamespaceConnector())){
391 //Push the namedeplist
392 for(List
<SimpleType
*>::iterator simpletype
= str
->Data
.nameDepList
.begin(); simpletype
; simpletype
= simpletype
->Next
){
393 head_element
->getNameDepList().push_back(simpletype
->Data
);
396 str
->Data
.typeSubsGroup
= head_element
;
401 head_element
->setInvisible();
403 st
->typeSubsGroup
= head_element
;
404 st
->getModule()->addStoredTypeSubstitution(head_element
);
406 st
->getTypeSubstitution()->addTypeSubstitution(this);
409 //Make the decoy invisible
414 void SimpleType::collectElementTypes(SimpleType
* found_ST
, ComplexType
* found_CT
){
415 //Only if type substitution is enabled and it is a top level(simpletype) element or
416 //it is a not top level element(complextype)
417 if(h_flag_used
&& (hasVariant(Mstring("\"element\"")) || xsdtype
== n_element
)){
418 SimpleType
* st
= NULL
, *nameDep
= NULL
;
419 Mstring uri
, value_
, type_
;
420 if(found_ST
!= NULL
|| found_CT
!= NULL
){
421 // st := found_ST or found_CT, which is not null
422 st
= found_ST
!= NULL
? found_ST
: found_CT
;
423 uri
= outside_reference
.get_uri();
424 value_
= outside_reference
.get_val();
426 }else if(isBuiltInType(type
.convertedValue
)){
428 uri
= module
->getTargetNamespace();
429 value_
= type
.convertedValue
;
430 if(outside_reference
.empty()){
434 type_
= outside_reference
.get_val();
437 //It is not possible to reach here (should be)
440 type_
= type_
.getValueWithoutPrefix(':');
442 const Mstring typeSubsName
= value_
+ Mstring("_derivations");
443 //Find if we already have a substitution type to this element reference
444 for(List
<ComplexType
*>::iterator
complex = st
->getModule()->getStoredTypeSubstitutions().begin(); complex; complex = complex->Next
){
446 if(uri
== st
->getModule()->getTargetNamespace() && typeSubsName
== complex->Data
->getName().convertedValue
){
447 complex->Data
->setVisible();
448 if(st
->getXsdtype() != n_NOTSET
&& this == st
){ //otherwise records would be renamed too
449 complex->Data
->addToNameDepList(st
);
450 ((ComplexType
*)st
)->setNameDep(nameDep
);
456 //Add the reference, to future possible type substitution
458 Mstring prefix
= st
->getModule()->getTargetNamespaceConnector();
459 if(prefix
!= empty_string
){
462 st
->getModule()->addElementType(prefix
+ type_
, nameDep
);
467 ComplexType
* SimpleType::findBuiltInTypeInStoredTypeSubstitutions(const Mstring
& builtInType
){
468 const Mstring typeSubsName
= builtInType
.getValueWithoutPrefix(':') + Mstring("_derivations");
469 for(List
<ComplexType
*>::iterator
complex = module
->getStoredTypeSubstitutions().begin(); complex; complex = complex->Next
){
470 if(typeSubsName
== complex->Data
->getName().convertedValue
){
471 return complex->Data
;
478 void SimpleType::setReference(const Mstring
& ref
, bool only_name_dependency
) {
482 if (isBuiltInType(ref
)) {
483 builtInBase
= ref
.getValueWithoutPrefix(':');
484 if (name
.convertedValue
.empty()) {
487 if (type
.convertedValue
.empty() || type
.convertedValue
== "anySimpleType") {
488 type
.upload(ref
.getValueWithoutPrefix(':'));
494 Mstring refPrefix
= ref
.getPrefix(':');
495 Mstring refValue
= ref
.getValueWithoutPrefix(':');
497 // Find the URI amongst the known namespace URIs
498 List
<NamespaceType
>::iterator declNS
;
499 for (declNS
= module
->getDeclaredNamespaces().begin(); declNS
; declNS
= declNS
->Next
) {
500 if (refPrefix
== declNS
->Data
.prefix
) {
501 refUri
= declNS
->Data
.uri
;
506 // FIXME: can this part be moved above the search ?
507 if (refUri
.empty()) { // not found
508 if (refPrefix
== "xml") {
509 refUri
= "http://www.w3.org/XML/1998/namespace";
510 } else if (refPrefix
== "xmlns") {
511 refUri
= "http://www.w3.org/2000/xmlns";
512 } else if (refPrefix
.empty() && module
->getTargetNamespace() == "NoTargetNamespace") {
513 refUri
= "NoTargetNamespace";
517 if (refUri
.empty()) { // something is incorrect - unable to find the uri to the given prefix
518 if (refPrefix
.empty()) {
519 printError(module
->getSchemaname(), parser
->getActualLineNumber(),
520 Mstring("The absent namespace must be imported because "
521 "it is not the same as the target namespace of the current schema."));
522 parser
->incrNumErrors();
525 printError(module
->getSchemaname(), parser
->getActualLineNumber(),
526 "The value \'" + ref
+ "\' is incorrect: "
527 "A namespace prefix does not denote any URI.");
528 parser
->incrNumErrors();
533 if (only_name_dependency
) {
537 outside_reference
.load(refUri
, refValue
, &declNS
->Data
);
540 void SimpleType::referenceResolving() {
541 if (outside_reference
.empty() || outside_reference
.is_resolved()){
542 addToTypeSubstitutions();
543 collectElementTypes();
545 if(outside_reference
.empty() && substitutionGroup
.empty()) return;
546 if (outside_reference
.is_resolved()) return;
548 if(!outside_reference
.empty()){
549 SimpleType
* found_ST
= static_cast<SimpleType
*> (
550 TTCN3ModuleInventory::getInstance().lookup(this, want_ST
));
551 ComplexType
* found_CT
= static_cast<ComplexType
*> (
552 TTCN3ModuleInventory::getInstance().lookup(this, want_CT
));
553 // It _is_ possible to find both
554 collectElementTypes(found_ST
, found_CT
);
555 if (found_ST
!= NULL
) {
556 if (!found_ST
->outside_reference
.empty() && !found_ST
->outside_reference
.is_resolved() && found_ST
!= this) {
557 found_ST
->referenceResolving();
558 if(!found_ST
->outside_reference
.is_resolved()){
559 found_ST
->outside_reference
.set_resolved(NULL
);
562 referenceForST(found_ST
);
563 addToTypeSubstitutions();
564 if (!isBuiltInType(type
.convertedValue
)) {
565 found_ST
->addToNameDepList(this);
567 } else if (found_CT
!= NULL
) {
568 referenceForCT(found_CT
);
569 addToTypeSubstitutions();
570 if (!isBuiltInType(type
.convertedValue
)) {
571 found_CT
->addToNameDepList(this);
574 printError(module
->getSchemaname(), name
.convertedValue
,
575 "Reference for a non-defined type: " + outside_reference
.repr());
576 TTCN3ModuleInventory::getInstance().incrNumErrors();
577 outside_reference
.set_resolved(NULL
);
579 addToSubstitutions();
581 addToSubstitutions();
585 void SimpleType::referenceForST(SimpleType
* found_ST
) {
586 outside_reference
.set_resolved(found_ST
);
591 if (construct
== c_element
)
594 if (mode
== listMode
)
597 if (!found_ST
->builtInBase
.empty()) {
598 builtInBase
= found_ST
->builtInBase
;
601 length
.applyReference(found_ST
->length
);
602 pattern
.applyReference(found_ST
->pattern
);
603 enumeration
.applyReference(found_ST
->enumeration
);
604 whitespace
.applyReference(found_ST
->whitespace
);
605 value
.applyReference(found_ST
->value
);
607 mode
= found_ST
->mode
;
608 if (found_ST
->mode
!= listMode
) {
609 type
.upload(found_ST
->getType().convertedValue
);
613 void SimpleType::referenceForCT(ComplexType
* found_CT
) {
614 outside_reference
.set_resolved(found_CT
);
619 // Section 7.5.3 Example5
620 if (found_CT
->getType().convertedValue
== Mstring("union") && mode
== restrictionMode
) {
621 for (List
<Mstring
>::iterator facet
= enumeration
.facets
.begin(); facet
; facet
= facet
->Next
) {
622 enumeration
.items_misc
.push_back(facet
->Data
);
625 size_t value_size
= value
.items_with_value
.size(); //Used to check changes
626 enumeration
.modified
= false;
627 for (List
<Mstring
>::iterator itemMisc
= enumeration
.items_misc
.begin(); itemMisc
; itemMisc
= itemMisc
->Next
) {
628 size_t act_size
= value
.items_with_value
.size(); //Used to detect if field did not match any field
629 for (List
<ComplexType
*>::iterator field
= found_CT
->complexfields
.begin(); field
; field
= field
->Next
) {
630 if (isIntegerType(field
->Data
->getType().convertedValue
)) {
633 sscanf(itemMisc
->Data
.c_str(), "%d%n", &val
, &read_chars
);
634 if ((size_t) read_chars
== itemMisc
->Data
.size()) {
635 expstring_t tmp_string
= mprintf("{%s:=%d}",
636 field
->Data
->getName().convertedValue
.c_str(), val
);
637 value
.items_with_value
.push_back(Mstring(tmp_string
));
642 if (isFloatType(field
->Data
->getType().convertedValue
)) {
645 sscanf(itemMisc
->Data
.c_str(), "%f%n", &val
, &read_chars
);
646 if ((size_t) read_chars
== itemMisc
->Data
.size()) {
647 expstring_t tmp_string
= mprintf("{%s:=%f}",
648 field
->Data
->getName().convertedValue
.c_str(), val
);
649 value
.items_with_value
.push_back(Mstring(tmp_string
));
654 if (isTimeType(field
->Data
->getType().convertedValue
)) {
655 if (matchDates(itemMisc
->Data
.c_str(), field
->Data
->getType().originalValueWoPrefix
.c_str())) {
656 expstring_t tmp_string
= mprintf("{%s:=\"%s\"}",
657 field
->Data
->getName().convertedValue
.c_str(), itemMisc
->Data
.c_str());
658 value
.items_with_value
.push_back(Mstring(tmp_string
));
663 if (isStringType(field
->Data
->getType().convertedValue
)) {
664 expstring_t tmp_string
= mprintf("{%s:=\"%s\"}",
665 field
->Data
->getName().convertedValue
.c_str(), itemMisc
->Data
.c_str());
666 value
.items_with_value
.push_back(Mstring(tmp_string
));
671 if (act_size
== value
.items_with_value
.size()) {
672 printWarning(getModule()->getSchemaname(), getName().convertedValue
,
673 Mstring("The following enumeration did not match any field: ") + itemMisc
->Data
+ Mstring("."));
674 TTCN3ModuleInventory::getInstance().incrNumWarnings();
678 if (value_size
!= value
.items_with_value
.size()) {
679 value
.modified
= true;
683 void SimpleType::nameConversion(NameConversionMode conversion_mode
, const List
<NamespaceType
> & ns
) {
685 switch (conversion_mode
) {
687 nameConversion_names();
690 nameConversion_types(ns
);
697 void SimpleType::nameConversion_names() {
698 Mstring res
, var(module
->getTargetNamespace());
699 XSDName2TTCN3Name(name
.convertedValue
, TTCN3ModuleInventory::getInstance().getTypenames(), type_name
, res
, var
);
700 name
.convertedValue
= res
;
701 addVariant(V_onlyValue
, var
);
702 for (List
<SimpleType
*>::iterator st
= nameDepList
.begin(); st
; st
= st
->Next
) {
703 st
->Data
->setTypeValue(res
);
707 void SimpleType::nameConversion_types(const List
<NamespaceType
> & ns
) {
708 if (type
.convertedValue
== "record" || type
.convertedValue
== "set"
709 || type
.convertedValue
== "union" || type
.convertedValue
== "enumerated") return;
711 Mstring prefix
= type
.convertedValue
.getPrefix(':');
712 Mstring value_str
= type
.convertedValue
.getValueWithoutPrefix(':');
715 for (List
<NamespaceType
>::iterator namesp
= ns
.begin(); namesp
; namesp
= namesp
->Next
) {
716 if (prefix
== namesp
->Data
.prefix
) {
717 uri
= namesp
->Data
.uri
;
722 QualifiedName
tmp(uri
, value_str
);
724 QualifiedNames::iterator origTN
= TTCN3ModuleInventory::getInstance().getTypenames().begin();
725 for (; origTN
; origTN
= origTN
->Next
) {
726 if (tmp
== origTN
->Data
) {
727 QualifiedName
tmp_name(module
->getTargetNamespace(), name
.convertedValue
);
728 if (tmp_name
== origTN
->Data
)
729 continue; // get a new type name
734 if (origTN
!= NULL
) {
735 setTypeValue(origTN
->Data
.name
);
736 // This ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ is always value_str
737 // The only effect here is to remove the "xs:" prefix from type.convertedValue,
738 // otherwise the new value is always the same as the old.
741 XSDName2TTCN3Name(value_str
, TTCN3ModuleInventory::getInstance().getTypenames(), type_reference_name
, res
, var
);
746 void SimpleType::finalModification() {
748 length
.applyFacets();
749 pattern
.applyFacet();
750 whitespace
.applyFacet();
751 enumeration
.applyFacets();
753 if (module
->getElementFormDefault() == qualified
&&
754 element_form_as
== unqualified
) {
755 addVariant(V_formAs
, Mstring("unqualified"));
756 } else if (module
->getElementFormDefault() != qualified
&&
757 element_form_as
== qualified
) {
758 addVariant(V_formAs
, Mstring("qualified"));
761 if (module
->getAttributeFormDefault() == qualified
&&
762 attribute_form_as
== unqualified
) {
763 addVariant(V_formAs
, Mstring("unqualified"));
764 } else if (module
->getAttributeFormDefault() != qualified
&&
765 attribute_form_as
== qualified
) {
766 addVariant(V_formAs
, Mstring("qualified"));
769 if (type
.originalValueWoPrefix
== Mstring("boolean")) {
770 addVariant(V_onlyValueHidden
, Mstring("\"text 'false' as '0'\""));
771 addVariant(V_onlyValueHidden
, Mstring("\"text 'true' as '1'\""));
774 isOptional
= isOptional
|| (minOccurs
== 0 && maxOccurs
== 0);
776 // If the type name is the same as the identifier then we have to prefix it
777 // with the module identifier.
778 if (type
.convertedValue
== name
.convertedValue
&& !outside_reference
.empty()) {
779 List
<const TTCN3Module
*>::iterator import_module
= module
->getImportedModules().begin();
780 for (; import_module
; import_module
= import_module
->Next
) {
781 if (import_module
->Data
->getTargetNamespace() == outside_reference
.get_uri()) {
782 type
.upload(import_module
->Data
->getModulename() + Mstring(".") + type
.convertedValue
);
789 bool SimpleType::hasUnresolvedReference() {
790 if (!outside_reference
.empty() && !outside_reference
.is_resolved()) {
797 void SimpleType::applyRefAttribute(const Mstring
& ref_value
) {
798 if (!ref_value
.empty()) {
799 setReference(ref_value
);
804 void SimpleType::printToFile(FILE * file
) {
811 fputs("type ", file
);
812 if(enumeration
.modified
&& hasVariant(Mstring("\"list\""))){
813 printMinOccursMaxOccurs(file
, false);
814 fprintf(file
, "enumerated\n{\n");
815 enumeration
.sortFacets();
816 enumeration
.printToFile(file
);
817 fprintf(file
, "\n} %s", name
.convertedValue
.c_str());
818 } else if (enumeration
.modified
) {
819 if (isFloatType(builtInBase
)) {
820 fprintf(file
, "%s %s (", type
.convertedValue
.c_str(), name
.convertedValue
.c_str());
821 enumeration
.sortFacets();
822 enumeration
.printToFile(file
);
825 fprintf(file
, "enumerated %s\n{\n", name
.convertedValue
.c_str());
826 enumeration
.sortFacets();
827 enumeration
.printToFile(file
);
831 printMinOccursMaxOccurs(file
, false);
833 int multiplicity
= multi(module
, outside_reference
, this);
834 const RootType
*type_ref
= outside_reference
.get_ref();
835 if ((multiplicity
> 1) && type_ref
836 && type_ref
->getModule() != module
) {
837 fprintf(file
, "%s.", type_ref
->getModule()->getModulename().c_str());
840 fprintf(file
, "%s %s",
841 type
.convertedValue
.c_str(), name
.convertedValue
.c_str());
842 pattern
.printToFile(file
);
843 value
.printToFile(file
);
844 length
.printToFile(file
);
846 enumeration
.insertVariants();
848 fputs(";\n\n\n", file
);
851 void SimpleType::dump(unsigned int depth
) const {
852 static const char *modes
[] = {
853 "", "restriction", "extension", "list"
855 fprintf(stderr
, "%*s SimpleType '%s' -> '%s' at %p\n", depth
* 2, "",
856 name
.originalValueWoPrefix
.c_str(), name
.convertedValue
.c_str(),
858 fprintf(stderr
, "%*s type '%s' -> '%s'\n", depth
* 2, "",
859 type
.originalValueWoPrefix
.c_str(), type
.convertedValue
.c_str());
861 if (mode
!= noMode
) {
862 fprintf(stderr
, "%*s %s, base='%s'\n", depth
* 2, "", modes
[mode
], builtInBase
.c_str());
865 // fprintf (stderr, "%*s rfo='%s' n_d='%s'\n", depth * 2, "",
866 // reference_for_other.c_str(), name_dependency.c_str());
869 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
871 LengthType::LengthType(SimpleType
* a_simpleType
)
872 : parent(a_simpleType
)
875 , facet_maxLength(ULLONG_MAX
)
877 , upper(ULLONG_MAX
) {
880 void LengthType::applyReference(const LengthType
& other
) {
881 if (!modified
) modified
= other
.modified
;
882 if (other
.facet_minLength
> facet_minLength
) facet_minLength
= other
.facet_minLength
;
883 if (other
.facet_maxLength
< facet_maxLength
) facet_maxLength
= other
.facet_maxLength
;
886 void LengthType::applyFacets() // only for string types and list types without QName
888 if (!modified
) return;
890 switch (parent
->getMode()) {
891 case SimpleType::restrictionMode
:
893 const Mstring
& base
= parent
->getBuiltInBase();
894 if ((isStringType(base
) || (isSequenceType(base
) && base
!= "QName") || isAnyType(base
)) || base
.empty()) {
895 lower
= facet_minLength
;
896 upper
= facet_maxLength
;
898 printWarning(parent
->getModule()->getSchemaname(), parent
->getName().convertedValue
,
899 Mstring("Length restriction is not supported on type '") + base
+ Mstring("'."));
900 TTCN3ModuleInventory::getInstance().incrNumWarnings();
904 case SimpleType::extensionMode
:
905 case SimpleType::listMode
:
906 lower
= facet_minLength
;
907 upper
= facet_maxLength
;
909 case SimpleType::noMode
:
913 printError(parent
->getModule()->getSchemaname(), parent
->getName().convertedValue
,
914 Mstring("The upper boundary of length restriction cannot be smaller than the lower boundary."));
915 TTCN3ModuleInventory::getInstance().incrNumErrors();
920 void LengthType::printToFile(FILE * file
) const {
921 if (!modified
) return;
922 if (parent
->getEnumeration().modified
) return;
924 if (lower
== upper
) {
925 fprintf(file
, " length(%llu)", lower
);
927 fprintf(file
, " length(%llu .. ", lower
);
929 if (upper
== ULLONG_MAX
) {
930 fputs("infinity", file
);
932 fprintf(file
, "%llu", upper
);
939 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
941 PatternType::PatternType(SimpleType
* a_simpleType
)
942 : parent(a_simpleType
)
948 void PatternType::applyReference(const PatternType
& other
) {
949 if (!modified
) modified
= other
.modified
;
950 if (facet
.empty()) facet
= other
.facet
;
953 void PatternType::applyFacet() // only for time types and string types without hexBinary
955 if (!modified
) return;
957 const Mstring
& base
= parent
->getBuiltInBase();
958 if (((isStringType(base
) && base
!= "hexBinary") || isTimeType(base
) || isAnyType(base
)) || base
.empty()) {
959 // XSD pattern to TTCN-3 pattern; ETSI ES 201 873-9 clause 6.1.4
960 // FIXME a proper scanner is needed, e.g. from flex
962 for (size_t i
= 0; i
!= facet
.size(); ++i
) {
966 value
+= charclass
? "\\("
970 value
+= charclass
? "\\)"
977 value
+= charclass
? "\\^"
988 case '.': // any character
989 value
+= charclass
? '.'
992 case '*': // 0 or more
993 value
+= '*'; //#(0,)
996 value
+= '+'; //#(1,)
999 value
+= charclass
? "?"
1007 if (charclass
== 0) {
1010 while (facet
[i
+ k
] != '}') {
1015 match
= sscanf(s
.c_str(), "%i,%i", &a
, &b
);
1016 if (match
== 1 || match
== 2) {
1030 value
+= charclass
? "\\}"
1035 // Appendix G1.1 of XML Schema Datatypes: Character class escapes;
1036 // specifically, http://www.w3.org/TR/xmlschema11-2/#nt-MultiCharEsc
1037 char cn
= facet
[i
+ 1];
1040 value
+= charclass
? "\\w\\d.\\-_:"
1044 value
+= charclass
? "^\\w\\d.\\-_:"
1045 : "[^\\w\\d.\\-_:]";
1048 value
+= charclass
? "^\\d"
1052 value
+= charclass
? "\\w\\d:"
1056 value
+= charclass
? "^\\w\\d:"
1060 value
+= charclass
? "\\q{0,0,0,20}\\q{0,0,0,10}\\t\\r"
1061 : "[\\q{0,0,0,20}\\q{0,0,0,10}\\t\\r]";
1064 value
+= charclass
? "^\\q{0,0,0,20}\\q{0,0,0,10}\\t\\r"
1065 : "[^\\q{0,0,0,20}\\q{0,0,0,10}\\t\\r]";
1068 value
+= charclass
? "^\\w"
1072 printWarning(parent
->getModule()->getSchemaname(), parent
->getName().convertedValue
,
1073 Mstring("Character categories and blocks are not supported."));
1074 TTCN3ModuleInventory::getInstance().incrNumWarnings();
1076 Mstring("Pattern is not converted due to using character categories and blocks in patterns is not supported."));
1084 // backslash + another: pass unmodified; this also handles \d and \w
1093 if (facet
[i
+ 1] == '#') { // &#....;
1096 while (facet
[i
+ k
] != ';') {
1100 long long int d
= atoll(s
.c_str());
1101 if (d
< 0 || d
> 2147483647) {
1102 printError(parent
->getModule()->getSchemaname(), parent
->getName().convertedValue
,
1103 Mstring("Invalid unicode character."));
1104 TTCN3ModuleInventory::getInstance().incrNumErrors();
1106 unsigned char group
= (d
>> 24) & 0xFF;
1107 unsigned char plane
= (d
>> 16) & 0xFF;
1108 unsigned char row
= (d
>> 8) & 0xFF;
1109 unsigned char cell
= d
& 0xFF;
1111 expstring_t res
= mprintf("\\q{%d, %d, %d, %d}", group
, plane
, row
, cell
);
1116 // else fall through
1117 default: //just_copy:
1123 printWarning(parent
->getModule()->getSchemaname(), parent
->getName().convertedValue
,
1124 Mstring("Pattern restriction is not supported on type '") + base
+ Mstring("'."));
1125 TTCN3ModuleInventory::getInstance().incrNumWarnings();
1129 void PatternType::printToFile(FILE * file
) const {
1130 if (!modified
|| value
.empty()) return;
1131 if (parent
->getEnumeration().modified
) return;
1133 fprintf(file
, " (pattern \"%s\")", value
.c_str());
1136 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1138 EnumerationType::EnumerationType(SimpleType
* a_simpleType
)
1139 : parent(a_simpleType
)
1150 void EnumerationType::applyReference(const EnumerationType
& other
) {
1151 if (!modified
) modified
= other
.modified
;
1152 for (List
<Mstring
>::iterator facet
= other
.facets
.begin(); facet
; facet
= facet
->Next
) {
1153 facets
.push_back(facet
->Data
);
1157 void EnumerationType::applyFacets() // string types, integer types, float types, time types
1159 if (!modified
) return;
1161 facets
.remove_dups();
1163 const Mstring
& base
= parent
->getBuiltInBase();
1165 if (isStringType(base
)) // here length restriction is applicable
1167 List
<Mstring
> text_variants
;
1168 for (List
<Mstring
>::iterator facet
= facets
.begin(); facet
; facet
= facet
->Next
) {
1169 const LengthType
& length
= parent
->getLength();
1170 if (length
.lower
<= facet
->Data
.size() && facet
->Data
.size() <= length
.upper
) {
1172 XSDName2TTCN3Name(facet
->Data
, items_string
, enum_id_name
, res
, var
);
1173 text_variants
.push_back(var
);
1176 text_variants
.sort();
1177 for (List
<Mstring
>::iterator var
= text_variants
.end(); var
; var
= var
->Prev
) {
1178 variants
.push_back(var
->Data
);
1180 } else if (isIntegerType(base
)) // here value restriction is applicable
1182 for (List
<Mstring
>::iterator facet
= facets
.begin(); facet
; facet
= facet
->Next
) {
1183 int int_value
= atoi(facet
->Data
.c_str());
1184 const ValueType
& value
= parent
->getValue();
1185 if (value
.lower
<= int_value
&& int_value
<= value
.upper
) {
1187 for (List
<int>::iterator itemInt
= items_int
.begin(); itemInt
; itemInt
= itemInt
->Next
) {
1188 if (int_value
== itemInt
->Data
) {
1193 if (!found
) items_int
.push_back(int_value
);
1195 if (variants
.empty() || variants
.back() != "\"useNumber\"") {
1196 variants
.push_back(Mstring("\"useNumber\""));
1200 } else if (isFloatType(base
)) // here value restriction is applicable
1202 for (List
<Mstring
>::iterator facet
= facets
.begin(); facet
; facet
= facet
->Next
) {
1203 double float_value
= atof(facet
->Data
.c_str());
1204 const ValueType
& value
= parent
->getValue();
1205 if (value
.lower
<= float_value
&& float_value
<= value
.upper
) {
1207 for (List
<double>::iterator itemFloat
= items_float
.begin(); itemFloat
; itemFloat
= itemFloat
->Next
) {
1208 if (float_value
== itemFloat
->Data
) {
1214 items_float
.push_back(float_value
);
1218 } else if (isTimeType(base
)) {
1219 List
<Mstring
> text_variants
;
1220 for (List
<Mstring
>::iterator facet
= facets
.begin(); facet
; facet
= facet
->Next
) {
1222 XSDName2TTCN3Name(facet
->Data
, items_time
, enum_id_name
, res
, var
);
1223 text_variants
.push_back(var
);
1225 text_variants
.sort();
1226 for (List
<Mstring
>::iterator var
= text_variants
.end(); var
; var
= var
->Prev
) {
1227 variants
.push_back(var
->Data
);
1229 } else if (isAnyType(base
)) {
1230 } else if (base
.empty()) {
1232 printWarning(parent
->getModule()->getSchemaname(), parent
->getName().convertedValue
,
1233 Mstring("Enumeration restriction is not supported on type '") + base
+ Mstring("'."));
1234 TTCN3ModuleInventory::getInstance().incrNumWarnings();
1235 parent
->setInvisible();
1239 void EnumerationType::sortFacets() {
1240 items_string
.sort();
1246 void EnumerationType::printToFile(FILE * file
, unsigned int indent_level
) const {
1247 if (!modified
) return;
1249 const Mstring
& base
= parent
->getBuiltInBase();
1250 if (isStringType(base
)) {
1251 for (QualifiedNames::iterator itemString
= items_string
.begin(); itemString
; itemString
= itemString
->Next
) {
1252 if (itemString
!= items_string
.begin()) fputs(",\n", file
);
1253 for (unsigned int l
= 0; l
!= indent_level
; ++l
) fputs("\t", file
);
1254 fprintf(file
, "\t%s", itemString
->Data
.name
.c_str());
1256 } else if (isIntegerType(base
)) {
1257 for (List
<int>::iterator itemInt
= items_int
.begin(); itemInt
; itemInt
= itemInt
->Next
) {
1258 if (itemInt
!= items_int
.begin()) fputs(",\n", file
);
1259 for (unsigned int l
= 0; l
!= indent_level
; ++l
) fputs("\t", file
);
1260 if (itemInt
->Data
< 0) {
1261 fprintf(file
, "\tint_%d(%d)", abs(itemInt
->Data
), itemInt
->Data
);
1263 fprintf(file
, "\tint%d(%d)", itemInt
->Data
, itemInt
->Data
);
1266 } else if (isFloatType(base
)) {
1267 for (List
<double>::iterator itemFloat
= items_float
.begin(); itemFloat
; itemFloat
= itemFloat
->Next
) {
1268 if (itemFloat
!= items_float
.begin()) fputs(", ", file
);
1271 double fracpart
= 0;
1272 fracpart
= modf(itemFloat
->Data
, &intpart
);
1273 if (fracpart
== 0) {
1274 fprintf(file
, "%lld.0", (long long int) (itemFloat
->Data
));
1276 fprintf(file
, "%g", itemFloat
->Data
);
1279 } else if (isTimeType(base
)) {
1280 for (QualifiedNames::iterator itemTime
= items_time
.begin(); itemTime
; itemTime
= itemTime
->Next
) {
1281 if (itemTime
!= items_time
.begin()) fputs(",\n", file
);
1282 for (unsigned int l
= 0; l
!= indent_level
; ++l
) fputs("\t", file
);
1283 fprintf(file
, "\t%s", itemTime
->Data
.name
.c_str());
1288 void EnumerationType::insertVariants(){
1289 if(!modified
) return;
1291 Mstring pre_connector
= empty_string
;
1292 if(parent
->getMinOccurs() == 0 && parent
->getMaxOccurs() == ULLONG_MAX
){
1293 pre_connector
= "([-]) ";
1295 for(List
<Mstring
>::iterator var
= variants
.begin(); var
; var
= var
->Next
){
1296 parent
->addVariant(V_onlyValue
, pre_connector
+ var
->Data
);
1300 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1302 WhitespaceType::WhitespaceType(SimpleType
* a_simpleType
)
1303 : p_parent(a_simpleType
)
1309 void WhitespaceType::applyReference(const WhitespaceType
& other
) {
1310 if (!modified
) modified
= other
.modified
;
1311 if (facet
.empty()) facet
= other
.facet
;
1314 void WhitespaceType::applyFacet() // only for string types: string, normalizedString, token, Name, NCName, language
1316 if (!modified
) return;
1318 const Mstring
& base
= p_parent
->getBuiltInBase();
1319 if (base
== "string" || base
== "normalizedString" || base
== "token" || base
== "language" ||
1320 base
== "Name" || base
== "NCName" || isAnyType(base
) || base
.empty()) {
1321 p_parent
->addVariant(V_whiteSpace
, facet
);
1323 printWarning(p_parent
->getModule()->getSchemaname(), p_parent
->getName().convertedValue
,
1324 Mstring("Facet 'whiteSpace' is not applicable for type '") + base
+ Mstring("'."));
1325 TTCN3ModuleInventory::getInstance().incrNumWarnings();
1329 ValueType::ValueType(SimpleType
* a_simpleType
)
1330 : parent(a_simpleType
)
1332 , facet_minInclusive(-DBL_MAX
)
1333 , facet_maxInclusive(DBL_MAX
)
1334 , facet_minExclusive(-DBL_MAX
)
1335 , facet_maxExclusive(DBL_MAX
)
1336 , facet_totalDigits(-1)
1339 , lowerExclusive(false)
1340 , upperExclusive(false)
1341 , not_a_number(false)
1344 , items_with_value() {
1347 void ValueType::applyReference(const ValueType
& other
) {
1349 modified
= other
.modified
;
1354 if (other
.not_a_number
) not_a_number
= true;
1355 if (other
.facet_minInclusive
> facet_minInclusive
) facet_minInclusive
= other
.facet_minInclusive
;
1356 if (other
.facet_maxInclusive
< facet_maxInclusive
) facet_maxInclusive
= other
.facet_maxInclusive
;
1357 if (other
.facet_minExclusive
> facet_minExclusive
) facet_minExclusive
= other
.facet_minExclusive
;
1358 if (other
.facet_maxExclusive
< facet_maxExclusive
) facet_maxExclusive
= other
.facet_maxExclusive
;
1359 if (other
.upperExclusive
) upperExclusive
= other
.upperExclusive
;
1360 if (other
.lowerExclusive
) lowerExclusive
= other
.lowerExclusive
;
1361 //-1 in case when it is not modified
1362 if (other
.facet_totalDigits
< facet_totalDigits
|| facet_totalDigits
== -1) facet_totalDigits
= other
.facet_totalDigits
;
1363 if (!other
.default_value
.empty()) {
1364 default_value
= other
.default_value
;
1365 parent
->addVariant(V_defaultForEmpty
, default_value
);
1367 if (!other
.fixed_value
.empty()) {
1368 fixed_value
= other
.fixed_value
;
1369 parent
->addVariant(V_defaultForEmpty
, fixed_value
);
1373 void ValueType::applyFacets() // only for integer and float types
1383 const Mstring
& base
= parent
->getBuiltInBase();
1385 * Setting of default value range of built-in types
1387 if (base
== "positiveInteger") {
1389 } else if (base
== "nonPositiveInteger") {
1391 } else if (base
== "negativeInteger") {
1393 } else if (base
== "nonNegativeInteger") {
1395 } else if (base
== "unsignedLong") {
1398 } else if (base
== "int") {
1401 } else if (base
== "unsignedInt") {
1404 } else if (base
== "short") {
1407 } else if (base
== "unsignedShort") {
1410 } else if (base
== "byte") {
1413 } else if (base
== "unsignedByte") {
1418 if (isIntegerType(base
)) {
1419 if (facet_minInclusive
!= -DBL_MAX
&& facet_minInclusive
> lower
) lower
= facet_minInclusive
;
1420 if (facet_maxInclusive
!= DBL_MAX
&& upper
> facet_maxInclusive
) upper
= facet_maxInclusive
;
1421 if (facet_minExclusive
!= -DBL_MAX
&& lower
< facet_minExclusive
) lower
= facet_minExclusive
;
1422 if (facet_maxExclusive
!= DBL_MAX
&& upper
> facet_maxExclusive
) upper
= facet_maxExclusive
;
1423 } else if (isFloatType(base
)) {
1424 if (facet_minInclusive
!= -DBL_MAX
&& lower
< facet_minInclusive
) lower
= facet_minInclusive
;
1425 if (facet_maxInclusive
!= DBL_MAX
&& upper
> facet_maxInclusive
) upper
= facet_maxInclusive
;
1426 if (facet_minExclusive
!= -DBL_MAX
&& lower
< facet_minExclusive
) lower
= facet_minExclusive
;
1427 if (facet_maxExclusive
!= DBL_MAX
&& upper
> facet_maxExclusive
) upper
= facet_maxExclusive
;
1428 } else if (isAnyType(base
) || isTimeType(base
) || isBooleanType(base
)) {
1429 } else if (isStringType(base
) && (
1430 base
.getValueWithoutPrefix(':') != "hexBinary" && base
.getValueWithoutPrefix(':') != "base64Binary")) {
1431 } else if (base
.empty()) {
1433 printWarning(parent
->getModule()->getSchemaname(), parent
->getName().convertedValue
,
1434 Mstring("Value restriction is not supported on type '") + base
+ Mstring("'."));
1435 TTCN3ModuleInventory::getInstance().incrNumWarnings();
1438 // totalDigits facet is only for integer types and decimal
1439 if (facet_totalDigits
> 0) // if this facet is used
1441 double r
= pow(10.0, facet_totalDigits
);
1443 if (base
== "integer") {
1444 lower
= (int) -(r
- 1);
1445 upper
= (int) (r
- 1);
1446 } else if (base
== "positiveInteger") {
1448 upper
= (int) (r
- 1);
1449 } else if (base
== "nonPositiveInteger") {
1450 lower
= (int) -(r
- 1);
1452 } else if (base
== "negativeInteger") {
1453 lower
= (int) -(r
- 1);
1455 } else if (base
== "nonNegativeInteger") {
1457 upper
= (int) (r
- 1);
1458 } else if (base
== "long" ||
1459 base
== "unsignedLong" ||
1461 base
== "unsignedInt" ||
1463 base
== "unsignedShort" ||
1465 base
== "unsignedByte") {
1466 lower
= (int) -(r
- 1);
1467 upper
= (int) (r
- 1);
1468 } else if (base
== "decimal") {
1469 lower
= (int) -(r
- 1);
1470 upper
= (int) (r
- 1);
1472 printWarning(parent
->getModule()->getSchemaname(), parent
->getName().convertedValue
,
1473 Mstring("Facet 'totalDigits' is not applicable for type '") + base
+ Mstring("'."));
1474 TTCN3ModuleInventory::getInstance().incrNumWarnings();
1477 items_with_value
.sort();
1480 void ValueType::printToFile(FILE * file
) const {
1481 if (!modified
) return;
1482 if (parent
->getEnumeration().modified
) return;
1485 fprintf(file
, " ( not_a_number )");
1488 if (!fixed_value
.empty()) {
1489 //Base64binary and hexbyte does not supported
1491 if(isBuiltInType(parent
->getType().originalValueWoPrefix
)){
1492 type
= parent
->getType().originalValueWoPrefix
;
1494 type
= getPrefixByNameSpace(parent
, parent
->getReference().get_uri()) + Mstring(":") + parent
->getReference().get_val();
1496 if(!isBuiltInType(type
)){
1497 type
= findBuiltInType(parent
, type
);
1499 if (isStringType(type
) || isTimeType(type
) || isQNameType(type
) || isAnyType(type
)) {
1500 const Mstring
& name
= type
.getValueWithoutPrefix(':');
1501 if (name
!= "hexBinary" && name
!= "base64Binary") {
1502 fprintf(file
, " (\"%s\")", fixed_value
.c_str());
1504 } else if (isBooleanType(type
)) {
1506 if (fixed_value
== "1") {
1508 } else if (fixed_value
== "0") {
1513 fprintf(file
, " (%s)", val
.c_str());
1515 fprintf(file
, " (%s)", fixed_value
.c_str());
1519 if (!items_with_value
.empty()) {
1520 fputs(" (\n", file
);
1521 for (List
<Mstring
>::iterator itemWithValue
= items_with_value
.begin(); itemWithValue
; itemWithValue
= itemWithValue
->Next
) {
1522 fprintf(file
, "\t%s", itemWithValue
->Data
.c_str());
1523 if (itemWithValue
!= items_with_value
.end()) {
1533 if (lower
== -DBL_MAX
&& upper
== DBL_MAX
) return;
1537 if (isIntegerType(parent
->getBuiltInBase())) {
1538 if (lowerExclusive
) {
1542 if (lower
== -DBL_MAX
) {
1543 fputs("-infinity", file
);
1544 } else if (lower
< 0) {
1545 long double temp_lower
= -lower
;
1546 fprintf(file
, "-%.0Lf", temp_lower
);
1548 fprintf(file
, "%.0Lf", lower
);
1551 fputs(" .. ", file
);
1552 if (upperExclusive
) {
1556 if (upper
== DBL_MAX
) {
1557 fputs("infinity", file
);
1558 } else if (upper
< 0) {
1559 long double temp_upper
= -upper
;
1560 fprintf(file
, "-%.0Lf", temp_upper
);
1562 fprintf(file
, "%.0Lf", upper
);
1564 } else if (isFloatType(parent
->getBuiltInBase())) {
1565 if (lowerExclusive
) {
1569 if (lower
== -DBL_MAX
) {
1570 fputs("-infinity", file
);
1573 double fracpart
= 0;
1574 fracpart
= modf(lower
, &intpart
);
1575 if (fracpart
== 0) {
1576 fprintf(file
, "%.1Lf", lower
);
1578 fprintf(file
, "%Lg", lower
);
1582 fputs(" .. ", file
);
1583 if (upperExclusive
) {
1587 if (upper
== DBL_MAX
) {
1588 fputs("infinity", file
);
1591 double fracpart
= 0;
1592 fracpart
= modf(upper
, &intpart
);
1593 if (fracpart
== 0) {
1594 fprintf(file
, "%.1Lf", upper
);
1596 fprintf(file
, "%Lg", upper
);