Merge pull request #19 from nspaseski/master
[deliverable/titan.core.git] / xsdconvert / GeneralFunctions.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 "GeneralFunctions.hh"
9#include "SimpleType.hh"
10#include "TTCN3Module.hh"
feade998 11#include "ImportStatement.hh"
970ed795
EL
12
13#include <cctype> // for using "toupper" function
14#include <cstring>
15#include <cstdio>
16#include <cmath>
3abe9331 17#include <regex.h>
970ed795 18
feade998 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
970ed795 29extern bool w_flag_used;
feade998 30extern bool t_flag_used;
970ed795
EL
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//
3abe9331 40
970ed795 41void XSDName2TTCN3Name(const Mstring& in, QualifiedNames & used_names, modeType type_of_the_name,
3abe9331 42 Mstring & res, Mstring & variant, bool no_replace) {
43 static const char* TTCN3_reserved_words[] = {
970ed795
EL
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 };
3abe9331 71 static const char* TTCN3_predefined_functions[] = {
970ed795
EL
72 "bit2int", "bit2hex", "bit2oct", "bit2str",
73 "char2int", "char2oct",
74 "decomp", "decvalue",
75 "encvalue", "enum2int",
76 "float2int", "float2str",
77 "hex2bit", "hex2int", "hex2oct", "hex2str",
3abe9331 78 "int2bit", "int2char", "int2enum", "int2float", "int2hex", "int2oct", "int2str", "int2unichar",
970ed795
EL
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 };
3abe9331 88 static const char* ASN1_reserved_words[] = {
970ed795
EL
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
3abe9331 126 if (type_of_the_name == type_reference_name) {
970ed795
EL
127 if (isBuiltInType(res)) {
128 res[0] = toupper(res[0]);
129 res = "XSD." + res;
130 return;
131 }
132 if (res == "record" ||
133 res == "union" ||
3abe9331 134 res == "set") {
970ed795
EL
135 return;
136 }
137 }
138
3abe9331 139 if (type_of_the_name == enum_id_name) {
970ed795 140 bool found = false;
3abe9331 141 for (QualifiedNames::iterator used = used_names.begin(); used; used = used->Next) {
970ed795 142 QualifiedName tmp(empty_string, res);
3abe9331 143 if (tmp.nsuri == used->Data.nsuri && tmp.orig_name == used->Data.orig_name) {
970ed795
EL
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] == ' ') ||
3abe9331 159 (res[i] == '.' && !no_replace) ||
160 (res[i] == '-')) {
970ed795
EL
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) {
3abe9331 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 }
970ed795
EL
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) {
3abe9331 175 if (res[i] == '_' && res[i - 1] == '_') {
176 res.eraseChar(i);
177 i--;
970ed795
EL
178 }
179 }
180 // "_" (LOW LINE) characters occurring at the end of the name shall be removed
3abe9331 181 if (!res.empty() && res[res.size() - 1] == '_') {
182 res.eraseChar(res.size() - 1);
183 }
970ed795 184 // "_" (LOW LINE) characters occurring at the beginning of the name shall be removed
3abe9331 185 if (!res.empty() && res[0] == '_') {
186 res.eraseChar(0);
187 }
970ed795
EL
188 }
189
3abe9331 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;
970ed795
EL
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;
3abe9331 226 QualifiedName qual_name(ns_uri, res, in);
970ed795 227
970ed795 228
3abe9331 229 switch (type_of_the_name) {
230 // Do not use "res" in this switch; only qual_name
231 case type_name:
970ed795 232 {
3abe9331 233 for (int k = 0; ASN1_reserved_words[k]; k++) {
234 if (qual_name.name == ASN1_reserved_words[k]) {
235 postfixing = true;
236 break;
970ed795 237 }
3abe9331 238 }
970ed795 239
3abe9331 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 }
970ed795 246
3abe9331 247 if (postfixing) {
248 bool found = false;
249 int counter = 1;
250 expstring_t tmpname = NULL;
251 do {
252 found = false;
970ed795
EL
253 Free(tmpname);
254 tmpname = mprintf("%s_%d", qual_name.name.c_str(), counter);
3abe9331 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 }
970ed795 260 }
3abe9331 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;
970ed795 268 }
3abe9331 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;
970ed795
EL
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"
3abe9331 321 if (type_of_the_name != type_reference_name) {
970ed795 322 bool found = false;
3abe9331 323 for (QualifiedNames::iterator used = used_names.begin(); used; used = used->Next) {
970ed795
EL
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" ||
3abe9331 341 in == "choice_list") {
970ed795
EL
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();
3abe9331 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 + "'\"";
970ed795 365 }
3abe9331 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;
970ed795
EL
392 }
393 }
394}
395
3abe9331 396bool isBuiltInType(const Mstring& in) {
970ed795
EL
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",
3abe9331 403 "QName", "boolean", "anyType", "anySimpleType", NULL
970ed795
EL
404 };
405 const Mstring& name = in.getValueWithoutPrefix(':');
406 for (int i = 0; XSD_built_in_types[i]; ++i) {
3abe9331 407 if (name == XSD_built_in_types[i]) {
408 return true;
409 }
970ed795
EL
410 }
411 return false;
412}
413
3abe9331 414bool isStringType(const Mstring& in) {
970ed795
EL
415 static const char* string_types[] = {
416 "string", "normalizedString", "token", "Name", "NMTOKEN", "NCName", "ID", "IDREF", "ENTITY",
3abe9331 417 "hexBinary", "base64Binary", "anyURI", "language", NULL
970ed795
EL
418 };
419 const Mstring& name = in.getValueWithoutPrefix(':');
420 for (int i = 0; string_types[i]; ++i) {
3abe9331 421 if (name == string_types[i]) {
422 return true;
423 }
970ed795
EL
424 }
425 return false;
426}
427
3abe9331 428bool isIntegerType(const Mstring& in) {
970ed795
EL
429 static const char* integer_types[] = {
430 "integer", "positiveInteger", "nonPositiveInteger", "negativeInteger", "nonNegativeInteger", "long",
3abe9331 431 "unsignedLong", "int", "unsignedInt", "short", "unsignedShort", "byte", "unsignedByte", NULL
970ed795
EL
432 };
433 const Mstring& name = in.getValueWithoutPrefix(':');
434 for (int i = 0; integer_types[i]; ++i) {
3abe9331 435 if (name == integer_types[i]) {
436 return true;
437 }
970ed795
EL
438 }
439 return false;
440}
441
3abe9331 442bool isFloatType(const Mstring& in) {
970ed795
EL
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) {
3abe9331 448 if (name == float_types[i]) {
449 return true;
450 }
970ed795
EL
451 }
452 return false;
453}
454
3abe9331 455bool isTimeType(const Mstring& in) {
970ed795
EL
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) {
3abe9331 461 if (name == time_types[i]) {
462 return true;
463 }
970ed795
EL
464 }
465 return false;
466}
467
3abe9331 468bool isSequenceType(const Mstring& in) {
970ed795
EL
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) {
3abe9331 474 if (name == sequence_types[i]) {
475 return true;
476 }
970ed795
EL
477 }
478 return false;
479}
480
3abe9331 481bool isBooleanType(const Mstring& in) {
970ed795
EL
482 static const Mstring booltype("boolean");
483 return booltype == in.getValueWithoutPrefix(':');
484}
485
3abe9331 486bool isQNameType(const Mstring& in) {
970ed795
EL
487 static const Mstring qntype("QName");
488 return qntype == in.getValueWithoutPrefix(':');
489}
490
3abe9331 491bool isAnyType(const Mstring& in) {
970ed795
EL
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
3abe9331 502bool 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
552bool 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
566void printError(const Mstring& filename, int lineNumber, const Mstring& text) {
970ed795
EL
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
3abe9331 576void printError(const Mstring& filename, const Mstring& typeName, const Mstring& text) {
970ed795
EL
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
3abe9331 586void printWarning(const Mstring& filename, int lineNumber, const Mstring& text) {
970ed795
EL
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
3abe9331 597void printWarning(const Mstring& filename, const Mstring& typeName, const Mstring& text) {
970ed795
EL
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
3abe9331 608void indent(FILE* file, const int x) {
609 for (int l = 0; l < x; ++l) {
610 fprintf(file, "\t");
611 }
612}
613
614long double stringToLongDouble(const char *input) {
970ed795
EL
615 long double result = 0.0;
616 // `strtold()' is not available on older platforms.
617 sscanf(input, "%Lf", &result);
618 return result;
619}
620
3abe9331 621const 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;
970ed795 625 }
970ed795 626 }
3abe9331 627 return empty_string;
628}
629
630const 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
639const 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 }
970ed795
EL
648}
649
3abe9331 650RootType * lookup(const List<TTCN3Module*> mods, const SimpleType * reference, wanted w) {
970ed795
EL
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
3abe9331 657RootType * lookup(const List<TTCN3Module*> mods,
658 const Mstring& name, const Mstring& nsuri, const RootType *reference, wanted w) {
970ed795 659 RootType *ret = NULL;
3abe9331 660 for (List<TTCN3Module*>::iterator module = mods.begin(); module; module = module->Next) {
970ed795
EL
661 ret = lookup1(module->Data, name, nsuri, reference, w);
662 if (ret != NULL) break;
663 } // next doc
664
665 return ret;
666}
667
668RootType *lookup1(const TTCN3Module *module,
3abe9331 669 const Mstring& name, const Mstring& nsuri, const RootType *reference, wanted w) {
970ed795 670 if (nsuri != module->getTargetNamespace()) return NULL;
feade998 671
3abe9331 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 }
970ed795 682 }
3abe9331 683 break;
970ed795 684
3abe9331 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 }
970ed795 693 }
3abe9331 694 break;
970ed795 695
3abe9331 696 default:
697 break;
970ed795
EL
698 }
699 }
feade998 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 }
970ed795
EL
710 return NULL;
711}
712
713int multi(const TTCN3Module *module, ReferenceData const& outside_reference,
3abe9331 714 const RootType *obj) {
970ed795
EL
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
3abe9331 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 }
970ed795 728 }
970ed795
EL
729 return multiplicity;
730}
feade998 731
732void 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.059961 seconds and 5 git commands to generate.