Titan Core Initial Contribution
[deliverable/titan.core.git] / xsdconvert / converter.cc
1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2014 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 "XMLParser.hh"
9 #include "TTCN3Module.hh"
10 #include "TTCN3ModuleInventory.hh"
11 #include "SimpleType.hh"
12 #include "ComplexType.hh"
13
14 #include "../common/version_internal.h"
15 #include "../common/license.h"
16
17 #include <unistd.h> // for using "getopt" function
18 #include <sys/stat.h>
19
20 bool c_flag_used = false;
21 int d_flag_used = 0;
22 bool e_flag_used = false;
23 bool f_flag_used = false;
24 bool p_flag_used = false;
25 bool s_flag_used = false;
26 bool t_flag_used = false;
27 bool q_flag_used = false;
28 bool w_flag_used = false;
29 bool x_flag_used = false;
30 bool z_flag_used = false;
31
32 static void printProductinfo();
33 static void printUsage(const char * argv0);
34 static void printVersion();
35 static void printErrorStatistics(unsigned int errors, unsigned int warnings);
36 static bool generatePredefinedModules();
37 static char **readModulesFromFile(const char *from_file, int *last_module);
38 static int checkSyntax(bool not_verbose, int first_module, int last_module,
39 const char * const * const module_names);
40 static int validate(int first_module, int last_module,
41 const char * const * const module_names);
42 static int generateCode(bool quiet, bool need_predefined,
43 int first_module, int last_module,
44 const char * const * const module_names);
45
46 int main(int argc, char **argv)
47 {
48 if (argc == 1) {
49 printProductinfo();
50 printUsage(argv[0]);
51 return EXIT_SUCCESS;
52 }
53
54 // The file holding a list of the XSD files.
55 const char *from_file = NULL;
56 char c;
57 opterr = 0;
58
59 while ((c = getopt(argc, argv, "cdef:pqstvwxz")) != -1)
60 {
61 switch(c)
62 {
63 case 'c':
64 c_flag_used = true;
65 break;
66 case 'd':
67 ++d_flag_used;
68 break;
69 case 'e':
70 e_flag_used = true;
71 break;
72 case 'f':
73 f_flag_used = true;
74 from_file = optarg;
75 break;
76 case 'p':
77 p_flag_used = true;
78 break;
79 case 's':
80 s_flag_used = true;
81 break;
82 case 't':
83 t_flag_used = true;
84 break;
85 case 'v':
86 printProductinfo();
87 printVersion();
88 #ifdef LICENSE
89 print_license_info();
90 #endif
91 return EXIT_SUCCESS;
92 case 'q':
93 q_flag_used = true;
94 break;
95 case 'w':
96 w_flag_used = true;
97 break;
98 case 'x':
99 x_flag_used = true;
100 break;
101 case 'z':
102 z_flag_used = true;
103 break;
104 default:
105 fprintf(stderr, "ERROR:\nInvalid option: -%c!\n", char(optopt));
106 printUsage(argv[0]);
107 return EXIT_FAILURE;
108 }
109 }
110
111 int first_module = f_flag_used ? 0 : optind,
112 last_module = f_flag_used ? 0 : argc;
113 char **module_names = f_flag_used ? NULL : argv;
114
115 if (f_flag_used) {
116 // Idea from CR_TR00015706.
117 module_names = readModulesFromFile(from_file, &last_module);
118 if (!module_names) {
119 fprintf(stderr, "ERROR: The file `%s' holding the XSD files cannot be "
120 "processed!\n", from_file);
121 goto error;
122 }
123 }
124
125 if (last_module - first_module <= 0) {
126 fprintf(stderr, "ERROR:\nNo module name was specified!\n");
127 printUsage(argv[0]);
128 goto error;
129 }
130
131 #ifdef LICENSE
132 {
133 init_openssl();
134 license_struct lstr;
135 load_license (&lstr);
136 int license_valid = verify_license(&lstr);
137 free_license (&lstr);
138 free_openssl();
139 if (!license_valid) {
140 exit(EXIT_FAILURE);
141 }
142 }
143 #endif
144
145 for (int i = first_module; i < last_module; ++i) {
146 if (!fopen(module_names[i], "r")) {
147 fprintf(stderr, "ERROR:\nInput file `%s' does not exist.\n",
148 module_names[i]);
149 goto error;
150 }
151 }
152
153 if (checkSyntax(q_flag_used, first_module, last_module, module_names) == EXIT_FAILURE)
154 goto error;
155
156 if (validate(first_module, last_module, module_names) == EXIT_FAILURE)
157 goto error;
158
159 if (s_flag_used) {
160 printErrorStatistics(XMLParser::getNumErrors(),
161 XMLParser::getNumWarnings());
162 if (XMLParser::getNumErrors() > 0)
163 goto error;
164 return EXIT_SUCCESS;
165 }
166
167 if (generateCode(q_flag_used, p_flag_used, first_module, last_module,
168 module_names) == EXIT_FAILURE)
169 goto error;
170
171 if (XMLParser::getNumWarnings() > 0 ||
172 TTCN3ModuleInventory::getNumErrors() > 0 ||
173 TTCN3ModuleInventory::getNumWarnings() > 0) {
174 printErrorStatistics(TTCN3ModuleInventory::getNumErrors(),
175 XMLParser::getNumWarnings() + TTCN3ModuleInventory::getNumWarnings());
176 }
177
178 return EXIT_SUCCESS;
179
180 error:
181 if (f_flag_used) {
182 for (int i = 0; i < last_module; ++i)
183 Free(module_names[i]);
184 Free(module_names);
185 }
186 return EXIT_FAILURE;
187 }
188
189 static void printProductinfo()
190 {
191 fputs("XSD to TTCN-3 Converter for the TTCN-3 Test Executor, version "
192 PRODUCT_NUMBER "\n", stderr);
193 }
194
195 static void printUsage(const char * argv0)
196 {
197 fprintf(stderr, "\n"
198 "usage: %s [-cepstVwx] [-f file] schema.xsd ...\n"
199 " or %s -v\n"
200 "\n"
201 "OPTIONS:\n"
202 " -c: disable the generation of comments in TTCN-3 modules\n"
203 " -e: disable the generation of encoding instructions in TTCN-3 modules\n"
204 " -f file: the names of XSD files are taken from file instead of the command line\n"
205 " -p: do not generate the UsefulTtcn3Types and XSD predefined modules\n"
206 " -q: quiet mode - disable the issue of status messages\n"
207 " -s: parse and validate only - no TTCN-3 module generation\n"
208 " -t: disable the generation of timing information in TTCN-3 modules\n"
209 " -v: show version information\n"
210 " -w: suppress warnings\n"
211 " -x: disable schema validation but generate TTCN-3 modules\n"
212 " -z: zap URI scheme from module name\n"
213 , argv0, argv0);
214 }
215
216 static void printVersion()
217 {
218 fputs("Product number: " PRODUCT_NUMBER "\n"
219 "Build date: " __DATE__ " " __TIME__ "\n"
220 "Compiled with: " C_COMPILER_VERSION "\n\n"
221 COPYRIGHT_STRING "\n\n", stderr);
222 }
223
224 static void printErrorStatistics(unsigned int errors, unsigned int warnings)
225 {
226 if (errors == 0) {
227 if (warnings == 0)
228 fprintf(stderr,
229 "Notify: No errors or warnings were detected.\n");
230 else
231 fprintf(stderr,
232 "Notify: No errors and %u warning%s were detected.\n",
233 warnings,
234 warnings > 1 ? "s" : "");
235 }
236 else {
237 if (warnings == 0)
238 fprintf(stderr,
239 "Notify: %u error%s and no warnings were detected.\n",
240 errors,
241 errors > 1 ? "s" : "");
242 else
243 fprintf(stderr,
244 "Notify: %u error%s and %u warning%s were detected.\n",
245 errors,
246 errors > 1 ? "s" : "",
247 warnings,
248 warnings > 1 ? "s" : "");
249 }
250 }
251
252 static bool generatePredefinedModules()
253 {
254 struct stat stFileInfo;
255 // FIXME: Regenerate only the missing file.
256 if (stat("UsefulTtcn3Types.ttcn", &stFileInfo) == 0 &&
257 stat("XSD.ttcn", &stFileInfo) == 0)
258 return true;
259
260 extern const char *moduleUsefulTtcn3Types;
261 extern const char *moduleXSD;
262
263 FILE *fileUsefulTtcn3Types = fopen("UsefulTtcn3Types.ttcn", "w");
264 FILE *fileXsd = fopen("XSD.ttcn", "w");
265
266 if (fileUsefulTtcn3Types == NULL) {
267 fprintf(stderr, "ERROR:\nCannot create file UsefulTtcn3Types.ttcn!\n");
268 return false;
269 }
270 if (fileXsd == NULL) {
271 fprintf(stderr, "ERROR:\nCannot create file XSD.ttcn!\n");
272 return false;
273 }
274
275 fprintf(fileUsefulTtcn3Types, "%s", moduleUsefulTtcn3Types);
276 fprintf(fileXsd, "%s", moduleXSD);
277
278 if (!q_flag_used) {
279 fprintf(stderr, "Notify: File \'UsefulTtcn3Types.ttcn\' was generated.\n");
280 fprintf(stderr, "Notify: File \'XSD.ttcn\' was generated.\n");
281 }
282
283 fclose(fileUsefulTtcn3Types);
284 fclose(fileXsd);
285
286 return true;
287 }
288
289 static char **readModulesFromFile(const char *from_file, int *last_module)
290 {
291 FILE *input = fopen(from_file, "r");
292 if (!input) return NULL;
293 // It should be a relatively small file.
294 fseek(input, 0, SEEK_END);
295 size_t input_bytes = ftell(input);
296 rewind(input);
297 size_t buf_len = input_bytes + 1; // sizeof(char)==1 by definition
298 char *buf = (char *)Malloc(buf_len);
299 buf[buf_len - 1] = 0;
300 size_t bytes_read = fread(buf, 1, input_bytes, input);
301 fclose(input);
302 if ((size_t)input_bytes != bytes_read) {
303 Free(buf);
304 return NULL;
305 }
306 char **ret_val = NULL;
307 *last_module = 0;
308 const char *delim = " \f\n\r\t\v";
309 char *name = strtok(buf, delim);
310 while (name) {
311 if (!strlen(name))
312 continue;
313 ret_val = (char **)Realloc(ret_val, sizeof(char *) * ++(*last_module));
314 ret_val[*last_module - 1] = mcopystr(name);
315 name = strtok(NULL, delim);
316 }
317 Free(buf);
318 return ret_val;
319 }
320
321 static int checkSyntax(bool not_verbose, int first_module, int last_module,
322 const char * const * const module_names)
323 {
324 if (!not_verbose)
325 fprintf(stderr, "Notify: Checking documents...\n");
326 for (int i = first_module; i < last_module; ++i) {
327 if (!not_verbose)
328 fprintf(stderr, "Notify: Parsing XML schema document `%s'...\n",
329 module_names[i]);
330 XMLParser syntaxchecker(module_names[i]);
331 syntaxchecker.checkSyntax();
332 }
333 if (XMLParser::getNumErrors() > 0) {
334 printErrorStatistics(XMLParser::getNumErrors(),
335 XMLParser::getNumWarnings());
336 return EXIT_FAILURE;
337 }
338 return EXIT_SUCCESS;
339 }
340
341 typedef List<QualifiedName> QualifiedNames;
342
343 static int generateCode(bool quiet, bool need_predefined,
344 int first_module, int last_module,
345 const char * const * const module_names)
346 {
347 TTCN3ModuleInventory& modules = TTCN3ModuleInventory::getInstance();
348 for (int i = first_module; i < last_module; ++i) {
349 XMLParser parser(module_names[i]);
350 TTCN3Module *module = modules.addModule(module_names[i], &parser);
351 parser.startConversion(module);
352 module->goodbyeParser(); // the parser is going away, don't use it
353 }
354
355 if (XMLParser::getNumErrors() > 0) {
356 printErrorStatistics(XMLParser::getNumErrors(),
357 XMLParser::getNumWarnings());
358 return EXIT_FAILURE;
359 }
360
361 if (d_flag_used > 1) {
362 modules.dump();
363 fputs("+++++++++++++++++++++++++++++\n", stderr);
364 }
365
366 modules.modulenameConversion();
367 modules.referenceResolving();
368 modules.nameConversion();
369 modules.finalModification();
370
371 if (d_flag_used > 0) modules.dump();
372
373 if (TTCN3ModuleInventory::getNumErrors() > 0) {
374 printErrorStatistics(TTCN3ModuleInventory::getNumErrors(),
375 XMLParser::getNumWarnings() + TTCN3ModuleInventory::getNumWarnings());
376 return EXIT_FAILURE;
377 }
378
379 if (!quiet)
380 fprintf(stderr, "Notify: Generating TTCN-3 modules...\n");
381
382 modules.moduleGeneration();
383
384 if (TTCN3ModuleInventory::getNumErrors() > 0) {
385 printErrorStatistics(TTCN3ModuleInventory::getNumErrors(),
386 XMLParser::getNumWarnings() + TTCN3ModuleInventory::getNumWarnings());
387 return EXIT_FAILURE;
388 }
389
390 if (!need_predefined)
391 if (!generatePredefinedModules())
392 return EXIT_FAILURE;
393 return EXIT_SUCCESS;
394 }
395
396 static int validate(int first_module, int last_module,
397 const char * const * const module_names)
398 {
399 for (int i = first_module; i < last_module; ++i) {
400 XMLParser validator(module_names[i]);
401 validator.validate();
402 }
403 if (XMLParser::getNumErrors() > 0) {
404 printErrorStatistics(XMLParser::getNumErrors(),
405 XMLParser::getNumWarnings());
406 return EXIT_FAILURE;
407 }
408 return EXIT_SUCCESS;
409 }
410
411 reffer::reffer(const char*) {}
This page took 0.038923 seconds and 6 git commands to generate.