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)
53 SimpleType::SimpleType(const SimpleType
& other
)
55 , builtInBase(other
.builtInBase
)
56 , length(other
.length
)
57 , pattern(other
.pattern
)
58 , enumeration(other
.enumeration
)
59 , whitespace(other
.whitespace
)
61 , element_form_as(other
.element_form_as
)
62 , attribute_form_as(other
.attribute_form_as
)
64 , outside_reference(other
.outside_reference
)
65 , in_name_only(other
.in_name_only
)
66 , fromRef(other
.fromRef
)
67 , xsdtype(other
.xsdtype
)
68 , isOptional(other
.isOptional
)
69 , substitutionGroup(other
.substitutionGroup
)
70 , subsGroup(other
.subsGroup
)
71 , typeSubsGroup(other
.typeSubsGroup
)
72 , addedToTypeSubstitution(other
.addedToTypeSubstitution
)
74 , inList(other
.inList
)
77 pattern
.parent
= this;
78 enumeration
.parent
= this;
79 whitespace
.p_parent
= this;
83 void SimpleType::loadWithValues() {
84 const XMLParser::TagAttributes
& atts
= parser
->getActualTagAttributes();
85 switch (parser
->getActualTagName()) {
87 type
.upload(atts
.base
);
88 setReference(atts
.base
);
89 mode
= restrictionMode
;
92 type
.upload(atts
.itemType
);
93 setReference(atts
.itemType
);
95 setMaxOccurs(ULLONG_MAX
);
101 { // generating complextype from simpletype
102 ComplexType
* new_complextype
= new ComplexType(*this, ComplexType::fromTagUnion
);
103 new_complextype
->loadWithValues();
107 name
.upload(atts
.name
);
108 type
.upload(atts
.type
);
109 setReference(atts
.type
, true);
110 if (!atts
.nillable
) {
111 applyDefaultAttribute(atts
.default_
);
112 applyFixedAttribute(atts
.fixed
);
114 applyAbstractAttribute(atts
.abstract
);
115 applySubstitionGroupAttribute(atts
.substitionGroup
);
116 applyBlockAttribute(atts
.block
);
117 //This shall be the last instruction always
118 applyNillableAttribute(atts
.nillable
);
121 name
.upload(atts
.name
);
122 type
.upload(atts
.type
);
123 xsdtype
= n_attribute
;
124 setReference(atts
.type
, true);
125 applyDefaultAttribute(atts
.default_
);
126 applyFixedAttribute(atts
.fixed
);
129 name
.upload(atts
.name
);
132 { // generating complextype from simpletype
133 ComplexType
* new_complextype
= new ComplexType(*this, ComplexType::fromTagComplexType
);
134 new_complextype
->loadWithValues();
138 if (inList
&& (xsdtype
!= n_NOTSET
|| mode
== restrictionAfterListMode
)) {
139 setMinOccurs(strtoull(atts
.value
.c_str(), NULL
, 0));
140 setMaxOccurs(strtoull(atts
.value
.c_str(), NULL
, 0));
143 length
.facet_minLength
= strtoull(atts
.value
.c_str(), NULL
, 0);
144 length
.facet_maxLength
= strtoull(atts
.value
.c_str(), NULL
, 0);
145 length
.modified
= true;
148 if (inList
&& (xsdtype
!= n_NOTSET
|| mode
== restrictionAfterListMode
)) {
149 setMinOccurs(strtoull(atts
.value
.c_str(), NULL
, 0));
152 length
.facet_minLength
= strtoull(atts
.value
.c_str(), NULL
, 0);
153 length
.modified
= true;
156 if (inList
&& (xsdtype
!= n_NOTSET
|| mode
== restrictionAfterListMode
)) {
157 setMaxOccurs(strtoull(atts
.value
.c_str(), NULL
, 0));
160 length
.facet_maxLength
= strtoull(atts
.value
.c_str(), NULL
, 0);
161 length
.modified
= true;
164 pattern
.facet
= atts
.value
;
165 pattern
.modified
= true;
168 enumeration
.facets
.push_back(atts
.value
);
169 enumeration
.modified
= true;
172 whitespace
.facet
= atts
.value
;
173 whitespace
.modified
= true;
176 if (atts
.value
== "NaN") {
177 value
.not_a_number
= true;
178 } else if (atts
.value
== "-INF") {
179 value
.facet_minInclusive
= -DBL_MAX
;
180 } else if (atts
.value
== "INF") {
181 value
.facet_minInclusive
= DBL_MAX
;
183 value
.facet_minInclusive
= stringToLongDouble(atts
.value
.c_str());
185 value
.modified
= true;
188 if (atts
.value
== "NaN") {
189 value
.not_a_number
= true;
190 } else if (atts
.value
== "-INF") {
191 value
.facet_maxInclusive
= -DBL_MAX
;
192 } else if (atts
.value
== "INF") {
193 value
.facet_maxInclusive
= DBL_MAX
;
195 value
.facet_maxInclusive
= stringToLongDouble(atts
.value
.c_str());
197 value
.modified
= true;
200 if (atts
.value
== "NaN") {
202 } else if (atts
.value
== "-INF") {
203 value
.facet_minExclusive
= -DBL_MAX
;
204 } else if (atts
.value
== "INF") {
207 value
.facet_minExclusive
= stringToLongDouble(atts
.value
.c_str());
209 value
.modified
= true;
210 value
.lowerExclusive
= true;
213 if (atts
.value
== "NaN") {
215 } else if (atts
.value
== "-INF") {
217 } else if (atts
.value
== "INF") {
218 value
.facet_maxExclusive
= DBL_MAX
;
220 value
.facet_maxExclusive
= stringToLongDouble(atts
.value
.c_str());
222 value
.modified
= true;
223 value
.upperExclusive
= true;
226 value
.facet_totalDigits
= strtoul(atts
.value
.c_str(), NULL
, 0);
227 value
.modified
= true;
229 case n_fractionDigits
:
230 //addVariant(V_fractionDigits, atts.value);
233 addComment(Mstring("LABEL:"));
236 addComment(Mstring("DEFINITION:"));
243 void SimpleType::applyDefaultAttribute(const Mstring
& default_value
) {
244 if (!default_value
.empty()) {
245 value
.default_value
= default_value
;
246 const Mstring nameT
= type
.originalValueWoPrefix
.getValueWithoutPrefix(':');
247 //Not supported for hexBinary and base64Binary
248 if (nameT
!= "hexBinary" && nameT
!= "base64Binary") {
249 addVariant(V_defaultForEmpty
, default_value
);
254 void SimpleType::applyFixedAttribute(const Mstring
& fixed_value
) {
255 if (!fixed_value
.empty()) {
256 value
.fixed_value
= fixed_value
;
257 value
.modified
= true;
258 const Mstring nameT
= type
.originalValueWoPrefix
.getValueWithoutPrefix(':');
259 //Not supported for hexBinary and base64Binary
260 if (nameT
!= "hexBinary" && nameT
!= "base64Binary") {
261 addVariant(V_defaultForEmpty
, fixed_value
);
266 void SimpleType::applyNillableAttribute(const bool nillable
) {
268 ComplexType
* new_complextype
= new ComplexType(*this, ComplexType::fromTagNillable
); // generating complextype from simpletype
269 new_complextype
->loadWithValues();
273 void SimpleType::applyAbstractAttribute(const bool abstract_value
) {
274 if (abstract_value
) {
275 addVariant(V_abstract
);
279 void SimpleType::applySubstitionGroupAttribute(const Mstring
& substitution_group
){
280 if(!substitution_group
.empty()){
281 substitutionGroup
= substitution_group
;
285 void SimpleType::applyBlockAttribute(const BlockValue block_
){
286 if(block_
== not_set
){
287 block
= getModule()->getBlockDefault();
293 void SimpleType::addToSubstitutions(){
294 if(!g_flag_used
|| substitutionGroup
.empty()){
297 SimpleType
* st_
= (SimpleType
*) TTCN3ModuleInventory::getInstance().lookup(this, substitutionGroup
, want_BOTH
);
299 printError(module
->getSchemaname(), name
.convertedValue
,
300 "Reference for a non-defined type: " + substitutionGroup
);
301 TTCN3ModuleInventory::getInstance().incrNumErrors();
304 SimpleType
* st
= (SimpleType
*)st_
;
305 if(st
->getSubstitution() != NULL
){
306 st
= st
->getSubstitution();
309 st
->referenceResolving();
310 substitutionGroup
= empty_string
;
312 if(st
->subsGroup
== NULL
){
313 ComplexType
* head_element
= new ComplexType(*st
, ComplexType::fromTagSubstitution
);
314 for(List
<SimpleType
*>::iterator simpletype
= st
->nameDepList
.begin(); simpletype
; simpletype
= simpletype
->Next
){
315 head_element
->getNameDepList().push_back(simpletype
->Data
);
317 st
->nameDepList
.clear();
318 st
->getModule()->addMainType(head_element
);
319 head_element
->addVariant(V_untagged
);
320 head_element
->addSubstitution(st
);
321 head_element
->addSubstitution(this);
322 //if st->subsGroup == this, then it is a generated subs group
323 st
->subsGroup
= head_element
;
326 st
->subsGroup
->addSubstitution(this);
330 void SimpleType::addToTypeSubstitutions() {
331 //If the user did not request type substitution generation or
332 //the type is already added to type substitution
333 if(!h_flag_used
|| addedToTypeSubstitution
){
336 //Only available if it is a restricion or extension
337 if(mode
!= extensionMode
&& mode
!= restrictionMode
){
340 //Only top level complexTypes or simpleTypes, ergo no elements
341 if(parent
!= NULL
|| hasVariant(Mstring("\"element\""))){
345 //It would be nice if here outside_reference.resolved to everything
347 SimpleType
* st
= (SimpleType
*)outside_reference
.get_ref();
348 if(st
== NULL
&& !isBuiltInType(type
.convertedValue
)){
349 //Not even a reference, and not a built in type
351 }else if(st
== NULL
&& isBuiltInType(type
.convertedValue
)){
352 st
= new SimpleType(parser
, module
, construct
);
353 st
->type
.upload(type
.convertedValue
);
354 st
->name
.upload(type
.convertedValue
);
355 st
->typeSubsGroup
= findBuiltInTypeInStoredTypeSubstitutions(type
.convertedValue
);
356 outside_reference
.set_resolved(st
);
357 //Add this decoy type to the maintypes -> module will free st
358 //st->setInvisible();
359 module
->addMainType(st
);
363 addedToTypeSubstitution
= true;
364 st
->addToTypeSubstitutions();
365 //If type substitution is NULL then we need to create the union
366 if(st
->getTypeSubstitution() == NULL
){
367 ComplexType
* head_element
= new ComplexType(*st
, ComplexType::fromTypeSubstitution
);
368 head_element
->getNameDepList().clear();
369 for(List
<SimpleType
*>::iterator simpletype
= st
->nameDepList
.begin(), nextST
; simpletype
; simpletype
= nextST
){
370 nextST
= simpletype
->Next
;
371 //Don't add if it is in a type substitution
372 if(simpletype
->Data
->getTypeSubstitution() == NULL
){
373 head_element
->getNameDepList().push_back(simpletype
->Data
);
374 st
->getNameDepList().remove(simpletype
);
378 st
->getModule()->addMainType(head_element
);
379 head_element
->addVariant(V_useType
);
380 //For cascading type substitution
381 if(st
->outside_reference
.get_ref() != NULL
&& ((ComplexType
*)st
->outside_reference
.get_ref())->getTypeSubstitution() != NULL
){
382 head_element
->setParentTypeSubsGroup(((ComplexType
*)st
->outside_reference
.get_ref())->getTypeSubstitution());
384 head_element
->addTypeSubstitution(st
);
385 head_element
->addTypeSubstitution(this);
387 //Check to find if there was already an element reference with this type
388 for(List
<typeNameDepList
>::iterator str
= module
->getElementTypes().begin(); str
; str
= str
->Next
){
389 Mstring prefix
= str
->Data
.type
.getPrefix(':');
390 Mstring value_
= str
->Data
.type
.getValueWithoutPrefix(':');
392 if((value_
== st
->getName().convertedValue
.getValueWithoutPrefix(':') && prefix
== module
->getTargetNamespaceConnector()) ||
393 (isBuiltInType(value_
) && !isBuiltInType(st
->getType().convertedValue
) && value_
== st
->getType().convertedValue
&& prefix
== module
->getTargetNamespaceConnector())){
394 //Push the namedeplist
395 for(List
<SimpleType
*>::iterator simpletype
= str
->Data
.nameDepList
.begin(); simpletype
; simpletype
= simpletype
->Next
){
396 head_element
->getNameDepList().push_back(simpletype
->Data
);
399 str
->Data
.typeSubsGroup
= head_element
;
404 head_element
->setInvisible();
406 st
->typeSubsGroup
= head_element
;
407 st
->getModule()->addStoredTypeSubstitution(head_element
);
409 st
->getTypeSubstitution()->addTypeSubstitution(this);
412 //Make the decoy invisible
417 void SimpleType::collectElementTypes(SimpleType
* found_ST
, ComplexType
* found_CT
){
418 //Only if type substitution is enabled and it is a top level(simpletype) element or
419 //it is a not top level element(complextype)
420 if(h_flag_used
&& (hasVariant(Mstring("\"element\"")) || xsdtype
== n_element
)){
421 SimpleType
* st
= NULL
, *nameDep
= NULL
;
422 Mstring uri
, value_
, type_
;
423 if(found_ST
!= NULL
|| found_CT
!= NULL
){
424 // st := found_ST or found_CT, which is not null
425 st
= found_ST
!= NULL
? found_ST
: found_CT
;
426 uri
= outside_reference
.get_uri();
427 value_
= outside_reference
.get_val();
429 }else if(isBuiltInType(type
.convertedValue
)){
431 uri
= module
->getTargetNamespace();
432 value_
= type
.convertedValue
;
433 if(outside_reference
.empty()){
437 type_
= outside_reference
.get_val();
440 //It is not possible to reach here (should be)
443 type_
= type_
.getValueWithoutPrefix(':');
445 const Mstring typeSubsName
= value_
+ Mstring("_derivations");
446 //Find if we already have a substitution type to this element reference
447 for(List
<ComplexType
*>::iterator
complex = st
->getModule()->getStoredTypeSubstitutions().begin(); complex; complex = complex->Next
){
449 if(uri
== st
->getModule()->getTargetNamespace() && typeSubsName
== complex->Data
->getName().convertedValue
){
450 complex->Data
->setVisible();
451 if(st
->getXsdtype() != n_NOTSET
&& this == st
){ //otherwise records would be renamed too
452 complex->Data
->addToNameDepList(st
);
453 ((ComplexType
*)st
)->setNameDep(nameDep
);
459 //Add the reference, to future possible type substitution
461 Mstring prefix
= st
->getModule()->getTargetNamespaceConnector();
462 if(prefix
!= empty_string
){
465 st
->getModule()->addElementType(prefix
+ type_
, nameDep
);
470 ComplexType
* SimpleType::findBuiltInTypeInStoredTypeSubstitutions(const Mstring
& builtInType
){
471 const Mstring typeSubsName
= builtInType
.getValueWithoutPrefix(':') + Mstring("_derivations");
472 for(List
<ComplexType
*>::iterator
complex = module
->getStoredTypeSubstitutions().begin(); complex; complex = complex->Next
){
473 if(typeSubsName
== complex->Data
->getName().convertedValue
){
474 return complex->Data
;
481 void SimpleType::setReference(const Mstring
& ref
, bool only_name_dependency
) {
485 if (isBuiltInType(ref
)) {
486 builtInBase
= ref
.getValueWithoutPrefix(':');
487 if (name
.convertedValue
.empty()) {
490 if (type
.convertedValue
.empty() || type
.convertedValue
== "anySimpleType") {
491 type
.upload(ref
.getValueWithoutPrefix(':'));
497 Mstring refPrefix
= ref
.getPrefix(':');
498 Mstring refValue
= ref
.getValueWithoutPrefix(':');
500 // Find the URI amongst the known namespace URIs
501 List
<NamespaceType
>::iterator declNS
;
502 for (declNS
= module
->getDeclaredNamespaces().begin(); declNS
; declNS
= declNS
->Next
) {
503 if (refPrefix
== declNS
->Data
.prefix
) {
504 refUri
= declNS
->Data
.uri
;
509 // FIXME: can this part be moved above the search ?
510 if (refUri
.empty()) { // not found
511 if (refPrefix
== "xml") {
512 refUri
= "http://www.w3.org/XML/1998/namespace";
513 } else if (refPrefix
== "xmlns") {
514 refUri
= "http://www.w3.org/2000/xmlns";
515 } else if (refPrefix
.empty() && module
->getTargetNamespace() == "NoTargetNamespace") {
516 refUri
= "NoTargetNamespace";
520 if (refUri
.empty()) { // something is incorrect - unable to find the uri to the given prefix
521 if (refPrefix
.empty()) {
522 printError(module
->getSchemaname(), parser
->getActualLineNumber(),
523 Mstring("The absent namespace must be imported because "
524 "it is not the same as the target namespace of the current schema."));
525 parser
->incrNumErrors();
528 printError(module
->getSchemaname(), parser
->getActualLineNumber(),
529 "The value \'" + ref
+ "\' is incorrect: "
530 "A namespace prefix does not denote any URI.");
531 parser
->incrNumErrors();
536 if (only_name_dependency
) {
540 outside_reference
.load(refUri
, refValue
, &declNS
->Data
);
543 void SimpleType::referenceResolving() {
544 if (outside_reference
.empty() || outside_reference
.is_resolved()){
545 addToTypeSubstitutions();
546 collectElementTypes();
548 if(outside_reference
.empty() && substitutionGroup
.empty()) return;
549 if (outside_reference
.is_resolved()) return;
551 if(!outside_reference
.empty()){
552 SimpleType
* found_ST
= static_cast<SimpleType
*> (
553 TTCN3ModuleInventory::getInstance().lookup(this, want_ST
));
554 ComplexType
* found_CT
= static_cast<ComplexType
*> (
555 TTCN3ModuleInventory::getInstance().lookup(this, want_CT
));
556 // It _is_ possible to find both
557 collectElementTypes(found_ST
, found_CT
);
558 if (found_ST
!= NULL
) {
559 if (!found_ST
->outside_reference
.empty() && !found_ST
->outside_reference
.is_resolved() && found_ST
!= this) {
560 found_ST
->referenceResolving();
561 if(!found_ST
->outside_reference
.is_resolved()){
562 found_ST
->outside_reference
.set_resolved(NULL
);
565 referenceForST(found_ST
);
566 addToTypeSubstitutions();
567 if (!isBuiltInType(type
.convertedValue
)) {
568 found_ST
->addToNameDepList(this);
570 } else if (found_CT
!= NULL
) {
571 referenceForCT(found_CT
);
572 addToTypeSubstitutions();
573 if (!isBuiltInType(type
.convertedValue
)) {
574 found_CT
->addToNameDepList(this);
577 printError(module
->getSchemaname(), name
.convertedValue
,
578 "Reference for a non-defined type: " + outside_reference
.repr());
579 TTCN3ModuleInventory::getInstance().incrNumErrors();
580 outside_reference
.set_resolved(NULL
);
582 addToSubstitutions();
584 addToSubstitutions();
588 void SimpleType::referenceForST(SimpleType
* found_ST
) {
589 outside_reference
.set_resolved(found_ST
);
594 if (construct
== c_element
)
597 if (mode
== listMode
|| mode
== restrictionAfterListMode
)
600 if (!found_ST
->builtInBase
.empty()) {
601 builtInBase
= found_ST
->builtInBase
;
604 length
.applyReference(found_ST
->length
);
605 pattern
.applyReference(found_ST
->pattern
);
606 enumeration
.applyReference(found_ST
->enumeration
);
607 whitespace
.applyReference(found_ST
->whitespace
);
608 value
.applyReference(found_ST
->value
);
610 mode
= found_ST
->mode
;
611 if (found_ST
->mode
!= listMode
&& found_ST
->mode
!= restrictionAfterListMode
) {
612 type
.upload(found_ST
->getType().convertedValue
);
616 void SimpleType::referenceForCT(ComplexType
* found_CT
) {
617 outside_reference
.set_resolved(found_CT
);
622 // Section 7.5.3 Example5
623 if (found_CT
->getType().convertedValue
== Mstring("union") && mode
== restrictionMode
) {
624 for (List
<Mstring
>::iterator facet
= enumeration
.facets
.begin(); facet
; facet
= facet
->Next
) {
625 enumeration
.items_misc
.push_back(facet
->Data
);
628 size_t value_size
= value
.items_with_value
.size(); //Used to check changes
629 enumeration
.modified
= false;
630 for (List
<Mstring
>::iterator itemMisc
= enumeration
.items_misc
.begin(); itemMisc
; itemMisc
= itemMisc
->Next
) {
631 size_t act_size
= value
.items_with_value
.size(); //Used to detect if field did not match any field
632 for (List
<ComplexType
*>::iterator field
= found_CT
->complexfields
.begin(); field
; field
= field
->Next
) {
633 if (isIntegerType(field
->Data
->getType().convertedValue
)) {
636 sscanf(itemMisc
->Data
.c_str(), "%d%n", &val
, &read_chars
);
637 if ((size_t) read_chars
== itemMisc
->Data
.size()) {
638 expstring_t tmp_string
= mprintf("{%s:=%d}",
639 field
->Data
->getName().convertedValue
.c_str(), val
);
640 value
.items_with_value
.push_back(Mstring(tmp_string
));
645 if (isFloatType(field
->Data
->getType().convertedValue
)) {
648 sscanf(itemMisc
->Data
.c_str(), "%f%n", &val
, &read_chars
);
649 if ((size_t) read_chars
== itemMisc
->Data
.size()) {
650 expstring_t tmp_string
= mprintf("{%s:=%f}",
651 field
->Data
->getName().convertedValue
.c_str(), val
);
652 value
.items_with_value
.push_back(Mstring(tmp_string
));
657 if (isTimeType(field
->Data
->getType().convertedValue
)) {
658 if (matchDates(itemMisc
->Data
.c_str(), field
->Data
->getType().originalValueWoPrefix
.c_str())) {
659 expstring_t tmp_string
= mprintf("{%s:=\"%s\"}",
660 field
->Data
->getName().convertedValue
.c_str(), itemMisc
->Data
.c_str());
661 value
.items_with_value
.push_back(Mstring(tmp_string
));
666 if (isStringType(field
->Data
->getType().convertedValue
)) {
667 expstring_t tmp_string
= mprintf("{%s:=\"%s\"}",
668 field
->Data
->getName().convertedValue
.c_str(), itemMisc
->Data
.c_str());
669 value
.items_with_value
.push_back(Mstring(tmp_string
));
674 if (act_size
== value
.items_with_value
.size()) {
675 printWarning(getModule()->getSchemaname(), getName().convertedValue
,
676 Mstring("The following enumeration did not match any field: ") + itemMisc
->Data
+ Mstring("."));
677 TTCN3ModuleInventory::getInstance().incrNumWarnings();
681 if (value_size
!= value
.items_with_value
.size()) {
682 value
.modified
= true;
686 void SimpleType::nameConversion(NameConversionMode conversion_mode
, const List
<NamespaceType
> & ns
) {
688 switch (conversion_mode
) {
690 nameConversion_names();
693 nameConversion_types(ns
);
700 void SimpleType::nameConversion_names() {
701 Mstring res
, var(module
->getTargetNamespace());
702 XSDName2TTCN3Name(name
.convertedValue
, TTCN3ModuleInventory::getInstance().getTypenames(), type_name
, res
, var
);
703 name
.convertedValue
= res
;
704 addVariant(V_onlyValue
, var
);
705 for (List
<SimpleType
*>::iterator st
= nameDepList
.begin(); st
; st
= st
->Next
) {
706 st
->Data
->setTypeValue(res
);
710 void SimpleType::nameConversion_types(const List
<NamespaceType
> & ns
) {
711 if (type
.convertedValue
== "record" || type
.convertedValue
== "set"
712 || type
.convertedValue
== "union" || type
.convertedValue
== "enumerated") return;
714 Mstring prefix
= type
.convertedValue
.getPrefix(':');
715 Mstring value_str
= type
.convertedValue
.getValueWithoutPrefix(':');
718 for (List
<NamespaceType
>::iterator namesp
= ns
.begin(); namesp
; namesp
= namesp
->Next
) {
719 if (prefix
== namesp
->Data
.prefix
) {
720 uri
= namesp
->Data
.uri
;
725 QualifiedName
tmp(uri
, value_str
);
727 QualifiedNames::iterator origTN
= TTCN3ModuleInventory::getInstance().getTypenames().begin();
728 for (; origTN
; origTN
= origTN
->Next
) {
729 if (tmp
== origTN
->Data
) {
730 QualifiedName
tmp_name(module
->getTargetNamespace(), name
.convertedValue
);
731 if (tmp_name
== origTN
->Data
)
732 continue; // get a new type name
737 if (origTN
!= NULL
) {
738 setTypeValue(origTN
->Data
.name
);
739 // This ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ is always value_str
740 // The only effect here is to remove the "xs:" prefix from type.convertedValue,
741 // otherwise the new value is always the same as the old.
744 XSDName2TTCN3Name(value_str
, TTCN3ModuleInventory::getInstance().getTypenames(), type_reference_name
, res
, var
);
749 void SimpleType::finalModification() {
751 length
.applyFacets();
752 pattern
.applyFacet();
753 whitespace
.applyFacet();
754 enumeration
.applyFacets();
756 if (module
->getElementFormDefault() == qualified
&&
757 element_form_as
== unqualified
) {
758 addVariant(V_formAs
, Mstring("unqualified"));
759 } else if (module
->getElementFormDefault() != qualified
&&
760 element_form_as
== qualified
) {
761 addVariant(V_formAs
, Mstring("qualified"));
764 if (module
->getAttributeFormDefault() == qualified
&&
765 attribute_form_as
== unqualified
) {
766 addVariant(V_formAs
, Mstring("unqualified"));
767 } else if (module
->getAttributeFormDefault() != qualified
&&
768 attribute_form_as
== qualified
) {
769 addVariant(V_formAs
, Mstring("qualified"));
772 if (type
.originalValueWoPrefix
== Mstring("boolean")) {
773 addVariant(V_onlyValueHidden
, Mstring("\"text 'false' as '0'\""));
774 addVariant(V_onlyValueHidden
, Mstring("\"text 'true' as '1'\""));
777 isOptional
= isOptional
|| (getMinOccurs() == 0 && getMaxOccurs() == 0);
779 // If the type name is the same as the identifier then we have to prefix it
780 // with the module identifier.
781 if (type
.convertedValue
== name
.convertedValue
&& !outside_reference
.empty()) {
782 List
<const TTCN3Module
*>::iterator import_module
= module
->getImportedModules().begin();
783 for (; import_module
; import_module
= import_module
->Next
) {
784 if (import_module
->Data
->getTargetNamespace() == outside_reference
.get_uri()) {
785 type
.upload(import_module
->Data
->getModulename() + Mstring(".") + type
.convertedValue
);
792 bool SimpleType::hasUnresolvedReference() {
793 if (!outside_reference
.empty() && !outside_reference
.is_resolved()) {
800 void SimpleType::applyRefAttribute(const Mstring
& ref_value
) {
801 if (!ref_value
.empty()) {
802 setReference(ref_value
);
807 void SimpleType::printToFile(FILE * file
) {
814 fputs("type ", file
);
815 if(enumeration
.modified
&& hasVariant(Mstring("\"list\""))){
816 printMinOccursMaxOccurs(file
, false);
817 fprintf(file
, "enumerated\n{\n");
818 enumeration
.sortFacets();
819 enumeration
.printToFile(file
);
820 fprintf(file
, "\n} %s", name
.convertedValue
.c_str());
821 } else if (enumeration
.modified
) {
822 if (isFloatType(builtInBase
)) {
823 fprintf(file
, "%s %s (", type
.convertedValue
.c_str(), name
.convertedValue
.c_str());
824 enumeration
.sortFacets();
825 enumeration
.printToFile(file
);
828 fprintf(file
, "enumerated %s\n{\n", name
.convertedValue
.c_str());
829 enumeration
.sortFacets();
830 enumeration
.printToFile(file
);
834 printMinOccursMaxOccurs(file
, false);
836 int multiplicity
= multi(module
, outside_reference
, this);
837 const RootType
*type_ref
= outside_reference
.get_ref();
838 if ((multiplicity
> 1) && type_ref
839 && type_ref
->getModule() != module
) {
840 fprintf(file
, "%s.", type_ref
->getModule()->getModulename().c_str());
843 fprintf(file
, "%s %s",
844 type
.convertedValue
.c_str(), name
.convertedValue
.c_str());
845 pattern
.printToFile(file
);
846 value
.printToFile(file
);
847 length
.printToFile(file
);
849 enumeration
.insertVariants();
851 fputs(";\n\n\n", file
);
854 void SimpleType::dump(unsigned int depth
) const {
855 static const char *modes
[] = {
856 "", "restriction", "extension", "list"
858 fprintf(stderr
, "%*s SimpleType '%s' -> '%s' at %p\n", depth
* 2, "",
859 name
.originalValueWoPrefix
.c_str(), name
.convertedValue
.c_str(),
861 fprintf(stderr
, "%*s type '%s' -> '%s'\n", depth
* 2, "",
862 type
.originalValueWoPrefix
.c_str(), type
.convertedValue
.c_str());
864 if (mode
!= noMode
) {
865 fprintf(stderr
, "%*s %s, base='%s'\n", depth
* 2, "", modes
[mode
], builtInBase
.c_str());
868 // fprintf (stderr, "%*s rfo='%s' n_d='%s'\n", depth * 2, "",
869 // reference_for_other.c_str(), name_dependency.c_str());
872 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
874 LengthType::LengthType(SimpleType
* a_simpleType
)
875 : parent(a_simpleType
)
878 , facet_maxLength(ULLONG_MAX
)
880 , upper(ULLONG_MAX
) {
883 void LengthType::applyReference(const LengthType
& other
) {
884 if (!modified
) modified
= other
.modified
;
885 if (other
.facet_minLength
> facet_minLength
) facet_minLength
= other
.facet_minLength
;
886 if (other
.facet_maxLength
< facet_maxLength
) facet_maxLength
= other
.facet_maxLength
;
889 void LengthType::applyFacets() // only for string types and list types without QName
891 if (!modified
) return;
893 switch (parent
->getMode()) {
894 case SimpleType::restrictionMode
:
896 const Mstring
& base
= parent
->getBuiltInBase();
897 if ((isStringType(base
) || (isSequenceType(base
) && base
!= "QName") || isAnyType(base
)) || base
.empty()) {
898 lower
= facet_minLength
;
899 upper
= facet_maxLength
;
901 printWarning(parent
->getModule()->getSchemaname(), parent
->getName().convertedValue
,
902 Mstring("Length restriction is not supported on type '") + base
+ Mstring("'."));
903 TTCN3ModuleInventory::getInstance().incrNumWarnings();
907 case SimpleType::extensionMode
:
908 case SimpleType::listMode
:
909 case SimpleType::restrictionAfterListMode
:
910 lower
= facet_minLength
;
911 upper
= facet_maxLength
;
913 case SimpleType::noMode
:
917 printError(parent
->getModule()->getSchemaname(), parent
->getName().convertedValue
,
918 Mstring("The upper boundary of length restriction cannot be smaller than the lower boundary."));
919 TTCN3ModuleInventory::getInstance().incrNumErrors();
924 void LengthType::printToFile(FILE * file
) const {
925 if (!modified
) return;
926 if (parent
->getEnumeration().modified
) return;
928 if (lower
== upper
) {
929 fprintf(file
, " length(%llu)", lower
);
931 fprintf(file
, " length(%llu .. ", lower
);
933 if (upper
== ULLONG_MAX
) {
934 fputs("infinity", file
);
936 fprintf(file
, "%llu", upper
);
943 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
945 PatternType::PatternType(SimpleType
* a_simpleType
)
946 : parent(a_simpleType
)
952 void PatternType::applyReference(const PatternType
& other
) {
953 if (!modified
) modified
= other
.modified
;
954 if (facet
.empty()) facet
= other
.facet
;
957 void PatternType::applyFacet() // only for time types and string types without hexBinary
959 if (!modified
) return;
961 const Mstring
& base
= parent
->getBuiltInBase();
962 if (((isStringType(base
) && base
!= "hexBinary") || isTimeType(base
) || isAnyType(base
)) || base
.empty()) {
963 // XSD pattern to TTCN-3 pattern; ETSI ES 201 873-9 clause 6.1.4
964 // FIXME a proper scanner is needed, e.g. from flex
966 for (size_t i
= 0; i
!= facet
.size(); ++i
) {
970 value
+= charclass
? "\\("
974 value
+= charclass
? "\\)"
981 value
+= charclass
? "\\^"
992 case '.': // any character
993 value
+= charclass
? '.'
996 case '*': // 0 or more
997 value
+= '*'; //#(0,)
1000 value
+= '+'; //#(1,)
1003 value
+= charclass
? "?"
1011 if (charclass
== 0) {
1014 while (facet
[i
+ k
] != '}') {
1019 match
= sscanf(s
.c_str(), "%i,%i", &a
, &b
);
1020 if (match
== 1 || match
== 2) {
1034 value
+= charclass
? "\\}"
1039 // Appendix G1.1 of XML Schema Datatypes: Character class escapes;
1040 // specifically, http://www.w3.org/TR/xmlschema11-2/#nt-MultiCharEsc
1041 char cn
= facet
[i
+ 1];
1044 value
+= charclass
? "\\w\\d.\\-_:"
1048 value
+= charclass
? "^\\w\\d.\\-_:"
1049 : "[^\\w\\d.\\-_:]";
1052 value
+= charclass
? "^\\d"
1056 value
+= charclass
? "\\w\\d:"
1060 value
+= charclass
? "^\\w\\d:"
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
? "^\\q{0,0,0,20}\\q{0,0,0,10}\\t\\r"
1069 : "[^\\q{0,0,0,20}\\q{0,0,0,10}\\t\\r]";
1072 value
+= charclass
? "^\\w"
1076 printWarning(parent
->getModule()->getSchemaname(), parent
->getName().convertedValue
,
1077 Mstring("Character categories and blocks are not supported."));
1078 TTCN3ModuleInventory::getInstance().incrNumWarnings();
1080 Mstring("Pattern is not converted due to using character categories and blocks in patterns is not supported."));
1088 // backslash + another: pass unmodified; this also handles \d and \w
1097 if (facet
[i
+ 1] == '#') { // &#....;
1100 while (facet
[i
+ k
] != ';') {
1104 long long int d
= atoll(s
.c_str());
1105 if (d
< 0 || d
> 2147483647) {
1106 printError(parent
->getModule()->getSchemaname(), parent
->getName().convertedValue
,
1107 Mstring("Invalid unicode character."));
1108 TTCN3ModuleInventory::getInstance().incrNumErrors();
1110 unsigned char group
= (d
>> 24) & 0xFF;
1111 unsigned char plane
= (d
>> 16) & 0xFF;
1112 unsigned char row
= (d
>> 8) & 0xFF;
1113 unsigned char cell
= d
& 0xFF;
1115 expstring_t res
= mprintf("\\q{%d, %d, %d, %d}", group
, plane
, row
, cell
);
1120 // else fall through
1121 default: //just_copy:
1127 printWarning(parent
->getModule()->getSchemaname(), parent
->getName().convertedValue
,
1128 Mstring("Pattern restriction is not supported on type '") + base
+ Mstring("'."));
1129 TTCN3ModuleInventory::getInstance().incrNumWarnings();
1133 void PatternType::printToFile(FILE * file
) const {
1134 if (!modified
|| value
.empty()) return;
1135 if (parent
->getEnumeration().modified
) return;
1137 fprintf(file
, " (pattern \"%s\")", value
.c_str());
1140 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1142 EnumerationType::EnumerationType(SimpleType
* a_simpleType
)
1143 : parent(a_simpleType
)
1154 void EnumerationType::applyReference(const EnumerationType
& other
) {
1155 if (!modified
) modified
= other
.modified
;
1156 if ((other
.parent
->getXsdtype() == n_NOTSET
&& parent
->getMode() != SimpleType::restrictionMode
)
1157 || parent
->getXsdtype() == n_simpleType
) {
1158 for (List
<Mstring
>::iterator facet
= other
.facets
.begin(); facet
; facet
= facet
->Next
) {
1159 facets
.push_back(facet
->Data
);
1164 void EnumerationType::applyFacets() // string types, integer types, float types, time types
1166 if (!modified
) return;
1168 facets
.remove_dups();
1170 const Mstring
& base
= parent
->getBuiltInBase();
1172 if (isStringType(base
)) // here length restriction is applicable
1174 List
<Mstring
> text_variants
;
1175 for (List
<Mstring
>::iterator facet
= facets
.begin(); facet
; facet
= facet
->Next
) {
1176 const LengthType
& length
= parent
->getLength();
1177 if (length
.lower
<= facet
->Data
.size() && facet
->Data
.size() <= length
.upper
) {
1179 XSDName2TTCN3Name(facet
->Data
, items_string
, enum_id_name
, res
, var
);
1180 text_variants
.push_back(var
);
1183 text_variants
.sort();
1184 for (List
<Mstring
>::iterator var
= text_variants
.end(); var
; var
= var
->Prev
) {
1185 variants
.push_back(var
->Data
);
1187 } else if (isIntegerType(base
)) // here value restriction is applicable
1189 for (List
<Mstring
>::iterator facet
= facets
.begin(); facet
; facet
= facet
->Next
) {
1190 int int_value
= atoi(facet
->Data
.c_str());
1191 const ValueType
& value
= parent
->getValue();
1192 if (value
.lower
<= int_value
&& int_value
<= value
.upper
) {
1194 for (List
<int>::iterator itemInt
= items_int
.begin(); itemInt
; itemInt
= itemInt
->Next
) {
1195 if (int_value
== itemInt
->Data
) {
1200 if (!found
) items_int
.push_back(int_value
);
1202 if (variants
.empty() || variants
.back() != "\"useNumber\"") {
1203 variants
.push_back(Mstring("\"useNumber\""));
1207 } else if (isFloatType(base
)) // here value restriction is applicable
1209 for (List
<Mstring
>::iterator facet
= facets
.begin(); facet
; facet
= facet
->Next
) {
1210 double float_value
= atof(facet
->Data
.c_str());
1211 const ValueType
& value
= parent
->getValue();
1212 if (value
.lower
<= float_value
&& float_value
<= value
.upper
) {
1214 for (List
<double>::iterator itemFloat
= items_float
.begin(); itemFloat
; itemFloat
= itemFloat
->Next
) {
1215 if (float_value
== itemFloat
->Data
) {
1221 items_float
.push_back(float_value
);
1225 } else if (isTimeType(base
)) {
1226 List
<Mstring
> text_variants
;
1227 for (List
<Mstring
>::iterator facet
= facets
.begin(); facet
; facet
= facet
->Next
) {
1229 XSDName2TTCN3Name(facet
->Data
, items_time
, enum_id_name
, res
, var
);
1230 text_variants
.push_back(var
);
1232 text_variants
.sort();
1233 for (List
<Mstring
>::iterator var
= text_variants
.end(); var
; var
= var
->Prev
) {
1234 variants
.push_back(var
->Data
);
1236 } else if (isAnyType(base
)) {
1237 } else if (base
.empty()) {
1239 printWarning(parent
->getModule()->getSchemaname(), parent
->getName().convertedValue
,
1240 Mstring("Enumeration restriction is not supported on type '") + base
+ Mstring("'."));
1241 TTCN3ModuleInventory::getInstance().incrNumWarnings();
1242 parent
->setInvisible();
1246 void EnumerationType::sortFacets() {
1247 items_string
.sort();
1253 void EnumerationType::printToFile(FILE * file
, unsigned int indent_level
) const {
1254 if (!modified
) return;
1256 const Mstring
& base
= parent
->getBuiltInBase();
1257 if (isStringType(base
)) {
1258 for (QualifiedNames::iterator itemString
= items_string
.begin(); itemString
; itemString
= itemString
->Next
) {
1259 if (itemString
!= items_string
.begin()) fputs(",\n", file
);
1260 for (unsigned int l
= 0; l
!= indent_level
; ++l
) fputs("\t", file
);
1261 fprintf(file
, "\t%s", itemString
->Data
.name
.c_str());
1263 } else if (isIntegerType(base
)) {
1264 for (List
<int>::iterator itemInt
= items_int
.begin(); itemInt
; itemInt
= itemInt
->Next
) {
1265 if (itemInt
!= items_int
.begin()) fputs(",\n", file
);
1266 for (unsigned int l
= 0; l
!= indent_level
; ++l
) fputs("\t", file
);
1267 if (itemInt
->Data
< 0) {
1268 fprintf(file
, "\tint_%d(%d)", abs(itemInt
->Data
), itemInt
->Data
);
1270 fprintf(file
, "\tint%d(%d)", itemInt
->Data
, itemInt
->Data
);
1273 } else if (isFloatType(base
)) {
1274 for (List
<double>::iterator itemFloat
= items_float
.begin(); itemFloat
; itemFloat
= itemFloat
->Next
) {
1275 if (itemFloat
!= items_float
.begin()) fputs(", ", file
);
1278 double fracpart
= 0;
1279 fracpart
= modf(itemFloat
->Data
, &intpart
);
1280 if (fracpart
== 0) {
1281 fprintf(file
, "%lld.0", (long long int) (itemFloat
->Data
));
1283 fprintf(file
, "%g", itemFloat
->Data
);
1286 } else if (isTimeType(base
)) {
1287 for (QualifiedNames::iterator itemTime
= items_time
.begin(); itemTime
; itemTime
= itemTime
->Next
) {
1288 if (itemTime
!= items_time
.begin()) fputs(",\n", file
);
1289 for (unsigned int l
= 0; l
!= indent_level
; ++l
) fputs("\t", file
);
1290 fprintf(file
, "\t%s", itemTime
->Data
.name
.c_str());
1295 void EnumerationType::insertVariants(){
1296 if(!modified
) return;
1298 Mstring pre_connector
= empty_string
;
1299 if(parent
->getMinOccurs() == 0 && parent
->getMaxOccurs() == ULLONG_MAX
){
1300 pre_connector
= "([-]) ";
1302 for(List
<Mstring
>::iterator var
= variants
.begin(); var
; var
= var
->Next
){
1303 parent
->addVariant(V_onlyValue
, pre_connector
+ var
->Data
);
1307 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1309 WhitespaceType::WhitespaceType(SimpleType
* a_simpleType
)
1310 : p_parent(a_simpleType
)
1316 void WhitespaceType::applyReference(const WhitespaceType
& other
) {
1317 if (!modified
) modified
= other
.modified
;
1318 if (facet
.empty()) facet
= other
.facet
;
1321 void WhitespaceType::applyFacet() // only for string types: string, normalizedString, token, Name, NCName, language
1323 if (!modified
) return;
1325 const Mstring
& base
= p_parent
->getBuiltInBase();
1326 if (base
== "string" || base
== "normalizedString" || base
== "token" || base
== "language" ||
1327 base
== "Name" || base
== "NCName" || isAnyType(base
) || base
.empty()) {
1328 p_parent
->addVariant(V_whiteSpace
, facet
);
1330 printWarning(p_parent
->getModule()->getSchemaname(), p_parent
->getName().convertedValue
,
1331 Mstring("Facet 'whiteSpace' is not applicable for type '") + base
+ Mstring("'."));
1332 TTCN3ModuleInventory::getInstance().incrNumWarnings();
1336 ValueType::ValueType(SimpleType
* a_simpleType
)
1337 : parent(a_simpleType
)
1339 , facet_minInclusive(-DBL_MAX
)
1340 , facet_maxInclusive(DBL_MAX
)
1341 , facet_minExclusive(-DBL_MAX
)
1342 , facet_maxExclusive(DBL_MAX
)
1343 , facet_totalDigits(-1)
1346 , lowerExclusive(false)
1347 , upperExclusive(false)
1348 , not_a_number(false)
1351 , items_with_value() {
1354 void ValueType::applyReference(const ValueType
& other
) {
1356 modified
= other
.modified
;
1361 if (other
.not_a_number
) not_a_number
= true;
1362 if (other
.facet_minInclusive
> facet_minInclusive
) facet_minInclusive
= other
.facet_minInclusive
;
1363 if (other
.facet_maxInclusive
< facet_maxInclusive
) facet_maxInclusive
= other
.facet_maxInclusive
;
1364 if (other
.facet_minExclusive
> facet_minExclusive
) facet_minExclusive
= other
.facet_minExclusive
;
1365 if (other
.facet_maxExclusive
< facet_maxExclusive
) facet_maxExclusive
= other
.facet_maxExclusive
;
1366 if (other
.upperExclusive
) upperExclusive
= other
.upperExclusive
;
1367 if (other
.lowerExclusive
) lowerExclusive
= other
.lowerExclusive
;
1368 //-1 in case when it is not modified
1369 if (other
.facet_totalDigits
< facet_totalDigits
|| facet_totalDigits
== -1) facet_totalDigits
= other
.facet_totalDigits
;
1370 if (!other
.default_value
.empty()) {
1371 default_value
= other
.default_value
;
1372 parent
->addVariant(V_defaultForEmpty
, default_value
);
1374 if (!other
.fixed_value
.empty()) {
1375 fixed_value
= other
.fixed_value
;
1376 parent
->addVariant(V_defaultForEmpty
, fixed_value
);
1380 void ValueType::applyFacets() // only for integer and float types
1390 const Mstring
& base
= parent
->getBuiltInBase();
1392 * Setting of default value range of built-in types
1394 if (base
== "positiveInteger") {
1396 } else if (base
== "nonPositiveInteger") {
1398 } else if (base
== "negativeInteger") {
1400 } else if (base
== "nonNegativeInteger") {
1402 } else if (base
== "unsignedLong") {
1405 } else if (base
== "int") {
1408 } else if (base
== "unsignedInt") {
1411 } else if (base
== "short") {
1414 } else if (base
== "unsignedShort") {
1417 } else if (base
== "byte") {
1420 } else if (base
== "unsignedByte") {
1425 if (isIntegerType(base
)) {
1426 if (facet_minInclusive
!= -DBL_MAX
&& facet_minInclusive
> lower
) lower
= facet_minInclusive
;
1427 if (facet_maxInclusive
!= DBL_MAX
&& upper
> facet_maxInclusive
) upper
= facet_maxInclusive
;
1428 if (facet_minExclusive
!= -DBL_MAX
&& lower
< facet_minExclusive
) lower
= facet_minExclusive
;
1429 if (facet_maxExclusive
!= DBL_MAX
&& upper
> facet_maxExclusive
) upper
= facet_maxExclusive
;
1430 } else if (isFloatType(base
)) {
1431 if (facet_minInclusive
!= -DBL_MAX
&& lower
< facet_minInclusive
) lower
= facet_minInclusive
;
1432 if (facet_maxInclusive
!= DBL_MAX
&& upper
> facet_maxInclusive
) upper
= facet_maxInclusive
;
1433 if (facet_minExclusive
!= -DBL_MAX
&& lower
< facet_minExclusive
) lower
= facet_minExclusive
;
1434 if (facet_maxExclusive
!= DBL_MAX
&& upper
> facet_maxExclusive
) upper
= facet_maxExclusive
;
1435 } else if (isAnyType(base
) || isTimeType(base
) || isBooleanType(base
)) {
1436 } else if (isStringType(base
) && (
1437 base
.getValueWithoutPrefix(':') != "hexBinary" && base
.getValueWithoutPrefix(':') != "base64Binary")) {
1438 } else if (base
.empty()) {
1440 printWarning(parent
->getModule()->getSchemaname(), parent
->getName().convertedValue
,
1441 Mstring("Value restriction is not supported on type '") + base
+ Mstring("'."));
1442 TTCN3ModuleInventory::getInstance().incrNumWarnings();
1445 // totalDigits facet is only for integer types and decimal
1446 if (facet_totalDigits
> 0) // if this facet is used
1448 double r
= pow(10.0, facet_totalDigits
);
1450 if (base
== "integer") {
1451 lower
= (int) -(r
- 1);
1452 upper
= (int) (r
- 1);
1453 } else if (base
== "positiveInteger") {
1455 upper
= (int) (r
- 1);
1456 } else if (base
== "nonPositiveInteger") {
1457 lower
= (int) -(r
- 1);
1459 } else if (base
== "negativeInteger") {
1460 lower
= (int) -(r
- 1);
1462 } else if (base
== "nonNegativeInteger") {
1464 upper
= (int) (r
- 1);
1465 } else if (base
== "long" ||
1466 base
== "unsignedLong" ||
1468 base
== "unsignedInt" ||
1470 base
== "unsignedShort" ||
1472 base
== "unsignedByte") {
1473 lower
= (int) -(r
- 1);
1474 upper
= (int) (r
- 1);
1475 } else if (base
== "decimal") {
1476 lower
= (int) -(r
- 1);
1477 upper
= (int) (r
- 1);
1479 printWarning(parent
->getModule()->getSchemaname(), parent
->getName().convertedValue
,
1480 Mstring("Facet 'totalDigits' is not applicable for type '") + base
+ Mstring("'."));
1481 TTCN3ModuleInventory::getInstance().incrNumWarnings();
1484 items_with_value
.sort();
1487 void ValueType::printToFile(FILE * file
) const {
1488 if (!modified
) return;
1489 if (parent
->getEnumeration().modified
) return;
1492 fprintf(file
, " ( not_a_number )");
1495 if (!fixed_value
.empty()) {
1496 //Base64binary and hexbyte does not supported
1498 if(isBuiltInType(parent
->getType().originalValueWoPrefix
)){
1499 type
= parent
->getType().originalValueWoPrefix
;
1501 type
= getPrefixByNameSpace(parent
, parent
->getReference().get_uri()) + Mstring(":") + parent
->getReference().get_val();
1503 if(!isBuiltInType(type
)){
1504 type
= findBuiltInType(parent
, type
);
1506 if (isStringType(type
) || isTimeType(type
) || isQNameType(type
) || isAnyType(type
)) {
1507 const Mstring
& name
= type
.getValueWithoutPrefix(':');
1508 if (name
!= "hexBinary" && name
!= "base64Binary") {
1509 fprintf(file
, " (\"%s\")", fixed_value
.c_str());
1511 } else if (isBooleanType(type
)) {
1513 if (fixed_value
== "1") {
1515 } else if (fixed_value
== "0") {
1520 fprintf(file
, " (%s)", val
.c_str());
1522 fprintf(file
, " (%s)", fixed_value
.c_str());
1526 if (!items_with_value
.empty()) {
1527 fputs(" (\n", file
);
1528 for (List
<Mstring
>::iterator itemWithValue
= items_with_value
.begin(); itemWithValue
; itemWithValue
= itemWithValue
->Next
) {
1529 fprintf(file
, "\t%s", itemWithValue
->Data
.c_str());
1530 if (itemWithValue
!= items_with_value
.end()) {
1540 if (lower
== -DBL_MAX
&& upper
== DBL_MAX
) return;
1544 if (isIntegerType(parent
->getBuiltInBase())) {
1545 if (lowerExclusive
) {
1549 if (lower
== -DBL_MAX
) {
1550 fputs("-infinity", file
);
1551 } else if (lower
< 0) {
1552 long double temp_lower
= -lower
;
1553 fprintf(file
, "-%.0Lf", temp_lower
);
1555 fprintf(file
, "%.0Lf", lower
);
1558 fputs(" .. ", file
);
1559 if (upperExclusive
) {
1563 if (upper
== DBL_MAX
) {
1564 fputs("infinity", file
);
1565 } else if (upper
< 0) {
1566 long double temp_upper
= -upper
;
1567 fprintf(file
, "-%.0Lf", temp_upper
);
1569 fprintf(file
, "%.0Lf", upper
);
1571 } else if (isFloatType(parent
->getBuiltInBase())) {
1572 if (lowerExclusive
) {
1576 if (lower
== -DBL_MAX
) {
1577 fputs("-infinity", file
);
1580 double fracpart
= 0;
1581 fracpart
= modf(lower
, &intpart
);
1582 if (fracpart
== 0) {
1583 fprintf(file
, "%.1Lf", lower
);
1585 fprintf(file
, "%Lg", lower
);
1589 fputs(" .. ", file
);
1590 if (upperExclusive
) {
1594 if (upper
== DBL_MAX
) {
1595 fputs("infinity", file
);
1598 double fracpart
= 0;
1599 fracpart
= modf(upper
, &intpart
);
1600 if (fracpart
== 0) {
1601 fprintf(file
, "%.1Lf", upper
);
1603 fprintf(file
, "%Lg", upper
);