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
17 ******************************************************************************/
18 #include "TTCN3Module.hh"
20 #include "RootType.hh"
21 #include "SimpleType.hh"
22 #include "ComplexType.hh"
23 #include "ImportStatement.hh"
24 #include "Annotation.hh"
26 #include "../common/version_internal.h"
28 #if defined(WIN32) && !defined(MINGW)
29 #include <cygwin/version.h>
30 #include <sys/cygwin.h>
34 extern bool e_flag_used
;
35 extern bool z_flag_used
;
37 TTCN3Module::TTCN3Module(const char * a_filename
, XMLParser
* a_parser
)
42 , actualXsdConstruct(c_unknown
)
47 , targetNamespace_connectedPrefix()
48 , declaredNamespaces()
49 , elementFormDefault(notset
)
50 , attributeFormDefault(notset
)
51 , blockDefault(not_set
)
52 , storedTypeSubstitutions()
56 , moduleNotIntoFile(false)
57 , moduleNotIntoNameConversion(false) {
58 #if defined(WIN32) && !defined(MINGW)
59 // Transform a Windows style path: "C:\cygwin\tmp\a.xsd"
60 // into a POSIX style path: "/home/a/xsd", so getValueWithoutPrefix('/')
61 // can chop off the directory path.
62 #if CYGWIN_VERSION_DLL_MAJOR >= 1007
64 ssize_t needed
= cygwin_conv_path(CCP_WIN_A_TO_POSIX
| CCP_RELATIVE
, a_filename
, NULL
, 0);
66 posix
= (char*) Malloc(needed
);
67 if (cygwin_conv_path(CCP_WIN_A_TO_POSIX
| CCP_RELATIVE
, a_filename
, posix
, needed
)) {
68 posix
= NULL
; // conversion failed
71 Mstring
filename(posix
? posix
: a_filename
);
72 Free(posix
); // even if NULL
75 int fail
= cygwin_conv_to_posix_path(a_filename
, posix
);
76 Mstring
filename(fail
? a_filename
: posix
);
80 Mstring
filename(a_filename
);
82 schemaname
= filename
.getValueWithoutPrefix('/'); // excludes the path of the input file
85 TTCN3Module::~TTCN3Module() {
86 for (List
<RootType
*>::iterator type
= definedTypes
.begin(); type
; type
= type
->Next
) {
91 void TTCN3Module::loadValuesFromXMLDeclaration(const char *a_version
,
92 const char *a_encoding
, int a_standalone
) {
93 xsdVersion
= a_version
;
94 xsdEncoding
= a_encoding
;
95 xsdStandalone
= a_standalone
;
98 void TTCN3Module::loadValuesFromSchemaTag(const Mstring
& a_targetNamespace
,
99 List
<NamespaceType
> a_declaredNamespaces
,
100 FormValue a_elementFormDefault
, FormValue a_attributeFormDefault
,
101 BlockValue a_blockDefault
) {
102 if (a_targetNamespace
.empty()) {
103 targetNamespace
= "NoTargetNamespace";
105 if (a_targetNamespace
== "http://www.w3.org/2001/XMLSchema") {
108 targetNamespace
= a_targetNamespace
;
111 elementFormDefault
= a_elementFormDefault
;
112 attributeFormDefault
= a_attributeFormDefault
;
113 blockDefault
= a_blockDefault
;
115 declaredNamespaces
= a_declaredNamespaces
;
117 for (List
<NamespaceType
>::iterator ns
= declaredNamespaces
.begin(); ns
; ns
= ns
->Next
) {
118 if (ns
->Data
.uri
== targetNamespace
) {
119 targetNamespace_connectedPrefix
= ns
->Data
.prefix
;
125 void TTCN3Module::addMainType(const ConstructType typeOfMainType
) {
126 switch (typeOfMainType
) {
129 SimpleType
* new_ST
= new SimpleType(parser
, this, c_simpleType
);
130 definedTypes
.push_back(new_ST
);
131 new_ST
->loadWithValues();
136 SimpleType
* new_ST
= new SimpleType(parser
, this, c_element
);
137 definedTypes
.push_back(new_ST
);
138 new_ST
->loadWithValues();
143 SimpleType
* new_ST
= new SimpleType(parser
, this, c_attribute
);
144 definedTypes
.push_back(new_ST
);
145 new_ST
->loadWithValues();
150 ComplexType
* new_CT
= new ComplexType(parser
, this, c_complexType
);
151 definedTypes
.push_back(new_CT
);
152 new_CT
->loadWithValues();
157 ComplexType
* new_CT
= new ComplexType(parser
, this, c_group
);
158 definedTypes
.push_back(new_CT
);
159 new_CT
->loadWithValues();
162 case c_attributeGroup
:
164 ComplexType
* new_CT
= new ComplexType(parser
, this, c_attributeGroup
);
165 definedTypes
.push_back(new_CT
);
166 new_CT
->loadWithValues();
171 ImportStatement
* new_INCL
= new ImportStatement(parser
, this, c_include
);
172 definedTypes
.push_back(new_INCL
);
173 new_INCL
->loadWithValues();
178 ImportStatement
* new_IMP
= new ImportStatement(parser
, this, c_import
);
179 definedTypes
.push_back(new_IMP
);
180 new_IMP
->loadWithValues();
185 Annotation
* new_ANN
= new Annotation(parser
, this, c_annotation
);
186 definedTypes
.push_back(new_ANN
);
187 new_ANN
->loadWithValues();
192 Mstring type
= empty_string
;
193 if (hasDefinedMainType()) {
194 type
= getLastMainType().getName().convertedValue
;
196 printWarning(getSchemaname(), type
,
197 Mstring("The mapping of ID attribute is not supported."));
198 TTCN3ModuleInventory::getInstance().incrNumWarnings();
206 actualXsdConstruct
= typeOfMainType
;
209 void TTCN3Module::replaceLastMainType(RootType
* t
) {
210 delete(definedTypes
.back());
211 definedTypes
.pop_back();
212 definedTypes
.push_back(t
);
213 actualXsdConstruct
= t
->getConstruct();
216 void TTCN3Module::generate_TTCN3_fileinfo(FILE * file
) {
223 if (!xsdVersion
.empty()) {
224 fprintf(file
, "version = \"%s\" ", xsdVersion
.c_str());
226 if (!xsdEncoding
.empty()) {
227 fprintf(file
, "encoding = \"%s\" ", xsdEncoding
.c_str());
230 switch (xsdStandalone
) {
232 fprintf(file
, "standalone = \"no\" ");
235 fprintf(file
, "standalone = \"yes\" ");
243 "//\t\t\t/* targetnamespace = \"%s\" */\n",
244 targetNamespace
.c_str()
248 void TTCN3Module::generate_TTCN3_modulestart(FILE * file
) {
253 "import from XSD all;\n"
260 void TTCN3Module::generate_TTCN3_import_statements(FILE * file
) {
261 for (List
<RootType
*>::iterator type
= definedTypes
.begin(); type
; type
= type
->Next
) {
262 if (type
->Data
->getConstruct() == c_import
) {
263 type
->Data
->printToFile(file
);
268 void TTCN3Module::generate_TTCN3_included_types(FILE * file
) {
269 for (List
<RootType
*>::iterator type
= definedTypes
.begin(); type
; type
= type
->Next
) {
270 if (type
->Data
->getConstruct() == c_include
) {
271 type
->Data
->printToFile(file
);
276 void TTCN3Module::generate_TTCN3_types(FILE * file
) {
277 for (List
<RootType
*>::iterator type
= definedTypes
.begin(); type
; type
= type
->Next
) {
278 if (type
->Data
->getConstruct() != c_include
&& type
->Data
->getConstruct() != c_import
) {
279 type
->Data
->printToFile(file
);
284 void TTCN3Module::generate_with_statement(FILE * file
, List
<NamespaceType
> used_namespaces
) {
296 for (List
<NamespaceType
>::iterator usedNS
= used_namespaces
.begin(); usedNS
; usedNS
= usedNS
->Next
) {
297 if (usedNS
->Data
.uri
== "http://www.w3.org/2001/XMLSchema") {
301 if (usedNS
->Data
.uri
== "NoTargetNamespace") {
304 // XXX this inner loop is either redundant now, or it should be elsewhere.
305 // It is quite dodgy to modify(!) namespaces when we are already generating code.
306 for (List
<NamespaceType
>::iterator usedNS2
= usedNS
->Next
; usedNS2
; usedNS2
= usedNS2
->Next
) {
307 if (usedNS
->Data
.uri
== usedNS2
->Data
.uri
) {
308 if (usedNS2
->Data
.prefix
.empty())
309 usedNS2
->Data
.prefix
= usedNS
->Data
.prefix
;
315 if (targetNamespace
!= "NoTargetNamespace") {
316 fprintf(file
, " variant \"namespace as \'%s\'", targetNamespace
.c_str());
317 if (!targetNamespace_connectedPrefix
.empty()) {
318 fprintf(file
, " prefix \'%s\'", targetNamespace_connectedPrefix
.c_str());
320 fprintf(file
, "\";\n");
326 " variant \"controlNamespace \'http://www.w3.org/2001/XMLSchema-instance\' prefix \'xsi\'\";\n");
328 if (attributeFormDefault
== qualified
) {
330 " variant \"attributeFormQualified\";\n");
332 if (elementFormDefault
== qualified
) {
334 " variant \"elementFormQualified\";\n");
340 void TTCN3Module::TargetNamespace2ModuleName() {
341 Mstring
res(targetNamespace
);
345 found
= res
.foundAt("http://");
346 //check if the http:// is at the beginning of the namespace
347 if (found
== res
.c_str()) { //res.c_str() returns a pointer to the first char
348 for (int i
= 0; i
!= 7; ++i
) {
352 found
= res
.foundAt("urn:");
353 //check if the urn: is at the beginning of the namespace
354 if (found
== res
.c_str()) { //res.c_str() returns a pointer to the first char
355 for (int i
= 0; i
!= 4; ++i
) {
361 // the characters ' '(SPACE), '.'(FULL STOP) and '-'(HYPEN-MINUS)
362 // and '/', '#', ':' shall all be replaced by a "_" (LOW LINE)
363 for (size_t i
= 0; i
!= res
.size(); ++i
) {
364 if ((res
[i
] == ' ') ||
373 // any character except "A" to "Z", "a" to "z" or "0" to "9" and "_" shall be removed
374 for (size_t i
= 0; i
!= res
.size(); ++i
) {
375 if (!isalpha((const unsigned char) res
[i
]) && !isdigit((const unsigned char) res
[i
]) && (res
[i
] != '_')) {
380 // a sequence of two of more "_" (LOW LINE) shall be replaced with a single "_" (LOW LINE)
381 for (size_t i
= 1; i
< res
.size(); ++i
) {
382 if (res
[i
] == '_' && res
[i
- 1] == '_') {
389 // "_" (LOW LINE) characters occurring at the beginning of the name shall be removed
395 // "_" (LOW LINE) characters occurring at the end of the name shall be removed
396 if (res
[res
.size() - 1] == '_') {
397 res
.eraseChar(res
.size() - 1);
403 } else if (isdigit((const unsigned char) res
[0])) {
404 res
.insertChar(0, 'x');
407 //Postfix with _i if the targetnamespace is different
408 bool postfixing
= false;
409 for (List
<TTCN3Module
*>::iterator mod
= TTCN3ModuleInventory::getInstance().getModules().begin(); mod
; mod
= mod
->Next
) {
410 if (mod
->Data
!= this && mod
->Data
->getModulename() == res
&& mod
->Data
->getTargetNamespace() != targetNamespace
) {
419 expstring_t tmpname
= NULL
;
423 tmpname
= mprintf("%s_%d", res
.c_str(), counter
);
424 for(List
<TTCN3Module
*>::iterator mod
= TTCN3ModuleInventory::getInstance().getModules().begin(); mod
; mod
= mod
->Next
){
425 if(mod
->Data
!= this && mod
->Data
->getModulename() == Mstring(tmpname
)){
432 res
= Mstring(tmpname
);
439 void TTCN3Module::dump() const {
440 fprintf(stderr
, "Module '%s' at %p (from %s)\n",
441 modulename
.c_str(), (const void*) this, schemaname
.c_str());
443 for (List
<RootType
*>::iterator type
= definedTypes
.begin(); type
; type
= type
->Next
) {