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