implemented decmatch (artf724241)
[deliverable/titan.core.git] / xsdconvert / GeneralFunctions.cc
CommitLineData
d44e3c4f 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 ******************************************************************************/
970ed795
EL
19#include "GeneralFunctions.hh"
20#include "SimpleType.hh"
21#include "TTCN3Module.hh"
feade998 22#include "ImportStatement.hh"
970ed795
EL
23
24#include <cctype> // for using "toupper" function
25#include <cstring>
26#include <cstdio>
27#include <cmath>
3abe9331 28#include <regex.h>
970ed795 29
feade998 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
970ed795 40extern bool w_flag_used;
feade998 41extern bool t_flag_used;
970ed795
EL
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//
3abe9331 51
970ed795 52void XSDName2TTCN3Name(const Mstring& in, QualifiedNames & used_names, modeType type_of_the_name,
3abe9331 53 Mstring & res, Mstring & variant, bool no_replace) {
54 static const char* TTCN3_reserved_words[] = {
970ed795
EL
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",
28352dbd 59 "decmatch", "deactivate", "default", "derefers", "disconnect", "display", "do", "done",
970ed795
EL
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 };
3abe9331 82 static const char* TTCN3_predefined_functions[] = {
970ed795
EL
83 "bit2int", "bit2hex", "bit2oct", "bit2str",
84 "char2int", "char2oct",
85 "decomp", "decvalue",
86 "encvalue", "enum2int",
87 "float2int", "float2str",
88 "hex2bit", "hex2int", "hex2oct", "hex2str",
3abe9331 89 "int2bit", "int2char", "int2enum", "int2float", "int2hex", "int2oct", "int2str", "int2unichar",
970ed795
EL
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 };
3abe9331 99 static const char* ASN1_reserved_words[] = {
970ed795
EL
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
3abe9331 137 if (type_of_the_name == type_reference_name) {
970ed795
EL
138 if (isBuiltInType(res)) {
139 res[0] = toupper(res[0]);
140 res = "XSD." + res;
141 return;
142 }
143 if (res == "record" ||
144 res == "union" ||
3abe9331 145 res == "set") {
970ed795
EL
146 return;
147 }
148 }
149
3abe9331 150 if (type_of_the_name == enum_id_name) {
970ed795 151 bool found = false;
3abe9331 152 for (QualifiedNames::iterator used = used_names.begin(); used; used = used->Next) {
970ed795 153 QualifiedName tmp(empty_string, res);
3abe9331 154 if (tmp.nsuri == used->Data.nsuri && tmp.orig_name == used->Data.orig_name) {
970ed795
EL
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] == ' ') ||
3abe9331 170 (res[i] == '.' && !no_replace) ||
171 (res[i] == '-')) {
970ed795
EL
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) {
3abe9331 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 }
970ed795
EL
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) {
3abe9331 186 if (res[i] == '_' && res[i - 1] == '_') {
187 res.eraseChar(i);
188 i--;
970ed795
EL
189 }
190 }
191 // "_" (LOW LINE) characters occurring at the end of the name shall be removed
3abe9331 192 if (!res.empty() && res[res.size() - 1] == '_') {
193 res.eraseChar(res.size() - 1);
194 }
970ed795 195 // "_" (LOW LINE) characters occurring at the beginning of the name shall be removed
3abe9331 196 if (!res.empty() && res[0] == '_') {
197 res.eraseChar(0);
198 }
970ed795
EL
199 }
200
3abe9331 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;
970ed795
EL
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;
3abe9331 237 QualifiedName qual_name(ns_uri, res, in);
970ed795 238
970ed795 239
3abe9331 240 switch (type_of_the_name) {
241 // Do not use "res" in this switch; only qual_name
242 case type_name:
970ed795 243 {
3abe9331 244 for (int k = 0; ASN1_reserved_words[k]; k++) {
245 if (qual_name.name == ASN1_reserved_words[k]) {
246 postfixing = true;
247 break;
970ed795 248 }
3abe9331 249 }
970ed795 250
3abe9331 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 }
970ed795 257
3abe9331 258 if (postfixing) {
259 bool found = false;
260 int counter = 1;
261 expstring_t tmpname = NULL;
262 do {
263 found = false;
970ed795
EL
264 Free(tmpname);
265 tmpname = mprintf("%s_%d", qual_name.name.c_str(), counter);
3abe9331 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 }
970ed795 271 }
3abe9331 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;
970ed795 279 }
3abe9331 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;
970ed795
EL
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"
3abe9331 332 if (type_of_the_name != type_reference_name) {
970ed795 333 bool found = false;
3abe9331 334 for (QualifiedNames::iterator used = used_names.begin(); used; used = used->Next) {
970ed795
EL
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" ||
3abe9331 352 in == "choice_list") {
970ed795
EL
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();
3abe9331 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 + "'\"";
970ed795 376 }
3abe9331 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;
970ed795
EL
403 }
404 }
405}
406
3abe9331 407bool isBuiltInType(const Mstring& in) {
970ed795
EL
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",
3abe9331 414 "QName", "boolean", "anyType", "anySimpleType", NULL
970ed795
EL
415 };
416 const Mstring& name = in.getValueWithoutPrefix(':');
417 for (int i = 0; XSD_built_in_types[i]; ++i) {
3abe9331 418 if (name == XSD_built_in_types[i]) {
419 return true;
420 }
970ed795
EL
421 }
422 return false;
423}
424
3abe9331 425bool isStringType(const Mstring& in) {
970ed795
EL
426 static const char* string_types[] = {
427 "string", "normalizedString", "token", "Name", "NMTOKEN", "NCName", "ID", "IDREF", "ENTITY",
3abe9331 428 "hexBinary", "base64Binary", "anyURI", "language", NULL
970ed795
EL
429 };
430 const Mstring& name = in.getValueWithoutPrefix(':');
431 for (int i = 0; string_types[i]; ++i) {
3abe9331 432 if (name == string_types[i]) {
433 return true;
434 }
970ed795
EL
435 }
436 return false;
437}
438
3abe9331 439bool isIntegerType(const Mstring& in) {
970ed795
EL
440 static const char* integer_types[] = {
441 "integer", "positiveInteger", "nonPositiveInteger", "negativeInteger", "nonNegativeInteger", "long",
3abe9331 442 "unsignedLong", "int", "unsignedInt", "short", "unsignedShort", "byte", "unsignedByte", NULL
970ed795
EL
443 };
444 const Mstring& name = in.getValueWithoutPrefix(':');
445 for (int i = 0; integer_types[i]; ++i) {
3abe9331 446 if (name == integer_types[i]) {
447 return true;
448 }
970ed795
EL
449 }
450 return false;
451}
452
3abe9331 453bool isFloatType(const Mstring& in) {
970ed795
EL
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) {
3abe9331 459 if (name == float_types[i]) {
460 return true;
461 }
970ed795
EL
462 }
463 return false;
464}
465
3abe9331 466bool isTimeType(const Mstring& in) {
970ed795
EL
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) {
3abe9331 472 if (name == time_types[i]) {
473 return true;
474 }
970ed795
EL
475 }
476 return false;
477}
478
3abe9331 479bool isSequenceType(const Mstring& in) {
970ed795
EL
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) {
3abe9331 485 if (name == sequence_types[i]) {
486 return true;
487 }
970ed795
EL
488 }
489 return false;
490}
491
3abe9331 492bool isBooleanType(const Mstring& in) {
970ed795
EL
493 static const Mstring booltype("boolean");
494 return booltype == in.getValueWithoutPrefix(':');
495}
496
3abe9331 497bool isQNameType(const Mstring& in) {
970ed795
EL
498 static const Mstring qntype("QName");
499 return qntype == in.getValueWithoutPrefix(':');
500}
501
3abe9331 502bool isAnyType(const Mstring& in) {
970ed795
EL
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
3abe9331 513bool 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
563bool 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
577void printError(const Mstring& filename, int lineNumber, const Mstring& text) {
970ed795
EL
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
3abe9331 587void printError(const Mstring& filename, const Mstring& typeName, const Mstring& text) {
970ed795
EL
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
3abe9331 597void printWarning(const Mstring& filename, int lineNumber, const Mstring& text) {
970ed795
EL
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
3abe9331 608void printWarning(const Mstring& filename, const Mstring& typeName, const Mstring& text) {
970ed795
EL
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
3abe9331 619void indent(FILE* file, const int x) {
620 for (int l = 0; l < x; ++l) {
621 fprintf(file, "\t");
622 }
623}
624
625long double stringToLongDouble(const char *input) {
970ed795
EL
626 long double result = 0.0;
627 // `strtold()' is not available on older platforms.
628 sscanf(input, "%Lf", &result);
629 return result;
630}
631
3abe9331 632const 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;
970ed795 636 }
970ed795 637 }
3abe9331 638 return empty_string;
639}
640
641const 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
650const 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 }
970ed795
EL
659}
660
3abe9331 661RootType * lookup(const List<TTCN3Module*> mods, const SimpleType * reference, wanted w) {
970ed795
EL
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
3abe9331 668RootType * lookup(const List<TTCN3Module*> mods,
669 const Mstring& name, const Mstring& nsuri, const RootType *reference, wanted w) {
970ed795 670 RootType *ret = NULL;
3abe9331 671 for (List<TTCN3Module*>::iterator module = mods.begin(); module; module = module->Next) {
970ed795
EL
672 ret = lookup1(module->Data, name, nsuri, reference, w);
673 if (ret != NULL) break;
674 } // next doc
675
676 return ret;
677}
678
679RootType *lookup1(const TTCN3Module *module,
3abe9331 680 const Mstring& name, const Mstring& nsuri, const RootType *reference, wanted w) {
970ed795 681 if (nsuri != module->getTargetNamespace()) return NULL;
feade998 682
3abe9331 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 }
970ed795 693 }
3abe9331 694 break;
970ed795 695
3abe9331 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 }
970ed795 704 }
3abe9331 705 break;
970ed795 706
3abe9331 707 default:
708 break;
970ed795
EL
709 }
710 }
feade998 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 }
970ed795
EL
721 return NULL;
722}
723
724int multi(const TTCN3Module *module, ReferenceData const& outside_reference,
3abe9331 725 const RootType *obj) {
970ed795
EL
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
3abe9331 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 }
970ed795 739 }
970ed795
EL
740 return multiplicity;
741}
feade998 742
743void 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 );
d44e3c4f 794}
This page took 0.055785 seconds and 5 git commands to generate.