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 "XMLParser.hh"
18 #include "TTCN3ModuleInventory.hh"
20 #include "GeneralFunctions.hh"
22 #include "TTCN3Module.hh"
23 #include "SimpleType.hh"
24 #include "ComplexType.hh"
26 extern bool h_flag_used
;
27 extern bool q_flag_used
;
31 unsigned int TTCN3ModuleInventory::num_errors
= 0;
32 unsigned int TTCN3ModuleInventory::num_warnings
= 0;
34 TTCN3ModuleInventory::TTCN3ModuleInventory()
40 TTCN3ModuleInventory::~TTCN3ModuleInventory() {
41 for (List
<TTCN3Module
*>::iterator module
= definedModules
.begin(); module
; module
= module
->Next
) {
46 TTCN3ModuleInventory
& TTCN3ModuleInventory::getInstance() {
47 // Singleton, see Meyers, More Effective C++, Item 26 (page 131)
48 static TTCN3ModuleInventory instance
;
52 TTCN3Module
* TTCN3ModuleInventory::addModule(const char * xsd_filename
, XMLParser
* a_parser
) {
53 TTCN3Module
* module
= new TTCN3Module(xsd_filename
, a_parser
);
54 definedModules
.push_back(module
);
55 return definedModules
.back();
58 void TTCN3ModuleInventory::modulenameConversion() {
59 definedModules
.sort(compareModules
);
61 for (List
<TTCN3Module
*>::iterator module
= definedModules
.begin(); module
; module
= module
->Next
) {
62 module
->Data
->TargetNamespace2ModuleName();
66 void TTCN3ModuleInventory::referenceResolving() {
68 * Reference resolving for include and import statements
70 for (List
<TTCN3Module
*>::iterator module
= definedModules
.begin(); module
; module
= module
->Next
) {
71 for (List
<RootType
*>::iterator type
= module
->Data
->getDefinedTypes().begin(); type
; type
= type
->Next
) {
72 if (type
->Data
->getName().convertedValue
== "import" || type
->Data
->getName().convertedValue
== "include") {
73 type
->Data
->referenceResolving();
79 * Reference resolving for all others
81 bool there_is_unresolved_reference_somewhere
= false;
83 there_is_unresolved_reference_somewhere
= false;
85 for (List
<TTCN3Module
*>::iterator module
= definedModules
.begin(); module
; module
= module
->Next
) {
86 for (List
<RootType
*>::iterator type
= module
->Data
->getDefinedTypes().begin(); type
; type
= type
->Next
) {
87 if (type
->Data
->getName().convertedValue
!= "import" && type
->Data
->getName().convertedValue
!= "include") {
88 type
->Data
->referenceResolving();
89 if (type
->Data
->hasUnresolvedReference()) {
90 there_is_unresolved_reference_somewhere
= true;
95 } while (there_is_unresolved_reference_somewhere
);
98 void TTCN3ModuleInventory::finalModification() {
99 for (List
<TTCN3Module
*>::iterator module
= definedModules
.begin(); module
; module
= module
->Next
) {
100 for (List
<RootType
*>::iterator type
= module
->Data
->getDefinedTypes().begin(); type
; type
= type
->Next
) {
101 type
->Data
->finalModification();
106 void TTCN3ModuleInventory::nameConversion() {
108 * Sort of types and fields
111 definedModules
.sort(compareModules
);
112 /********************************************************
113 * Conversion of the name of types
114 * ******************************************************/
115 for (List
<TTCN3Module
*>::iterator module
= definedModules
.begin(); module
; module
= module
->Next
) {
116 if (module
->Data
->isnotIntoNameConversion()) continue;
118 List
<RootType
*> definedElements_inABC
;
119 List
<RootType
*> definedAttributes_inABC
;
120 List
<RootType
*> definedSimpleTypes_inABC
;
121 List
<RootType
*> definedComplexTypes_inABC
;
122 List
<RootType
*> definedAttributeGroups_inABC
;
123 List
<RootType
*> definedGroups_inABC
;
125 for (List
<TTCN3Module
*>::iterator module2
= module
; module2
; module2
= module2
->Next
) {
126 if (module2
->Data
->getModulename() != module
->Data
->getModulename()) continue;
128 for (List
<RootType
*>::iterator type
= module2
->Data
->getDefinedTypes().begin(); type
; type
= type
->Next
) {
129 switch (type
->Data
->getConstruct()) {
131 definedSimpleTypes_inABC
.push_back(type
->Data
);
134 definedElements_inABC
.push_back(type
->Data
);
137 definedAttributes_inABC
.push_back(type
->Data
);
140 definedComplexTypes_inABC
.push_back(type
->Data
);
143 definedGroups_inABC
.push_back(type
->Data
);
145 case c_attributeGroup
:
146 definedAttributeGroups_inABC
.push_back(type
->Data
);
152 module2
->Data
->notIntoNameConversion();
155 definedElements_inABC
.sort(compareTypes
);
156 definedAttributes_inABC
.sort(compareTypes
);
157 definedSimpleTypes_inABC
.sort(compareTypes
);
158 definedComplexTypes_inABC
.sort(compareTypes
);
159 definedAttributeGroups_inABC
.sort(compareTypes
);
160 definedGroups_inABC
.sort(compareTypes
);
162 typenames
.push_back(QualifiedName(module
->Data
->getTargetNamespace(), module
->Data
->getModulename()));
163 for(List
<const TTCN3Module
*>::iterator mod
= module
->Data
->getImportedModules().begin(); mod
; mod
= mod
->Next
){
164 typenames
.push_back(QualifiedName(module
->Data
->getTargetNamespace(), mod
->Data
->getModulename()));
167 for (List
<RootType
*>::iterator type
= definedElements_inABC
.begin(); type
; type
= type
->Next
) {
168 type
->Data
->nameConversion(nameMode
, module
->Data
->getDeclaredNamespaces());
170 for (List
<RootType
*>::iterator type
= definedAttributes_inABC
.begin(); type
; type
= type
->Next
) {
171 type
->Data
->nameConversion(nameMode
, module
->Data
->getDeclaredNamespaces());
173 for (List
<RootType
*>::iterator type
= definedSimpleTypes_inABC
.begin(); type
; type
= type
->Next
) {
174 type
->Data
->nameConversion(nameMode
, module
->Data
->getDeclaredNamespaces());
176 for (List
<RootType
*>::iterator type
= definedComplexTypes_inABC
.begin(); type
; type
= type
->Next
) {
177 type
->Data
->nameConversion(nameMode
, module
->Data
->getDeclaredNamespaces());
179 for (List
<RootType
*>::iterator type
= definedAttributeGroups_inABC
.begin(); type
; type
= type
->Next
) {
180 type
->Data
->nameConversion(nameMode
, module
->Data
->getDeclaredNamespaces());
182 for (List
<RootType
*>::iterator type
= definedGroups_inABC
.begin(); type
; type
= type
->Next
) {
183 type
->Data
->nameConversion(nameMode
, module
->Data
->getDeclaredNamespaces());
187 /********************************************************
188 * Conversion of the type of types
189 * ******************************************************/
190 for (List
<TTCN3Module
*>::iterator module
= definedModules
.begin(); module
; module
= module
->Next
) {
191 for (List
<RootType
*>::iterator type
= module
->Data
->getDefinedTypes().begin(); type
; type
= type
->Next
) {
192 type
->Data
->nameConversion(typeMode
, module
->Data
->getDeclaredNamespaces());
195 /********************************************************
196 * Conversion of the names and the types of the fields
197 * ******************************************************/
198 for (List
<TTCN3Module
*>::iterator module
= definedModules
.begin(); module
; module
= module
->Next
) {
199 for (List
<RootType
*>::iterator type
= module
->Data
->getDefinedTypes().begin(); type
; type
= type
->Next
) {
200 type
->Data
->nameConversion(fieldMode
, module
->Data
->getDeclaredNamespaces());
205 void TTCN3ModuleInventory::moduleGeneration() {
206 for (List
<TTCN3Module
*>::iterator module
= definedModules
.begin(); module
; module
= module
->Next
) {
207 if (module
->Data
->isnotIntoFile()) {
211 List
<NamespaceType
> used_namespaces
;
212 NamespaceType targetns
;
213 targetns
.uri
= module
->Data
->getTargetNamespace();
214 used_namespaces
.push_back(targetns
);
216 // Now search for other modules with the same module name.
217 // They must have had the same targetNamespace.
218 for (List
<TTCN3Module
*>::iterator module2
= module
; module2
; module2
= module2
->Next
) {
219 if (module2
->Data
->getModulename() != module
->Data
->getModulename()) {
223 for (List
<NamespaceType
>::iterator declNS
= module2
->Data
->getDeclaredNamespaces().begin(); declNS
; declNS
= declNS
->Next
) {
224 used_namespaces
.push_back(declNS
->Data
);
226 module2
->Data
->notIntoFile(); // first module gets the TTCN-3 file
229 Mstring filename_s
= module
->Data
->getModulename() + ".ttcn";
230 FILE * file
= fopen(filename_s
.c_str(), "w");
232 Mstring
cannot_write("Cannot write file ");
233 perror((cannot_write
+ filename_s
).c_str());
238 // In debug mode, set the output stream to unbuffered.
239 // This allows watching the output as it appears (e.g. with tail -f).
240 setvbuf(file
, NULL
, _IONBF
, 0);
243 generate_TTCN3_header(file
, module
->Data
->getModulename().c_str());
245 fprintf(file
, "//\tGenerated from file(s):\n");
247 for (List
<TTCN3Module
*>::iterator module2
= module
; module2
; module2
= module2
->Next
) {
248 if (module2
->Data
->getModulename() == module
->Data
->getModulename()) {
249 module2
->Data
->generate_TTCN3_fileinfo(file
);
254 "////////////////////////////////////////////////////////////////////////////////\n"
255 "// Modification header(s):\n"
256 "//-----------------------------------------------------------------------------\n"
258 "// Modification date:\n"
260 "// Modification contact:\n"
261 "//------------------------------------------------------------------------------\n"
262 "////////////////////////////////////////////////////////////////////////////////\n"
266 module
->Data
->generate_TTCN3_modulestart(file
);
268 for (List
<TTCN3Module
*>::iterator module2
= module
; module2
; module2
= module2
->Next
) {
269 if (module2
->Data
->getModulename() == module
->Data
->getModulename()) {
270 module2
->Data
->generate_TTCN3_import_statements(file
);
274 writtenImports
.clear();
276 for (List
<TTCN3Module
*>::iterator module2
= module
; module2
; module2
= module2
->Next
) {
277 if (module2
->Data
->getModulename() == module
->Data
->getModulename()) {
278 module2
->Data
->generate_TTCN3_included_types(file
);
279 module2
->Data
->generate_TTCN3_types(file
);
283 fprintf(file
, "}\n");
285 module
->Data
->generate_with_statement(file
, used_namespaces
);
287 if (!q_flag_used
) fprintf(stderr
, "Notify: File '%s' was generated.\n", filename_s
.c_str());
293 RootType
* TTCN3ModuleInventory::lookup(const RootType
* ref
, const Mstring
& reference
, wanted w
) const {
294 Mstring uri
= reference
.getPrefix(':');
295 const Mstring
& name
= reference
.getValueWithoutPrefix(':');
297 for(List
<NamespaceType
>::iterator qname
= ref
->getModule()->getDeclaredNamespaces().begin(); qname
; qname
= qname
->Next
){
298 if(qname
->Data
.prefix
.empty()){
299 uri
= qname
->Data
.uri
;
304 //If the targetnamespace is NoTargetNamespace therefore no prefix connector used
305 uri
= ref
->getModule()->getTargetNamespace();
308 uri
= getNameSpaceByPrefix(ref
, uri
);
310 return lookup(name
, uri
, NULL
, w
);
313 RootType
* TTCN3ModuleInventory::lookup(const SimpleType
* reference
, wanted w
) const {
314 const Mstring
& uri
= reference
->getReference().get_uri();
315 const Mstring
& name
= reference
->getReference().get_val();
317 return lookup(name
, uri
, reference
, w
);
320 RootType
* TTCN3ModuleInventory::lookup(const ComplexType
* reference
, wanted w
) const {
321 const Mstring
& uri
= reference
->getReference().get_uri();
322 const Mstring
& name
= reference
->getReference().get_val();
324 return lookup(name
, uri
, reference
, w
);
327 RootType
* TTCN3ModuleInventory::lookup(const Mstring
& name
, const Mstring
& nsuri
,
328 const RootType
*reference
, wanted w
) const {
329 return ::lookup(definedModules
, name
, nsuri
, reference
, w
);
332 void TTCN3ModuleInventory::dump() const {
333 fprintf(stderr
, "Dumping %lu modules.\n", (unsigned long) definedModules
.size());
334 for (List
<TTCN3Module
*>::iterator module
= definedModules
.begin(); module
; module
= module
->Next
) {
335 module
->Data
->dump();
338 fprintf(stderr
, "Dumping %lu types\n", (unsigned long) typenames
.size());
340 Item
<QualifiedName
> *o
= typenames
.begin();
341 for (; o
!= NULL
; o
= o
->Next
) {
342 fprintf(stderr
, "{%s}%s,\n",
343 o
->Data
.nsuri
.c_str(), o
->Data
.name
.c_str());