Commit | Line | Data |
---|---|---|
970ed795 | 1 | /////////////////////////////////////////////////////////////////////////////// |
3abe9331 | 2 | // Copyright (c) 2000-2015 Ericsson Telecom AB |
970ed795 EL |
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" | |
10 | ||
11 | #include "GeneralFunctions.hh" | |
12 | ||
13 | #include "TTCN3Module.hh" | |
14 | #include "SimpleType.hh" | |
15 | #include "ComplexType.hh" | |
970ed795 EL |
16 | |
17 | extern bool h_flag_used; | |
18 | extern bool q_flag_used; | |
19 | ||
20 | ||
21 | ||
22 | unsigned int TTCN3ModuleInventory::num_errors = 0; | |
23 | unsigned int TTCN3ModuleInventory::num_warnings = 0; | |
24 | ||
970ed795 EL |
25 | TTCN3ModuleInventory::TTCN3ModuleInventory() |
26 | : definedModules() | |
27 | , writtenImports() | |
3abe9331 | 28 | , typenames() { |
29 | } | |
970ed795 | 30 | |
3abe9331 | 31 | TTCN3ModuleInventory::~TTCN3ModuleInventory() { |
970ed795 EL |
32 | for (List<TTCN3Module*>::iterator module = definedModules.begin(); module; module = module->Next) { |
33 | delete(module->Data); | |
34 | } | |
35 | } | |
36 | ||
3abe9331 | 37 | TTCN3ModuleInventory& TTCN3ModuleInventory::getInstance() { |
970ed795 EL |
38 | // Singleton, see Meyers, More Effective C++, Item 26 (page 131) |
39 | static TTCN3ModuleInventory instance; | |
40 | return instance; | |
41 | } | |
42 | ||
3abe9331 | 43 | TTCN3Module * TTCN3ModuleInventory::addModule(const char * xsd_filename, XMLParser * a_parser) { |
970ed795 EL |
44 | TTCN3Module * module = new TTCN3Module(xsd_filename, a_parser); |
45 | definedModules.push_back(module); | |
46 | return definedModules.back(); | |
47 | } | |
48 | ||
3abe9331 | 49 | void TTCN3ModuleInventory::modulenameConversion() { |
970ed795 EL |
50 | definedModules.sort(compareModules); |
51 | ||
3abe9331 | 52 | for (List<TTCN3Module*>::iterator module = definedModules.begin(); module; module = module->Next) { |
970ed795 EL |
53 | module->Data->TargetNamespace2ModuleName(); |
54 | } | |
55 | } | |
56 | ||
3abe9331 | 57 | void TTCN3ModuleInventory::referenceResolving() { |
970ed795 EL |
58 | /** |
59 | * Reference resolving for include and import statements | |
60 | */ | |
3abe9331 | 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") { | |
970ed795 EL |
64 | type->Data->referenceResolving(); |
65 | } | |
66 | } | |
67 | } | |
68 | ||
69 | /** | |
70 | * Reference resolving for all others | |
71 | */ | |
72 | bool there_is_unresolved_reference_somewhere = false; | |
3abe9331 | 73 | do { |
970ed795 EL |
74 | there_is_unresolved_reference_somewhere = false; |
75 | ||
3abe9331 | 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") { | |
970ed795 | 79 | type->Data->referenceResolving(); |
3abe9331 | 80 | if (type->Data->hasUnresolvedReference()) { |
970ed795 EL |
81 | there_is_unresolved_reference_somewhere = true; |
82 | } | |
83 | } | |
84 | } | |
85 | } | |
3abe9331 | 86 | } while (there_is_unresolved_reference_somewhere); |
970ed795 EL |
87 | } |
88 | ||
3abe9331 | 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) { | |
970ed795 EL |
92 | type->Data->finalModification(); |
93 | } | |
94 | } | |
95 | } | |
96 | ||
3abe9331 | 97 | void TTCN3ModuleInventory::nameConversion() { |
970ed795 EL |
98 | /** |
99 | * Sort of types and fields | |
100 | */ | |
970ed795 EL |
101 | |
102 | definedModules.sort(compareModules); | |
103 | /******************************************************** | |
104 | * Conversion of the name of types | |
105 | * ******************************************************/ | |
3abe9331 | 106 | for (List<TTCN3Module*>::iterator module = definedModules.begin(); module; module = module->Next) { |
970ed795 EL |
107 | if (module->Data->isnotIntoNameConversion()) continue; |
108 | ||
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; | |
115 | ||
3abe9331 | 116 | for (List<TTCN3Module*>::iterator module2 = module; module2; module2 = module2->Next) { |
970ed795 EL |
117 | if (module2->Data->getModulename() != module->Data->getModulename()) continue; |
118 | ||
3abe9331 | 119 | for (List<RootType*>::iterator type = module2->Data->getDefinedTypes().begin(); type; type = type->Next) { |
120 | switch (type->Data->getConstruct()) { | |
121 | case c_simpleType: | |
122 | definedSimpleTypes_inABC.push_back(type->Data); | |
123 | break; | |
124 | case c_element: | |
125 | definedElements_inABC.push_back(type->Data); | |
126 | break; | |
127 | case c_attribute: | |
128 | definedAttributes_inABC.push_back(type->Data); | |
129 | break; | |
130 | case c_complexType: | |
131 | definedComplexTypes_inABC.push_back(type->Data); | |
132 | break; | |
133 | case c_group: | |
134 | definedGroups_inABC.push_back(type->Data); | |
135 | break; | |
136 | case c_attributeGroup: | |
137 | definedAttributeGroups_inABC.push_back(type->Data); | |
138 | break; | |
139 | default: | |
140 | break; | |
970ed795 EL |
141 | } |
142 | } | |
143 | module2->Data->notIntoNameConversion(); | |
144 | } | |
145 | ||
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); | |
152 | ||
3abe9331 | 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())); | |
156 | } | |
157 | ||
158 | for (List<RootType*>::iterator type = definedElements_inABC.begin(); type; type = type->Next) { | |
970ed795 EL |
159 | type->Data->nameConversion(nameMode, module->Data->getDeclaredNamespaces()); |
160 | } | |
3abe9331 | 161 | for (List<RootType*>::iterator type = definedAttributes_inABC.begin(); type; type = type->Next) { |
970ed795 EL |
162 | type->Data->nameConversion(nameMode, module->Data->getDeclaredNamespaces()); |
163 | } | |
3abe9331 | 164 | for (List<RootType*>::iterator type = definedSimpleTypes_inABC.begin(); type; type = type->Next) { |
970ed795 EL |
165 | type->Data->nameConversion(nameMode, module->Data->getDeclaredNamespaces()); |
166 | } | |
3abe9331 | 167 | for (List<RootType*>::iterator type = definedComplexTypes_inABC.begin(); type; type = type->Next) { |
970ed795 EL |
168 | type->Data->nameConversion(nameMode, module->Data->getDeclaredNamespaces()); |
169 | } | |
3abe9331 | 170 | for (List<RootType*>::iterator type = definedAttributeGroups_inABC.begin(); type; type = type->Next) { |
970ed795 EL |
171 | type->Data->nameConversion(nameMode, module->Data->getDeclaredNamespaces()); |
172 | } | |
3abe9331 | 173 | for (List<RootType*>::iterator type = definedGroups_inABC.begin(); type; type = type->Next) { |
970ed795 EL |
174 | type->Data->nameConversion(nameMode, module->Data->getDeclaredNamespaces()); |
175 | } | |
3abe9331 | 176 | typenames.clear(); |
970ed795 EL |
177 | } |
178 | /******************************************************** | |
179 | * Conversion of the type of types | |
180 | * ******************************************************/ | |
3abe9331 | 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) { | |
970ed795 EL |
183 | type->Data->nameConversion(typeMode, module->Data->getDeclaredNamespaces()); |
184 | } | |
185 | } | |
186 | /******************************************************** | |
187 | * Conversion of the names and the types of the fields | |
188 | * ******************************************************/ | |
3abe9331 | 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) { | |
970ed795 EL |
191 | type->Data->nameConversion(fieldMode, module->Data->getDeclaredNamespaces()); |
192 | } | |
193 | } | |
194 | } | |
195 | ||
3abe9331 | 196 | void TTCN3ModuleInventory::moduleGeneration() { |
197 | for (List<TTCN3Module*>::iterator module = definedModules.begin(); module; module = module->Next) { | |
198 | if (module->Data->isnotIntoFile()) { | |
199 | continue; | |
200 | } | |
970ed795 EL |
201 | |
202 | List<NamespaceType> used_namespaces; | |
203 | NamespaceType targetns; | |
204 | targetns.uri = module->Data->getTargetNamespace(); | |
205 | used_namespaces.push_back(targetns); | |
206 | ||
207 | // Now search for other modules with the same module name. | |
208 | // They must have had the same targetNamespace. | |
3abe9331 | 209 | for (List<TTCN3Module*>::iterator module2 = module; module2; module2 = module2->Next) { |
210 | if (module2->Data->getModulename() != module->Data->getModulename()) { | |
211 | continue; | |
212 | } | |
970ed795 | 213 | |
3abe9331 | 214 | for (List<NamespaceType>::iterator declNS = module2->Data->getDeclaredNamespaces().begin(); declNS; declNS = declNS->Next) { |
970ed795 EL |
215 | used_namespaces.push_back(declNS->Data); |
216 | } | |
217 | module2->Data->notIntoFile(); // first module gets the TTCN-3 file | |
218 | } | |
219 | ||
220 | Mstring filename_s = module->Data->getModulename() + ".ttcn"; | |
221 | FILE * file = fopen(filename_s.c_str(), "w"); | |
222 | if (file == NULL) { | |
223 | Mstring cannot_write("Cannot write file "); | |
224 | perror((cannot_write + filename_s).c_str()); | |
225 | ++num_errors; | |
226 | return; | |
227 | } | |
228 | #ifndef NDEBUG | |
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); | |
232 | #endif | |
233 | ||
234 | module->Data->generate_TTCN3_header(file); | |
235 | ||
236 | fprintf(file, "//\tGenerated from file(s):\n"); | |
237 | ||
3abe9331 | 238 | for (List<TTCN3Module*>::iterator module2 = module; module2; module2 = module2->Next) { |
239 | if (module2->Data->getModulename() == module->Data->getModulename()) { | |
970ed795 EL |
240 | module2->Data->generate_TTCN3_fileinfo(file); |
241 | } | |
242 | } | |
243 | ||
244 | fprintf(file, | |
245 | "////////////////////////////////////////////////////////////////////////////////\n" | |
246 | "// Modification header(s):\n" | |
247 | "//-----------------------------------------------------------------------------\n" | |
248 | "// Modified by:\n" | |
249 | "// Modification date:\n" | |
250 | "// Description:\n" | |
251 | "// Modification contact:\n" | |
252 | "//------------------------------------------------------------------------------\n" | |
253 | "////////////////////////////////////////////////////////////////////////////////\n" | |
254 | "\n" | |
255 | "\n"); | |
256 | ||
257 | module->Data->generate_TTCN3_modulestart(file); | |
258 | ||
3abe9331 | 259 | for (List<TTCN3Module*>::iterator module2 = module; module2; module2 = module2->Next) { |
260 | if (module2->Data->getModulename() == module->Data->getModulename()) { | |
970ed795 EL |
261 | module2->Data->generate_TTCN3_import_statements(file); |
262 | } | |
263 | } | |
264 | ||
265 | writtenImports.clear(); | |
266 | ||
3abe9331 | 267 | for (List<TTCN3Module*>::iterator module2 = module; module2; module2 = module2->Next) { |
268 | if (module2->Data->getModulename() == module->Data->getModulename()) { | |
970ed795 EL |
269 | module2->Data->generate_TTCN3_included_types(file); |
270 | module2->Data->generate_TTCN3_types(file); | |
271 | } | |
272 | } | |
273 | ||
274 | fprintf(file, "}\n"); | |
275 | ||
276 | module->Data->generate_with_statement(file, used_namespaces); | |
277 | ||
278 | if (!q_flag_used) fprintf(stderr, "Notify: File '%s' was generated.\n", filename_s.c_str()); | |
279 | ||
280 | fclose(file); | |
281 | } | |
282 | } | |
283 | ||
3abe9331 | 284 | RootType * TTCN3ModuleInventory::lookup(const RootType* ref, const Mstring& reference, wanted w) const { |
285 | Mstring uri = reference.getPrefix(':'); | |
286 | const Mstring& name = reference.getValueWithoutPrefix(':'); | |
287 | if(uri.empty()){ | |
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; | |
291 | break; | |
292 | } | |
293 | } | |
51fa56b9 | 294 | if(uri.empty()){ |
295 | //If the targetnamespace is NoTargetNamespace therefore no prefix connector used | |
296 | uri = ref->getModule()->getTargetNamespace(); | |
297 | } | |
3abe9331 | 298 | }else { |
299 | uri = getNameSpaceByPrefix(ref, uri); | |
300 | } | |
301 | return lookup(name, uri, NULL, w); | |
302 | } | |
303 | ||
304 | RootType * TTCN3ModuleInventory::lookup(const SimpleType * reference, wanted w) const { | |
305 | const Mstring& uri = reference->getReference().get_uri(); | |
306 | const Mstring& name = reference->getReference().get_val(); | |
307 | ||
308 | return lookup(name, uri, reference, w); | |
309 | } | |
310 | ||
311 | RootType * TTCN3ModuleInventory::lookup(const ComplexType * reference, wanted w) const { | |
970ed795 EL |
312 | const Mstring& uri = reference->getReference().get_uri(); |
313 | const Mstring& name = reference->getReference().get_val(); | |
314 | ||
315 | return lookup(name, uri, reference, w); | |
316 | } | |
317 | ||
318 | RootType * TTCN3ModuleInventory::lookup(const Mstring& name, const Mstring& nsuri, | |
3abe9331 | 319 | const RootType *reference, wanted w) const { |
970ed795 EL |
320 | return ::lookup(definedModules, name, nsuri, reference, w); |
321 | } | |
322 | ||
3abe9331 | 323 | void TTCN3ModuleInventory::dump() const { |
324 | fprintf(stderr, "Dumping %lu modules.\n", (unsigned long) definedModules.size()); | |
325 | for (List<TTCN3Module*>::iterator module = definedModules.begin(); module; module = module->Next) { | |
970ed795 EL |
326 | module->Data->dump(); |
327 | } | |
328 | ||
3abe9331 | 329 | fprintf(stderr, "Dumping %lu types\n", (unsigned long) typenames.size()); |
970ed795 EL |
330 | |
331 | Item<QualifiedName> *o = typenames.begin(); | |
3abe9331 | 332 | for (; o != NULL; o = o->Next) { |
970ed795 EL |
333 | fprintf(stderr, "{%s}%s,\n", |
334 | o->Data.nsuri.c_str(), o->Data.name.c_str()); | |
335 | } | |
336 | } |