Sync with 5.4.3
[deliverable/titan.core.git] / xsdconvert / GeneralFunctions.cc
1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2015 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 "GeneralFunctions.hh"
9 #include "SimpleType.hh"
10 #include "TTCN3Module.hh"
11 #include "ImportStatement.hh"
12
13 #include <cctype> // for using "toupper" function
14 #include <cstring>
15 #include <cstdio>
16 #include <cmath>
17 #include <regex.h>
18
19 #include "../common/version_internal.h"
20
21 #include <ctime>
22
23 #if defined(WIN32) && !defined(MINGW)
24 #include <cygwin/version.h>
25 #include <sys/cygwin.h>
26 #include <limits.h>
27 #endif
28
29 extern bool w_flag_used;
30 extern bool t_flag_used;
31
32 // XSDName2TTCN3Name function:
33 // Parameters:
34 // in - input string - XSD name
35 // used_names - set of previously defined types, used field names etc.
36 // type_of_the_name - mode of the function behaviour
37 // res - generated result
38 // variant - generated variant string for TTCN-3
39 //
40
41 void XSDName2TTCN3Name(const Mstring& in, QualifiedNames & used_names, modeType type_of_the_name,
42 Mstring & res, Mstring & variant, bool no_replace) {
43 static const char* TTCN3_reserved_words[] = {
44 "action", "activate", "address", "alive", "all", "alt", "altstep", "and", "and4b", "any", "anytype", "apply",
45 "bitstring", "boolean", "break",
46 "call", "case", "catch", "char", "charstring", "check", "clear", "complement", "component", "connect",
47 "const", "continue", "control", "create",
48 "deactivate", "default", "derefers", "disconnect", "display", "do", "done",
49 "else", "encode", "enumerated", "error", "except", "exception", "execute", "extends", "extension",
50 "external",
51 "fail", "false", "float", "for", "friend", "from", "function",
52 "getverdict", "getcall", "getreply", "goto", "group",
53 "halt", "hexstring",
54 "if", "if present", "import", "in", "inconc", "infinity", "inout", "integer", "interleave",
55 "kill", "killed",
56 "label", "language", "length", "log",
57 "map", "match", "message", "mixed", "mod", "modifies", "module", "modulepar", "mtc",
58 "noblock", "none", "not", "not4b", "nowait", "null",
59 "objid", "octetstring", "of", "omit", "on", "optional", "or", "or4b", "out", "override",
60 "param", "pass", "pattern", "permutation", "port", "present", "private", "procedure", "public",
61 "raise", "read", "receive", "record", "recursive", "refers", "rem", "repeat", "reply", "return", "running", "runs",
62 "select", "self", "send", "sender", "set", "setverdict", "signature", "start", "stop", "subset",
63 "superset", "system",
64 "template", "testcase", "timeout", "timer", "to", "trigger", "true", "type",
65 "union", "universal", "unmap",
66 "value", "valueof", "var", "variant", "verdicttype",
67 "while", "with",
68 "xor", "xor4b",
69 NULL
70 };
71 static const char* TTCN3_predefined_functions[] = {
72 "bit2int", "bit2hex", "bit2oct", "bit2str",
73 "char2int", "char2oct",
74 "decomp", "decvalue",
75 "encvalue", "enum2int",
76 "float2int", "float2str",
77 "hex2bit", "hex2int", "hex2oct", "hex2str",
78 "int2bit", "int2char", "int2enum", "int2float", "int2hex", "int2oct", "int2str", "int2unichar",
79 "isvalue", "ischosen", "ispresent",
80 "lengthof", "log2str",
81 "oct2bit", "oct2char", "oct2hex", "oct2int", "oct2str", "oct2unichar"
82 "regexp", "replace", "rnd", "remove_bom", "get_stringencoding",
83 "sizeof", "str2bit", "str2float", "str2hex", "str2int", "str2oct", "substr",
84 "testcasename",
85 "unichar2int", "unichar2char", "unichar2oct",
86 NULL
87 };
88 static const char* ASN1_reserved_words[] = {
89 "ABSENT", "ABSTRACT-SYNTAX", "ALL", "APPLICATION", "AUTOMATIC",
90 "BEGIN", "BIT", "BMPString", "BOOLEAN", "BY",
91 "CHARACTER", "CHOICE", "CLASS", "COMPONENT", "COMPONENTS", "CONSTRAINED", "CONTAINING",
92 "DEFAULT", "DEFINITIONS",
93 "EMBEDDED", "ENCODED", "END", "ENUMERATED", "EXCEPT", "EXPLICIT", "EXPORTS", "EXTENSIBILITY",
94 "EXTERNAL",
95 "FALSE", "FROM",
96 "GeneralizedTime", "GeneralString", "GraphicString",
97 "IA5String", "IDENTIFIER", "IMPLICIT", "IMPLIED", "IMPORTS", "INCLUDES", "INSTANCE", "INTEGER",
98 "INTERSECTION", "ISO646String",
99 "MAX", "MIN", "MINUS-INFINITY",
100 "NULL", "NumericString",
101 "OBJECT", "ObjectDescriptor", "OCTET", "OF", "OPTIONAL",
102 "PATTERN", "PDV", "PLUS-INFINITY", "PRESENT", "PrintableString", "PRIVATE",
103 "REAL", "RELATIVE-OID",
104 "SEQUENCE", "SET", "SIZE", "STRING", "SYNTAX",
105 "T61String", "TAGS", "TeletexString", "TRUE", "TYPE-IDENTIFIER",
106 "UNION", "UNIQUE", "UNIVERSAL", "UniversalString", "UTCTime", "UTF8String",
107 "VideotexString", "VisibleString",
108 "WITH",
109 NULL
110 };
111
112 Mstring ns_uri(variant);
113
114 res.clear();
115 variant.clear();
116 res = in;
117
118 if (res.size() > 0) {
119 /********************************************************
120 * STEP 0 - recognizing XSD built-in types
121 *
122 * ******************************************************/
123 // If the type or field reference name is an XSD built-in type then it will be capitalized and get a prefix "XSD."
124 // if (type_of_the_name == type_reference_name || type_of_the_name == field_reference_name) {
125
126 if (type_of_the_name == type_reference_name) {
127 if (isBuiltInType(res)) {
128 res[0] = toupper(res[0]);
129 res = "XSD." + res;
130 return;
131 }
132 if (res == "record" ||
133 res == "union" ||
134 res == "set") {
135 return;
136 }
137 }
138
139 if (type_of_the_name == enum_id_name) {
140 bool found = false;
141 for (QualifiedNames::iterator used = used_names.begin(); used; used = used->Next) {
142 QualifiedName tmp(empty_string, res);
143 if (tmp.nsuri == used->Data.nsuri && tmp.orig_name == used->Data.orig_name) {
144 found = true;
145 break;
146 }
147 }
148 if (found) return;
149 }
150 /********************************************************
151 * STEP 1 - character changes
152 *
153 * according to
154 * clause 5.2.2.1 - Generic name transformation rules
155 * ******************************************************/
156 // the characters ' '(SPACE), '.'(FULL STOP) and '-'(HYPEN-MINUS)shall all be replaced by a "_" (LOW LINE)
157 for (size_t i = 0; i != res.size(); ++i) {
158 if ((res[i] == ' ') ||
159 (res[i] == '.' && !no_replace) ||
160 (res[i] == '-')) {
161 res[i] = '_';
162 }
163 }
164 // any character except "A" to "Z", "a" to "z" or "0" to "9" and "_" shall be removed
165 for (size_t i = 0; i != res.size(); ++i) {
166 if (!isalpha((const unsigned char) res[i]) && !isdigit((const unsigned char) res[i]) && (res[i] != '_')) {
167 if (!no_replace && res[i] != '.') {
168 res.eraseChar(i);
169 i--;
170 }
171 }
172 }
173 // a sequence of two of more "_" (LOW LINE) shall be replaced with a single "_" (LOW LINE)
174 for (size_t i = 1; i < res.size(); ++i) {
175 if (res[i] == '_' && res[i - 1] == '_') {
176 res.eraseChar(i);
177 i--;
178 }
179 }
180 // "_" (LOW LINE) characters occurring at the end of the name shall be removed
181 if (!res.empty() && res[res.size() - 1] == '_') {
182 res.eraseChar(res.size() - 1);
183 }
184 // "_" (LOW LINE) characters occurring at the beginning of the name shall be removed
185 if (!res.empty() && res[0] == '_') {
186 res.eraseChar(0);
187 }
188 }
189
190 switch (type_of_the_name) {
191 case type_reference_name:
192 case type_name:
193 if (res.empty()) {
194 res = "X";
195 } else {
196 if (islower((const unsigned char) res[0])) {
197 res.setCapitalized();
198 } else if (isdigit((const unsigned char) res[0])) {
199 res.insertChar(0, 'X');
200 }
201 }
202 break;
203 case field_name:
204 case enum_id_name:
205 if (res.empty()) {
206 res = "x";
207 } else {
208 if (isupper((const unsigned char) res[0])) res.setUncapitalized();
209 else if (isdigit((const unsigned char) res[0])) res.insertChar(0, 'x');
210 }
211 break;
212 }
213 /********************************************************
214 * STEP 2 - process if the generated name is
215 * - already used
216 * - a TTCN3 keyword
217 * - an ASN.1 keyword
218 * and after any change is made
219 * according to
220 * clause 5.2.2.2 - Succeeding rules
221 * ******************************************************/
222 /********************************************************
223 * according to paragraph a)
224 * ******************************************************/
225 bool postfixing = false;
226 QualifiedName qual_name(ns_uri, res, in);
227
228
229 switch (type_of_the_name) {
230 // Do not use "res" in this switch; only qual_name
231 case type_name:
232 {
233 for (int k = 0; ASN1_reserved_words[k]; k++) {
234 if (qual_name.name == ASN1_reserved_words[k]) {
235 postfixing = true;
236 break;
237 }
238 }
239
240 for (QualifiedNames::iterator used = used_names.begin(); used; used = used->Next) {
241 if (qual_name == used->Data) {
242 postfixing = true;
243 break;
244 }
245 }
246
247 if (postfixing) {
248 bool found = false;
249 int counter = 1;
250 expstring_t tmpname = NULL;
251 do {
252 found = false;
253 Free(tmpname);
254 tmpname = mprintf("%s_%d", qual_name.name.c_str(), counter);
255 for (QualifiedNames::iterator used = used_names.begin(); used; used = used->Next) {
256 if (QualifiedName(/* empty_string ? */ ns_uri, Mstring(tmpname)) == used->Data) {
257 found = true;
258 break;
259 }
260 }
261 counter++;
262 } while (found);
263 qual_name.name = tmpname; // NULL will result in an empty string
264 Free(tmpname);
265 postfixing = false;
266 }
267 break;
268 }
269 case field_name:
270 case enum_id_name:
271 for (int k = 0; TTCN3_reserved_words[k]; k++) {
272 if (qual_name.name == TTCN3_reserved_words[k]) postfixing = true;
273 }
274 for (int k = 0; TTCN3_predefined_functions[k]; k++) {
275 if (qual_name.name == TTCN3_predefined_functions[k]) postfixing = true;
276 }
277 if (postfixing) {
278 qual_name.name += "_";
279 postfixing = false;
280 }
281
282 for (QualifiedNames::iterator used = used_names.begin(); used; used = used->Next) {
283 if (qual_name == used->Data) postfixing = true;
284 }
285
286 if (postfixing) {
287 bool found = false;
288 int counter = 1;
289 if (qual_name.name[qual_name.name.size() - 1] == '_')
290 qual_name.name.eraseChar(qual_name.name.size() - 1);
291 expstring_t tmpname = mprintf("%s_%d", qual_name.name.c_str(), counter);
292 do {
293 found = false;
294 if (counter > 0) {
295 Free(tmpname);
296 tmpname = mprintf("%s_%d", qual_name.name.c_str(), counter);
297 }
298 for (QualifiedNames::iterator used = used_names.begin(); used; used = used->Next) {
299 if (QualifiedName(/* empty_string ? */ns_uri, Mstring(tmpname)) == used->Data) {
300 found = true;
301 break;
302 }
303 }
304 counter++;
305 } while (found);
306 qual_name.name = tmpname;
307 Free(tmpname);
308 postfixing = false;
309 }
310 break;
311 default:
312 break;
313 }
314
315 res = qual_name.name;
316
317 /********************************************************
318 * STEP 3 - the defined name is put into the set of "not_av_names"
319 * ******************************************************/
320 // Finally recently defined name will be put into the set of "set<string> not_av_names"
321 if (type_of_the_name != type_reference_name) {
322 bool found = false;
323 for (QualifiedNames::iterator used = used_names.begin(); used; used = used->Next) {
324 if (qual_name == used->Data) {
325 found = true;
326 break;
327 }
328 }
329
330 if (!found) {
331 used_names.push_back(qual_name);
332 }
333 }
334 /********************************************************
335 * STEP 4
336 *
337 * ******************************************************/
338 if (in == "sequence" ||
339 in == "choice" ||
340 in == "sequence_list" ||
341 in == "choice_list") {
342 return;
343 }
344 /********************************************************
345 * STEP 5 - if "input name - in" and "generated name - res"
346 * are different
347 * then a "variant string" has to be generated
348 * ******************************************************/
349 // If the final generated type name, field name or enumeration identifier (res) is different from the original one (in) then ...
350 if (in != res) {
351 Mstring tmp1 = in;
352 Mstring tmp2 = res;
353 tmp1.setUncapitalized();
354 tmp2.setUncapitalized();
355 switch (type_of_the_name) {
356 case type_name:
357 if (tmp1 == tmp2) { // If the only difference is the case of the first letter
358 if (isupper(in[0])) {
359 variant += "\"name as capitalized\"";
360 } else {
361 variant += "\"name as uncapitalized\"";
362 }
363 } else { // Otherwise if other letters have changed too
364 variant += "\"name as '" + in + "'\"";
365 }
366 break;
367 case field_name:
368 // Creating a variant string from a field of a complex type needs to write out the path of the fieldname
369 if (tmp1 == tmp2) { // If the only difference is the case of the first letter
370 if (isupper(in[0])) {
371 variant += "\"name as capitalized\"";
372 } else {
373 variant += "\"name as uncapitalized\"";
374 }
375 } else { // Otherwise if other letters have changed too
376 variant += "\"name as '" + in + "'\"";
377 }
378 break;
379 case enum_id_name:
380 if (tmp1 == tmp2) { // If the only difference is the case of the first letter
381 if (isupper(in[0])) {
382 variant += "\"text \'" + res + "\' as capitalized\"";
383 } else {
384 variant += "\"text \'" + res + "\' as uncapitalized\"";
385 }
386 } else { // Otherwise if other letters have changed too
387 variant += "\"text \'" + res + "\' as '" + in + "'\"";
388 }
389 break;
390 default:
391 break;
392 }
393 }
394 }
395
396 bool isBuiltInType(const Mstring& in) {
397 static const char* XSD_built_in_types[] = {
398 "string", "normalizedString", "token", "Name", "NMTOKEN", "NCName", "ID", "IDREF", "ENTITY",
399 "hexBinary", "base64Binary", "anyURI", "language", "integer", "positiveInteger", "nonPositiveInteger",
400 "negativeInteger", "nonNegativeInteger", "long", "unsignedLong", "int", "unsignedInt", "short",
401 "unsignedShort", "byte", "unsignedByte", "decimal", "float", "double", "duration", "dateTime", "time",
402 "date", "gYearMonth", "gYear", "gMonthDay", "gDay", "gMonth", "NMTOKENS", "IDREFS", "ENTITIES",
403 "QName", "boolean", "anyType", "anySimpleType", NULL
404 };
405 const Mstring& name = in.getValueWithoutPrefix(':');
406 for (int i = 0; XSD_built_in_types[i]; ++i) {
407 if (name == XSD_built_in_types[i]) {
408 return true;
409 }
410 }
411 return false;
412 }
413
414 bool isStringType(const Mstring& in) {
415 static const char* string_types[] = {
416 "string", "normalizedString", "token", "Name", "NMTOKEN", "NCName", "ID", "IDREF", "ENTITY",
417 "hexBinary", "base64Binary", "anyURI", "language", NULL
418 };
419 const Mstring& name = in.getValueWithoutPrefix(':');
420 for (int i = 0; string_types[i]; ++i) {
421 if (name == string_types[i]) {
422 return true;
423 }
424 }
425 return false;
426 }
427
428 bool isIntegerType(const Mstring& in) {
429 static const char* integer_types[] = {
430 "integer", "positiveInteger", "nonPositiveInteger", "negativeInteger", "nonNegativeInteger", "long",
431 "unsignedLong", "int", "unsignedInt", "short", "unsignedShort", "byte", "unsignedByte", NULL
432 };
433 const Mstring& name = in.getValueWithoutPrefix(':');
434 for (int i = 0; integer_types[i]; ++i) {
435 if (name == integer_types[i]) {
436 return true;
437 }
438 }
439 return false;
440 }
441
442 bool isFloatType(const Mstring& in) {
443 static const char* float_types[] = {
444 "decimal", "float", "double", NULL
445 };
446 const Mstring& name = in.getValueWithoutPrefix(':');
447 for (int i = 0; float_types[i]; ++i) {
448 if (name == float_types[i]) {
449 return true;
450 }
451 }
452 return false;
453 }
454
455 bool isTimeType(const Mstring& in) {
456 static const char* time_types[] = {
457 "duration", "dateTime", "time", "date", "gYearMonth", "gYear", "gMonthDay", "gDay", "gMonth", NULL
458 };
459 const Mstring& name = in.getValueWithoutPrefix(':');
460 for (int i = 0; time_types[i]; ++i) {
461 if (name == time_types[i]) {
462 return true;
463 }
464 }
465 return false;
466 }
467
468 bool isSequenceType(const Mstring& in) {
469 static const char* sequence_types[] = {
470 "NMTOKENS", "IDREFS", "ENTITIES", "QName", NULL
471 };
472 const Mstring& name = in.getValueWithoutPrefix(':');
473 for (int i = 0; sequence_types[i]; ++i) {
474 if (name == sequence_types[i]) {
475 return true;
476 }
477 }
478 return false;
479 }
480
481 bool isBooleanType(const Mstring& in) {
482 static const Mstring booltype("boolean");
483 return booltype == in.getValueWithoutPrefix(':');
484 }
485
486 bool isQNameType(const Mstring& in) {
487 static const Mstring qntype("QName");
488 return qntype == in.getValueWithoutPrefix(':');
489 }
490
491 bool isAnyType(const Mstring& in) {
492 static const char* any_types[] = {
493 "anyType", "anySimpleType", NULL
494 };
495 const Mstring& name = in.getValueWithoutPrefix(':');
496 for (int i = 0; any_types[i]; ++i) {
497 if (name == any_types[i]) return true;
498 }
499 return false;
500 }
501
502 bool matchDates(const char * string, const char * type) {
503 const Mstring day("(0[1-9]|[12][0-9]|3[01])");
504 const Mstring month("(0[1-9]|1[0-2])");
505 const Mstring year("([0-9][0-9][0-9][0-9])");
506 const Mstring hour("([01][0-9]|2[0-3])");
507 const Mstring minute("([0-5][0-9])");
508 const Mstring second("([0-5][0-9])");
509 const Mstring endofdayext("24:00:00(.0?)?");
510 const Mstring yearext("((-)([1-9][0-9]*)?)?");
511 const Mstring timezone("(Z|[+-]((0[0-9]|1[0-3]):[0-5][0-9]|14:00))?");
512 const Mstring fraction("(.[0-9]+)?");
513 const Mstring nums("[0-9]+");
514 const Mstring durtime("(T[0-9]+"
515 "(H([0-9]+(M([0-9]+(S|.[0-9]+S))?|.[0-9]+S|S))?|"
516 "M([0-9]+(S|.[0-9]+S)|.[0-9]+M)?|S|.[0-9]+S))");
517
518 Mstring pattern;
519 if (strcmp(type, "gDay") == 0) {
520 pattern = Mstring("(---)") + day + timezone;
521 } else if (strcmp(type, "gMonth") == 0) {
522 pattern = Mstring("(--)") + month + timezone;
523 } else if (strcmp(type, "gYear") == 0) {
524 pattern = yearext + year + timezone;
525 } else if (strcmp(type, "gYearMonth") == 0) {
526 pattern = yearext + year + Mstring("(-)") + month + timezone;
527 } else if (strcmp(type, "gMonthDay") == 0) {
528 pattern = Mstring("(--)") + month + Mstring("(-)") + day + timezone;
529 } else if (strcmp(type, "date") == 0) {
530 pattern = yearext + year + Mstring("(-)") + month + Mstring("(-)") + day + timezone;
531 } else if (strcmp(type, "time") == 0) {
532 pattern = Mstring("(") + hour + Mstring(":") + minute + Mstring(":") + second +
533 fraction + Mstring("|") + endofdayext + Mstring(")") + timezone;
534 } else if (strcmp(type, "dateTime") == 0) {
535 pattern = yearext + year + Mstring("(-)") + month + Mstring("(-)") + day +
536 Mstring("T(") + hour + Mstring(":") + minute + Mstring(":") + second +
537 fraction + Mstring("|") + endofdayext + Mstring(")") + timezone;
538 } else if (strcmp(type, "duration") == 0) {
539 pattern = Mstring("(-)?P(") + nums + Mstring("(Y(") + nums + Mstring("(M(") +
540 nums + Mstring("D") + durtime + Mstring("?|") + durtime + Mstring("?|D") +
541 durtime + Mstring("?)|") + durtime + Mstring("?)|M") + nums + Mstring("D") +
542 durtime + Mstring("?|") + durtime + Mstring("?)|D") + durtime +
543 Mstring("?)|") + durtime + Mstring(")");
544 } else {
545 return false;
546 }
547
548 pattern = Mstring("^") + pattern + Mstring("$");
549 return matchRegexp(string, pattern.c_str());
550 }
551
552 bool matchRegexp(const char * string, const char * pattern) {
553 int status;
554 regex_t re;
555 if (regcomp(&re, pattern, REG_EXTENDED | REG_NOSUB) != 0) {
556 return (false); /* report error */
557 }
558 status = regexec(&re, string, (size_t) 0, NULL, 0);
559 regfree(&re);
560 if (status != 0) {
561 return (false); /* report error */
562 }
563 return (true);
564 }
565
566 void printError(const Mstring& filename, int lineNumber, const Mstring& text) {
567 fprintf(stderr,
568 "ERROR:\n"
569 "%s (in line %d): "
570 "%s\n",
571 filename.c_str(),
572 lineNumber,
573 text.c_str());
574 }
575
576 void printError(const Mstring& filename, const Mstring& typeName, const Mstring& text) {
577 fprintf(stderr,
578 "ERROR:\n"
579 "%s (in type %s): "
580 "%s\n",
581 filename.c_str(),
582 typeName.c_str(),
583 text.c_str());
584 }
585
586 void printWarning(const Mstring& filename, int lineNumber, const Mstring& text) {
587 if (w_flag_used) return;
588 fprintf(stderr,
589 "WARNING:\n"
590 "%s (in line %d): "
591 "%s\n",
592 filename.c_str(),
593 lineNumber,
594 text.c_str());
595 }
596
597 void printWarning(const Mstring& filename, const Mstring& typeName, const Mstring& text) {
598 if (w_flag_used) return;
599 fprintf(stderr,
600 "WARNING:\n"
601 "%s (in type %s): "
602 "%s\n",
603 filename.c_str(),
604 typeName.c_str(),
605 text.c_str());
606 }
607
608 void indent(FILE* file, const int x) {
609 for (int l = 0; l < x; ++l) {
610 fprintf(file, "\t");
611 }
612 }
613
614 long double stringToLongDouble(const char *input) {
615 long double result = 0.0;
616 // `strtold()' is not available on older platforms.
617 sscanf(input, "%Lf", &result);
618 return result;
619 }
620
621 const Mstring& getNameSpaceByPrefix(const RootType * root, const Mstring& prefix){
622 for(List<NamespaceType>::iterator mod = root->getModule()->getDeclaredNamespaces().begin(); mod; mod = mod->Next){
623 if(mod->Data.prefix == prefix){
624 return mod->Data.uri;
625 }
626 }
627 return empty_string;
628 }
629
630 const Mstring& getPrefixByNameSpace(const RootType * root, const Mstring& namespace_){
631 for(List<NamespaceType>::iterator mod = root->getModule()->getDeclaredNamespaces().begin(); mod; mod = mod->Next){
632 if(mod->Data.uri == namespace_){
633 return mod->Data.prefix;
634 }
635 }
636 return empty_string;
637 }
638
639 const Mstring findBuiltInType(const RootType* ref, Mstring type){
640 RootType * root = TTCN3ModuleInventory::getInstance().lookup(ref, type, want_BOTH);
641 if(root != NULL && isBuiltInType(root->getType().originalValueWoPrefix)){
642 return root->getType().originalValueWoPrefix;
643 }else if(root != NULL){
644 return findBuiltInType(root, root->getType().originalValueWoPrefix);
645 }else {
646 return type;
647 }
648 }
649
650 RootType * lookup(const List<TTCN3Module*> mods, const SimpleType * reference, wanted w) {
651 const Mstring& uri = reference->getReference().get_uri();
652 const Mstring& name = reference->getReference().get_val();
653
654 return lookup(mods, name, uri, reference, w);
655 }
656
657 RootType * lookup(const List<TTCN3Module*> mods,
658 const Mstring& name, const Mstring& nsuri, const RootType *reference, wanted w) {
659 RootType *ret = NULL;
660 for (List<TTCN3Module*>::iterator module = mods.begin(); module; module = module->Next) {
661 ret = lookup1(module->Data, name, nsuri, reference, w);
662 if (ret != NULL) break;
663 } // next doc
664
665 return ret;
666 }
667
668 RootType *lookup1(const TTCN3Module *module,
669 const Mstring& name, const Mstring& nsuri, const RootType *reference, wanted w) {
670 if (nsuri != module->getTargetNamespace()) return NULL;
671
672 for (List<RootType*>::iterator type = module->getDefinedTypes().begin(); type; type = type->Next) {
673 switch (type->Data->getConstruct()) {
674 case c_simpleType:
675 case c_element:
676 case c_attribute:
677 if (w == want_ST || w == want_BOTH) {
678 if ((const RootType*) reference != type->Data
679 && name == type->Data->getName().originalValueWoPrefix) {
680 return type->Data;
681 }
682 }
683 break;
684
685 case c_complexType:
686 case c_group:
687 case c_attributeGroup:
688 if (w == want_CT || w == want_BOTH) {
689 if ((const RootType*) reference != type->Data
690 && name == type->Data->getName().originalValueWoPrefix) {
691 return type->Data;
692 }
693 }
694 break;
695
696 default:
697 break;
698 }
699 }
700
701 //Check for an include with NoTargetNamespace to look for the type
702 //XSD to TTCN ETSI standard 5.1.2
703 for(List<RootType*>::iterator it = module->getDefinedTypes().begin(); it; it = it->Next) {
704 if (it->Data != NULL && it->Data->getConstruct() == c_include &&
705 ((ImportStatement*)(it->Data))->getSourceModule() != NULL &&
706 ((ImportStatement*)(it->Data))->getSourceModule()->getTargetNamespace() == Mstring("NoTargetNamespace")) {
707 return lookup1(((ImportStatement*)(it->Data))->getSourceModule(), name, Mstring("NoTargetNamespace"), reference, w);
708 }
709 }
710 return NULL;
711 }
712
713 int multi(const TTCN3Module *module, ReferenceData const& outside_reference,
714 const RootType *obj) {
715 int multiplicity = 0;
716
717 RootType * st = ::lookup1(module, outside_reference.get_val(), outside_reference.get_uri(), obj, want_ST);
718 RootType * ct = ::lookup1(module, outside_reference.get_val(), outside_reference.get_uri(), obj, want_CT);
719 if (st || ct) {
720 multiplicity = 1; // locally defined, no qualif needed
721 } else for (List<const TTCN3Module*>::iterator it = module->getImportedModules().begin(); it; it = it->Next) {
722 // Artificial lookup
723 st = ::lookup1(it->Data, outside_reference.get_val(), it->Data->getTargetNamespace(), obj, want_ST);
724 ct = ::lookup1(it->Data, outside_reference.get_val(), it->Data->getTargetNamespace(), obj, want_CT);
725 if (st || ct) {
726 ++multiplicity;
727 }
728 }
729 return multiplicity;
730 }
731
732 void generate_TTCN3_header(FILE * file, const char * modulename, const bool timestamp /* = true */) {
733 time_t time_current = time(NULL);
734 fprintf(file,
735 "/*******************************************************************************\n"
736 );
737 if (t_flag_used) {
738 fprintf(file,
739 "* Copyright Ericsson Telecom AB\n"
740 "*\n"
741 "* XSD to TTCN-3 Translator\n"
742 "*\n"
743 );
744 } else {
745 fprintf(file,
746 "* Copyright (c) 2000-%-4d Ericsson Telecom AB\n"
747 "*\n"
748 "* XSD to TTCN-3 Translator version: %-40s\n"
749 "*\n",
750 1900 + (localtime(&time_current))->tm_year,
751 PRODUCT_NUMBER
752 );
753 }
754 fprintf(file,
755 "* All rights reserved. This program and the accompanying materials\n"
756 "* are made available under the terms of the Eclipse Public License v1.0\n"
757 "* which accompanies this distribution, and is available at\n"
758 "* http://www.eclipse.org/legal/epl-v10.html\n"
759 "*******************************************************************************/\n"
760 "//\n"
761 "// File: %s.ttcn\n"
762 "// Description:\n"
763 "// References:\n"
764 "// Rev:\n"
765 "// Prodnr:\n",
766 modulename
767 );
768 if (t_flag_used || !timestamp) {
769 fprintf(file,
770 "// Updated:\n"
771 );
772 } else {
773 fprintf(file,
774 "// Updated: %s",
775 ctime(&time_current)
776 );
777 }
778 fprintf(file,
779 "// Contact: http://ttcn.ericsson.se\n"
780 "//\n"
781 "////////////////////////////////////////////////////////////////////////////////\n"
782 );
783 }
This page took 0.049616 seconds and 5 git commands to generate.