Sync with 5.4.2
[deliverable/titan.core.git] / xsdconvert / TTCN3Module.cc
CommitLineData
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 "TTCN3Module.hh"
9
10#include "RootType.hh"
11#include "SimpleType.hh"
12#include "ComplexType.hh"
13#include "ImportStatement.hh"
14#include "Annotation.hh"
15
16#include "../common/version_internal.h"
17
18#include <ctime>
19
20#if defined(WIN32) && !defined(MINGW)
21#include <cygwin/version.h>
22#include <sys/cygwin.h>
23#include <limits.h>
24#endif
25
26extern bool e_flag_used;
27extern bool t_flag_used;
28extern bool z_flag_used;
29
30TTCN3Module::TTCN3Module(const char * a_filename, XMLParser * a_parser)
31: parser(a_parser)
32, schemaname()
33, modulename()
34, definedTypes()
35, actualXsdConstruct(c_unknown)
36, xsdVersion()
37, xsdEncoding()
38, xsdStandalone()
39, targetNamespace()
40, targetNamespace_connectedPrefix()
41, declaredNamespaces()
42, elementFormDefault(notset)
43, attributeFormDefault(notset)
3abe9331 44, blockDefault(not_set)
51fa56b9 45, storedTypeSubstitutions()
46, element_types()
970ed795
EL
47//, importedModules()
48, variant()
49, moduleNotIntoFile(false)
3abe9331 50, moduleNotIntoNameConversion(false) {
970ed795
EL
51#if defined(WIN32) && !defined(MINGW)
52 // Transform a Windows style path: "C:\cygwin\tmp\a.xsd"
53 // into a POSIX style path: "/home/a/xsd", so getValueWithoutPrefix('/')
54 // can chop off the directory path.
55#if CYGWIN_VERSION_DLL_MAJOR >= 1007
56 char *posix = NULL;
3abe9331 57 ssize_t needed = cygwin_conv_path(CCP_WIN_A_TO_POSIX | CCP_RELATIVE, a_filename, NULL, 0);
970ed795 58 if (needed >= 0) {
3abe9331 59 posix = (char*) Malloc(needed);
60 if (cygwin_conv_path(CCP_WIN_A_TO_POSIX | CCP_RELATIVE, a_filename, posix, needed)) {
970ed795
EL
61 posix = NULL; // conversion failed
62 }
63 }
64 Mstring filename(posix ? posix : a_filename);
65 Free(posix); // even if NULL
66#else // Cygwin 1.5
67 char posix[PATH_MAX];
68 int fail = cygwin_conv_to_posix_path(a_filename, posix);
69 Mstring filename(fail ? a_filename : posix);
70#endif
71
72#else
73 Mstring filename(a_filename);
74#endif
75 schemaname = filename.getValueWithoutPrefix('/'); // excludes the path of the input file
76}
77
3abe9331 78TTCN3Module::~TTCN3Module() {
970ed795 79 for (List<RootType*>::iterator type = definedTypes.begin(); type; type = type->Next) {
3abe9331 80 delete type->Data;
970ed795
EL
81 }
82}
83
84void TTCN3Module::loadValuesFromXMLDeclaration(const char *a_version,
3abe9331 85 const char *a_encoding, int a_standalone) {
970ed795
EL
86 xsdVersion = a_version;
87 xsdEncoding = a_encoding;
88 xsdStandalone = a_standalone;
89}
90
91void TTCN3Module::loadValuesFromSchemaTag(const Mstring& a_targetNamespace,
92 List<NamespaceType> a_declaredNamespaces,
3abe9331 93 FormValue a_elementFormDefault, FormValue a_attributeFormDefault,
94 BlockValue a_blockDefault) {
970ed795
EL
95 if (a_targetNamespace.empty()) {
96 targetNamespace = "NoTargetNamespace";
3abe9331 97 } else {
970ed795
EL
98 if (a_targetNamespace == "http://www.w3.org/2001/XMLSchema") {
99 notIntoFile();
100 }
101 targetNamespace = a_targetNamespace;
102 }
103
104 elementFormDefault = a_elementFormDefault;
105 attributeFormDefault = a_attributeFormDefault;
3abe9331 106 blockDefault = a_blockDefault;
970ed795
EL
107
108 declaredNamespaces = a_declaredNamespaces;
109
3abe9331 110 for (List<NamespaceType>::iterator ns = declaredNamespaces.begin(); ns; ns = ns->Next) {
970ed795
EL
111 if (ns->Data.uri == targetNamespace) {
112 targetNamespace_connectedPrefix = ns->Data.prefix;
113 break;
114 }
115 }
116}
117
3abe9331 118void TTCN3Module::addMainType(const ConstructType typeOfMainType) {
119 switch (typeOfMainType) {
120 case c_simpleType:
121 {
122 SimpleType * new_ST = new SimpleType(parser, this, c_simpleType);
123 definedTypes.push_back(new_ST);
124 new_ST->loadWithValues();
125 break;
126 }
127 case c_element:
128 {
129 SimpleType * new_ST = new SimpleType(parser, this, c_element);
130 definedTypes.push_back(new_ST);
131 new_ST->loadWithValues();
132 break;
133 }
134 case c_attribute:
135 {
136 SimpleType * new_ST = new SimpleType(parser, this, c_attribute);
137 definedTypes.push_back(new_ST);
138 new_ST->loadWithValues();
139 break;
140 }
141 case c_complexType:
142 {
143 ComplexType * new_CT = new ComplexType(parser, this, c_complexType);
144 definedTypes.push_back(new_CT);
145 new_CT->loadWithValues();
146 break;
147 }
148 case c_group:
149 {
150 ComplexType * new_CT = new ComplexType(parser, this, c_group);
151 definedTypes.push_back(new_CT);
152 new_CT->loadWithValues();
153 break;
154 }
155 case c_attributeGroup:
156 {
157 ComplexType * new_CT = new ComplexType(parser, this, c_attributeGroup);
158 definedTypes.push_back(new_CT);
159 new_CT->loadWithValues();
160 break;
161 }
162 case c_include:
163 {
164 ImportStatement * new_INCL = new ImportStatement(parser, this, c_include);
165 definedTypes.push_back(new_INCL);
166 new_INCL->loadWithValues();
167 break;
168 }
169 case c_import:
170 {
171 ImportStatement * new_IMP = new ImportStatement(parser, this, c_import);
172 definedTypes.push_back(new_IMP);
173 new_IMP->loadWithValues();
174 break;
175 }
176 case c_annotation:
177 {
178 Annotation * new_ANN = new Annotation(parser, this, c_annotation);
179 definedTypes.push_back(new_ANN);
180 new_ANN->loadWithValues();
181 break;
182 }
183 case c_idattrib:
184 {
185 Mstring type = empty_string;
186 if (hasDefinedMainType()) {
187 type = getLastMainType().getName().convertedValue;
188 }
189 printWarning(getSchemaname(), type,
190 Mstring("The mapping of ID attribute is not supported."));
191 TTCN3ModuleInventory::getInstance().incrNumWarnings();
192 break;
193 }
194 case c_unknown:
195 case c_schema:
196 break;
970ed795
EL
197 }
198
199 actualXsdConstruct = typeOfMainType;
200}
201
3abe9331 202void TTCN3Module::replaceLastMainType(RootType * t) {
970ed795
EL
203 delete(definedTypes.back());
204 definedTypes.pop_back();
205 definedTypes.push_back(t);
206 actualXsdConstruct = t->getConstruct();
207}
208
3abe9331 209void TTCN3Module::generate_TTCN3_header(FILE * file) {
970ed795
EL
210 time_t time_current = time(NULL);
211 fprintf(file,
212 "/*******************************************************************************\n"
3abe9331 213 );
970ed795
EL
214 if (t_flag_used) {
215 fprintf(file,
216 "* Copyright Ericsson Telecom AB\n"
217 "*\n"
218 "* XSD to TTCN-3 Translator\n"
219 "*\n"
3abe9331 220 );
221 } else {
970ed795 222 fprintf(file,
3abe9331 223 "* Copyright (c) 2000-%-4d Ericsson Telecom AB\n"
970ed795
EL
224 "*\n"
225 "* XSD to TTCN-3 Translator version: %-40s\n"
226 "*\n",
227 1900 + (localtime(&time_current))->tm_year,
228 PRODUCT_NUMBER
3abe9331 229 );
970ed795
EL
230 }
231 fprintf(file,
232 "* All rights reserved. This program and the accompanying materials\n"
233 "* are made available under the terms of the Eclipse Public License v1.0\n"
234 "* which accompanies this distribution, and is available at\n"
235 "* http://www.eclipse.org/legal/epl-v10.html\n"
236 "*******************************************************************************/\n"
237 "//\n"
238 "// File: %s.ttcn\n"
239 "// Description:\n"
240 "// References:\n"
241 "// Rev:\n"
242 "// Prodnr:\n",
243 modulename.c_str()
3abe9331 244 );
970ed795
EL
245 if (t_flag_used) {
246 fprintf(file,
247 "// Updated:\n"
3abe9331 248 );
249 } else {
970ed795
EL
250 fprintf(file,
251 "// Updated: %s",
252 ctime(&time_current)
3abe9331 253 );
970ed795
EL
254 }
255 fprintf(file,
256 "// Contact: http://ttcn.ericsson.se\n"
257 "//\n"
258 "////////////////////////////////////////////////////////////////////////////////\n"
3abe9331 259 );
970ed795
EL
260}
261
3abe9331 262void TTCN3Module::generate_TTCN3_fileinfo(FILE * file) {
970ed795
EL
263 fprintf(file,
264 "//\t- %s\n"
265 "//\t\t\t/* xml ",
266 schemaname.c_str()
3abe9331 267 );
970ed795
EL
268
269 if (!xsdVersion.empty()) {
270 fprintf(file, "version = \"%s\" ", xsdVersion.c_str());
271 }
272 if (!xsdEncoding.empty()) {
273 fprintf(file, "encoding = \"%s\" ", xsdEncoding.c_str());
274 }
275
3abe9331 276 switch (xsdStandalone) {
277 case 0:
278 fprintf(file, "standalone = \"no\" ");
279 break;
280 case 1:
281 fprintf(file, "standalone = \"yes\" ");
282 break;
283 default:
284 break;
970ed795
EL
285 }
286
287 fprintf(file,
288 "*/\n"
289 "//\t\t\t/* targetnamespace = \"%s\" */\n",
290 targetNamespace.c_str()
3abe9331 291 );
970ed795
EL
292}
293
3abe9331 294void TTCN3Module::generate_TTCN3_modulestart(FILE * file) {
970ed795
EL
295 fprintf(file,
296 "module %s {\n"
297 "\n"
298 "\n"
299 "import from XSD all;\n"
300 "\n"
301 "\n",
302 modulename.c_str()
3abe9331 303 );
970ed795
EL
304}
305
3abe9331 306void TTCN3Module::generate_TTCN3_import_statements(FILE * file) {
307 for (List<RootType*>::iterator type = definedTypes.begin(); type; type = type->Next) {
308 if (type->Data->getConstruct() == c_import) {
970ed795
EL
309 type->Data->printToFile(file);
310 }
311 }
312}
313
3abe9331 314void TTCN3Module::generate_TTCN3_included_types(FILE * file) {
315 for (List<RootType*>::iterator type = definedTypes.begin(); type; type = type->Next) {
316 if (type->Data->getConstruct() == c_include) {
970ed795
EL
317 type->Data->printToFile(file);
318 }
319 }
320}
321
3abe9331 322void TTCN3Module::generate_TTCN3_types(FILE * file) {
323 for (List<RootType*>::iterator type = definedTypes.begin(); type; type = type->Next) {
324 if (type->Data->getConstruct() != c_include && type->Data->getConstruct() != c_import) {
970ed795
EL
325 type->Data->printToFile(file);
326 }
327 }
328}
329
3abe9331 330void TTCN3Module::generate_with_statement(FILE * file, List<NamespaceType> used_namespaces) {
331 if (e_flag_used) {
332 return;
333 }
970ed795
EL
334
335 fprintf(file,
336 "with {\n"
3f84031e 337 " encode \"XML\";\n"
3abe9331 338 );
970ed795
EL
339
340 bool xsi = false;
341
3abe9331 342 for (List<NamespaceType>::iterator usedNS = used_namespaces.begin(); usedNS; usedNS = usedNS->Next) {
970ed795
EL
343 if (usedNS->Data.uri == "http://www.w3.org/2001/XMLSchema") {
344 xsi = true;
345 continue;
346 }
347 if (usedNS->Data.uri == "NoTargetNamespace") {
348 continue;
349 }
3abe9331 350 // XXX this inner loop is either redundant now, or it should be elsewhere.
351 // It is quite dodgy to modify(!) namespaces when we are already generating code.
352 for (List<NamespaceType>::iterator usedNS2 = usedNS->Next; usedNS2; usedNS2 = usedNS2->Next) {
970ed795
EL
353 if (usedNS->Data.uri == usedNS2->Data.uri) {
354 if (usedNS2->Data.prefix.empty())
355 usedNS2->Data.prefix = usedNS->Data.prefix;
356 break;
357 }
358 }
359 }
360
361 if (targetNamespace != "NoTargetNamespace") {
3f84031e 362 fprintf(file, " variant \"namespace as \'%s\'", targetNamespace.c_str());
3abe9331 363 if (!targetNamespace_connectedPrefix.empty()) {
970ed795 364 fprintf(file, " prefix \'%s\'", targetNamespace_connectedPrefix.c_str());
3abe9331 365 }
970ed795
EL
366 fprintf(file, "\";\n");
367 }
368
369
370 if (xsi) {
371 fprintf(file,
3f84031e 372 " variant \"controlNamespace \'http://www.w3.org/2001/XMLSchema-instance\' prefix \'xsi\'\";\n");
970ed795
EL
373 }
374 if (attributeFormDefault == qualified) {
375 fprintf(file,
3f84031e 376 " variant \"attributeFormQualified\";\n");
970ed795
EL
377 }
378 if (elementFormDefault == qualified) {
379 fprintf(file,
3f84031e 380 " variant \"elementFormQualified\";\n");
970ed795
EL
381 }
382 fprintf(file,
383 "}\n");
384}
385
3abe9331 386void TTCN3Module::TargetNamespace2ModuleName() {
970ed795
EL
387 Mstring res(targetNamespace);
388
389 if (z_flag_used) {
3abe9331 390 char * found;
391 found = res.foundAt("http://");
392 //check if the http:// is at the beginning of the namespace
393 if (found == res.c_str()) { //res.c_str() returns a pointer to the first char
394 for (int i = 0; i != 7; ++i) {
970ed795 395 res.eraseChar(0);
3abe9331 396 }
397 }
398 found = res.foundAt("urn:");
399 //check if the urn: is at the beginning of the namespace
400 if (found == res.c_str()) { //res.c_str() returns a pointer to the first char
401 for (int i = 0; i != 4; ++i) {
970ed795 402 res.eraseChar(0);
3abe9331 403 }
404 }
970ed795
EL
405 }
406
407 // the characters ' '(SPACE), '.'(FULL STOP) and '-'(HYPEN-MINUS)
408 // and '/', '#', ':' shall all be replaced by a "_" (LOW LINE)
409 for (size_t i = 0; i != res.size(); ++i) {
410 if ((res[i] == ' ') ||
411 (res[i] == '.') ||
412 (res[i] == '-') ||
413 (res[i] == '/') ||
414 (res[i] == '#') ||
3abe9331 415 (res[i] == ':')) {
970ed795
EL
416 res[i] = '_';
417 }
418 }
419 // any character except "A" to "Z", "a" to "z" or "0" to "9" and "_" shall be removed
420 for (size_t i = 0; i != res.size(); ++i) {
3abe9331 421 if (!isalpha((const unsigned char) res[i]) && !isdigit((const unsigned char) res[i]) && (res[i] != '_')) {
970ed795 422 res.eraseChar(i);
3abe9331 423 i--;
970ed795
EL
424 }
425 }
426 // a sequence of two of more "_" (LOW LINE) shall be replaced with a single "_" (LOW LINE)
427 for (size_t i = 1; i < res.size(); ++i) {
3abe9331 428 if (res[i] == '_' && res[i - 1] == '_') {
429 res.eraseChar(i);
430 i--;
431 }
432 }
433
434 if (!res.empty()) {
435 // "_" (LOW LINE) characters occurring at the beginning of the name shall be removed
436 if (res[0] == '_') {
437 res.eraseChar(0);
438 }
439 }
440 if (!res.empty()) {
441 // "_" (LOW LINE) characters occurring at the end of the name shall be removed
442 if (res[res.size() - 1] == '_') {
443 res.eraseChar(res.size() - 1);
970ed795
EL
444 }
445 }
970ed795
EL
446
447 if (res.empty()) {
448 res = "x";
3abe9331 449 } else if (isdigit((const unsigned char) res[0])) {
970ed795
EL
450 res.insertChar(0, 'x');
451 }
452
3abe9331 453 //Postfix with _i if the targetnamespace is different
454 bool postfixing = false;
455 for (List<TTCN3Module*>::iterator mod = TTCN3ModuleInventory::getInstance().getModules().begin(); mod; mod = mod->Next) {
456 if (mod->Data != this && mod->Data->getModulename() == res && mod->Data->getTargetNamespace() != targetNamespace) {
457 postfixing = true;
458 break;
459 }
460 }
461
462 if(postfixing){
463 bool found;
464 int counter = 1;
465 expstring_t tmpname = NULL;
466 do {
467 found = false;
468 Free(tmpname);
469 tmpname = mprintf("%s_%d", res.c_str(), counter);
470 for(List<TTCN3Module*>::iterator mod = TTCN3ModuleInventory::getInstance().getModules().begin(); mod; mod = mod->Next){
471 if(mod->Data != this && mod->Data->getModulename() == Mstring(tmpname)){
472 found = true;
473 break;
474 }
475 }
476 counter++;
477 } while (found);
478 res = Mstring(tmpname);
479 Free(tmpname);
480 }
481
970ed795
EL
482 modulename = res;
483}
484
3abe9331 485void TTCN3Module::dump() const {
970ed795 486 fprintf(stderr, "Module '%s' at %p (from %s)\n",
3abe9331 487 modulename.c_str(), (const void*) this, schemaname.c_str());
970ed795 488
3abe9331 489 for (List<RootType*>::iterator type = definedTypes.begin(); type; type = type->Next) {
970ed795
EL
490 type->Data->dump(1);
491 }
492}
This page took 0.048395 seconds and 5 git commands to generate.