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