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