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 "XMLParser.hh"
9 #include "TTCN3ModuleInventory.hh"
11 #include "GeneralFunctions.hh"
13 #include "TTCN3Module.hh"
14 #include "SimpleType.hh"
15 #include "ComplexType.hh"
17 extern bool h_flag_used
;
18 extern bool q_flag_used
;
22 unsigned int TTCN3ModuleInventory::num_errors
= 0;
23 unsigned int TTCN3ModuleInventory::num_warnings
= 0;
25 TTCN3ModuleInventory::TTCN3ModuleInventory()
31 TTCN3ModuleInventory::~TTCN3ModuleInventory() {
32 for (List
<TTCN3Module
*>::iterator module
= definedModules
.begin(); module
; module
= module
->Next
) {
37 TTCN3ModuleInventory
& TTCN3ModuleInventory::getInstance() {
38 // Singleton, see Meyers, More Effective C++, Item 26 (page 131)
39 static TTCN3ModuleInventory instance
;
43 TTCN3Module
* TTCN3ModuleInventory::addModule(const char * xsd_filename
, XMLParser
* a_parser
) {
44 TTCN3Module
* module
= new TTCN3Module(xsd_filename
, a_parser
);
45 definedModules
.push_back(module
);
46 return definedModules
.back();
49 void TTCN3ModuleInventory::modulenameConversion() {
50 definedModules
.sort(compareModules
);
52 for (List
<TTCN3Module
*>::iterator module
= definedModules
.begin(); module
; module
= module
->Next
) {
53 module
->Data
->TargetNamespace2ModuleName();
57 void TTCN3ModuleInventory::referenceResolving() {
59 * Reference resolving for include and import statements
61 for (List
<TTCN3Module
*>::iterator module
= definedModules
.begin(); module
; module
= module
->Next
) {
62 for (List
<RootType
*>::iterator type
= module
->Data
->getDefinedTypes().begin(); type
; type
= type
->Next
) {
63 if (type
->Data
->getName().convertedValue
== "import" || type
->Data
->getName().convertedValue
== "include") {
64 type
->Data
->referenceResolving();
70 * Reference resolving for all others
72 bool there_is_unresolved_reference_somewhere
= false;
74 there_is_unresolved_reference_somewhere
= false;
76 for (List
<TTCN3Module
*>::iterator module
= definedModules
.begin(); module
; module
= module
->Next
) {
77 for (List
<RootType
*>::iterator type
= module
->Data
->getDefinedTypes().begin(); type
; type
= type
->Next
) {
78 if (type
->Data
->getName().convertedValue
!= "import" && type
->Data
->getName().convertedValue
!= "include") {
79 type
->Data
->referenceResolving();
80 if (type
->Data
->hasUnresolvedReference()) {
81 there_is_unresolved_reference_somewhere
= true;
86 } while (there_is_unresolved_reference_somewhere
);
89 void TTCN3ModuleInventory::finalModification() {
90 for (List
<TTCN3Module
*>::iterator module
= definedModules
.begin(); module
; module
= module
->Next
) {
91 for (List
<RootType
*>::iterator type
= module
->Data
->getDefinedTypes().begin(); type
; type
= type
->Next
) {
92 type
->Data
->finalModification();
97 void TTCN3ModuleInventory::nameConversion() {
99 * Sort of types and fields
102 definedModules
.sort(compareModules
);
103 /********************************************************
104 * Conversion of the name of types
105 * ******************************************************/
106 for (List
<TTCN3Module
*>::iterator module
= definedModules
.begin(); module
; module
= module
->Next
) {
107 if (module
->Data
->isnotIntoNameConversion()) continue;
109 List
<RootType
*> definedElements_inABC
;
110 List
<RootType
*> definedAttributes_inABC
;
111 List
<RootType
*> definedSimpleTypes_inABC
;
112 List
<RootType
*> definedComplexTypes_inABC
;
113 List
<RootType
*> definedAttributeGroups_inABC
;
114 List
<RootType
*> definedGroups_inABC
;
116 for (List
<TTCN3Module
*>::iterator module2
= module
; module2
; module2
= module2
->Next
) {
117 if (module2
->Data
->getModulename() != module
->Data
->getModulename()) continue;
119 for (List
<RootType
*>::iterator type
= module2
->Data
->getDefinedTypes().begin(); type
; type
= type
->Next
) {
120 switch (type
->Data
->getConstruct()) {
122 definedSimpleTypes_inABC
.push_back(type
->Data
);
125 definedElements_inABC
.push_back(type
->Data
);
128 definedAttributes_inABC
.push_back(type
->Data
);
131 definedComplexTypes_inABC
.push_back(type
->Data
);
134 definedGroups_inABC
.push_back(type
->Data
);
136 case c_attributeGroup
:
137 definedAttributeGroups_inABC
.push_back(type
->Data
);
143 module2
->Data
->notIntoNameConversion();
146 definedElements_inABC
.sort(compareTypes
);
147 definedAttributes_inABC
.sort(compareTypes
);
148 definedSimpleTypes_inABC
.sort(compareTypes
);
149 definedComplexTypes_inABC
.sort(compareTypes
);
150 definedAttributeGroups_inABC
.sort(compareTypes
);
151 definedGroups_inABC
.sort(compareTypes
);
153 typenames
.push_back(QualifiedName(module
->Data
->getTargetNamespace(), module
->Data
->getModulename()));
154 for(List
<const TTCN3Module
*>::iterator mod
= module
->Data
->getImportedModules().begin(); mod
; mod
= mod
->Next
){
155 typenames
.push_back(QualifiedName(module
->Data
->getTargetNamespace(), mod
->Data
->getModulename()));
158 for (List
<RootType
*>::iterator type
= definedElements_inABC
.begin(); type
; type
= type
->Next
) {
159 type
->Data
->nameConversion(nameMode
, module
->Data
->getDeclaredNamespaces());
161 for (List
<RootType
*>::iterator type
= definedAttributes_inABC
.begin(); type
; type
= type
->Next
) {
162 type
->Data
->nameConversion(nameMode
, module
->Data
->getDeclaredNamespaces());
164 for (List
<RootType
*>::iterator type
= definedSimpleTypes_inABC
.begin(); type
; type
= type
->Next
) {
165 type
->Data
->nameConversion(nameMode
, module
->Data
->getDeclaredNamespaces());
167 for (List
<RootType
*>::iterator type
= definedComplexTypes_inABC
.begin(); type
; type
= type
->Next
) {
168 type
->Data
->nameConversion(nameMode
, module
->Data
->getDeclaredNamespaces());
170 for (List
<RootType
*>::iterator type
= definedAttributeGroups_inABC
.begin(); type
; type
= type
->Next
) {
171 type
->Data
->nameConversion(nameMode
, module
->Data
->getDeclaredNamespaces());
173 for (List
<RootType
*>::iterator type
= definedGroups_inABC
.begin(); type
; type
= type
->Next
) {
174 type
->Data
->nameConversion(nameMode
, module
->Data
->getDeclaredNamespaces());
178 /********************************************************
179 * Conversion of the type of types
180 * ******************************************************/
181 for (List
<TTCN3Module
*>::iterator module
= definedModules
.begin(); module
; module
= module
->Next
) {
182 for (List
<RootType
*>::iterator type
= module
->Data
->getDefinedTypes().begin(); type
; type
= type
->Next
) {
183 type
->Data
->nameConversion(typeMode
, module
->Data
->getDeclaredNamespaces());
186 /********************************************************
187 * Conversion of the names and the types of the fields
188 * ******************************************************/
189 for (List
<TTCN3Module
*>::iterator module
= definedModules
.begin(); module
; module
= module
->Next
) {
190 for (List
<RootType
*>::iterator type
= module
->Data
->getDefinedTypes().begin(); type
; type
= type
->Next
) {
191 type
->Data
->nameConversion(fieldMode
, module
->Data
->getDeclaredNamespaces());
196 void TTCN3ModuleInventory::moduleGeneration() {
197 for (List
<TTCN3Module
*>::iterator module
= definedModules
.begin(); module
; module
= module
->Next
) {
198 if (module
->Data
->isnotIntoFile()) {
202 List
<NamespaceType
> used_namespaces
;
203 NamespaceType targetns
;
204 targetns
.uri
= module
->Data
->getTargetNamespace();
205 used_namespaces
.push_back(targetns
);
207 // Now search for other modules with the same module name.
208 // They must have had the same targetNamespace.
209 for (List
<TTCN3Module
*>::iterator module2
= module
; module2
; module2
= module2
->Next
) {
210 if (module2
->Data
->getModulename() != module
->Data
->getModulename()) {
214 for (List
<NamespaceType
>::iterator declNS
= module2
->Data
->getDeclaredNamespaces().begin(); declNS
; declNS
= declNS
->Next
) {
215 used_namespaces
.push_back(declNS
->Data
);
217 module2
->Data
->notIntoFile(); // first module gets the TTCN-3 file
220 Mstring filename_s
= module
->Data
->getModulename() + ".ttcn";
221 FILE * file
= fopen(filename_s
.c_str(), "w");
223 Mstring
cannot_write("Cannot write file ");
224 perror((cannot_write
+ filename_s
).c_str());
229 // In debug mode, set the output stream to unbuffered.
230 // This allows watching the output as it appears (e.g. with tail -f).
231 setvbuf(file
, NULL
, _IONBF
, 0);
234 module
->Data
->generate_TTCN3_header(file
);
236 fprintf(file
, "//\tGenerated from file(s):\n");
238 for (List
<TTCN3Module
*>::iterator module2
= module
; module2
; module2
= module2
->Next
) {
239 if (module2
->Data
->getModulename() == module
->Data
->getModulename()) {
240 module2
->Data
->generate_TTCN3_fileinfo(file
);
245 "////////////////////////////////////////////////////////////////////////////////\n"
246 "// Modification header(s):\n"
247 "//-----------------------------------------------------------------------------\n"
249 "// Modification date:\n"
251 "// Modification contact:\n"
252 "//------------------------------------------------------------------------------\n"
253 "////////////////////////////////////////////////////////////////////////////////\n"
257 module
->Data
->generate_TTCN3_modulestart(file
);
259 for (List
<TTCN3Module
*>::iterator module2
= module
; module2
; module2
= module2
->Next
) {
260 if (module2
->Data
->getModulename() == module
->Data
->getModulename()) {
261 module2
->Data
->generate_TTCN3_import_statements(file
);
265 writtenImports
.clear();
267 for (List
<TTCN3Module
*>::iterator module2
= module
; module2
; module2
= module2
->Next
) {
268 if (module2
->Data
->getModulename() == module
->Data
->getModulename()) {
269 module2
->Data
->generate_TTCN3_included_types(file
);
270 module2
->Data
->generate_TTCN3_types(file
);
274 fprintf(file
, "}\n");
276 module
->Data
->generate_with_statement(file
, used_namespaces
);
278 if (!q_flag_used
) fprintf(stderr
, "Notify: File '%s' was generated.\n", filename_s
.c_str());
284 RootType
* TTCN3ModuleInventory::lookup(const RootType
* ref
, const Mstring
& reference
, wanted w
) const {
285 Mstring uri
= reference
.getPrefix(':');
286 const Mstring
& name
= reference
.getValueWithoutPrefix(':');
288 for(List
<NamespaceType
>::iterator qname
= ref
->getModule()->getDeclaredNamespaces().begin(); qname
; qname
= qname
->Next
){
289 if(qname
->Data
.prefix
.empty()){
290 uri
= qname
->Data
.uri
;
295 uri
= getNameSpaceByPrefix(ref
, uri
);
297 return lookup(name
, uri
, NULL
, w
);
300 RootType
* TTCN3ModuleInventory::lookup(const SimpleType
* reference
, wanted w
) const {
301 const Mstring
& uri
= reference
->getReference().get_uri();
302 const Mstring
& name
= reference
->getReference().get_val();
304 return lookup(name
, uri
, reference
, w
);
307 RootType
* TTCN3ModuleInventory::lookup(const ComplexType
* reference
, wanted w
) const {
308 const Mstring
& uri
= reference
->getReference().get_uri();
309 const Mstring
& name
= reference
->getReference().get_val();
311 return lookup(name
, uri
, reference
, w
);
314 RootType
* TTCN3ModuleInventory::lookup(const Mstring
& name
, const Mstring
& nsuri
,
315 const RootType
*reference
, wanted w
) const {
316 return ::lookup(definedModules
, name
, nsuri
, reference
, w
);
319 void TTCN3ModuleInventory::dump() const {
320 fprintf(stderr
, "Dumping %lu modules.\n", (unsigned long) definedModules
.size());
321 for (List
<TTCN3Module
*>::iterator module
= definedModules
.begin(); module
; module
= module
->Next
) {
322 module
->Data
->dump();
325 fprintf(stderr
, "Dumping %lu types\n", (unsigned long) typenames
.size());
327 Item
<QualifiedName
> *o
= typenames
.begin();
328 for (; o
!= NULL
; o
= o
->Next
) {
329 fprintf(stderr
, "{%s}%s,\n",
330 o
->Data
.nsuri
.c_str(), o
->Data
.name
.c_str());