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