Sync with 5.4.0
[deliverable/titan.core.git] / core / ProfMerge_main.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
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <stdarg.h>
12 #include <getopt.h>
13 #include <string.h>
14 #include "ProfilerTools.hh"
15 #include "version_internal.h"
16
17 #ifdef LICENSE
18 #include "license.h"
19 #endif
20
21 /** the name of the executable */
22 const char* program_name;
23
24 /** error flag, set automatically when an error occurs */
25 boolean erroneous = FALSE;
26
27 /** prints usage information */
28 void usage()
29 {
30 fprintf(stderr,
31 "usage: %s [-pc] [-o file] [-s file] [-f filter] db_file1 [db_file2 ...]\n"
32 " or %s -v\n\n"
33 "options:\n"
34 " -p: discard profiling data\n"
35 " -c: discard code coverage data\n"
36 " -o file: write merged database into file\n"
37 " -s file: generate statistics file from merged database\n"
38 " -f filter: filter the generated statistics file (the filter is a hexadecimal number)\n"
39 " -v: show version\n", program_name, program_name);
40 }
41
42 /** displays an error message and sets the erroneous flag */
43 void error(const char *fmt, ...)
44 {
45 fprintf(stderr, "%s: error: ", program_name);
46 va_list parameters;
47 va_start(parameters, fmt);
48 vfprintf(stderr, fmt, parameters);
49 va_end(parameters);
50 putc('\n', stderr);
51 fflush(stderr);
52 erroneous = TRUE;
53 }
54
55 /** checks if the specified file exists */
56 boolean file_exists(const char* p_filename)
57 {
58 FILE* file = fopen(p_filename, "r");
59 if (NULL != file) {
60 fclose(file);
61 return TRUE;
62 }
63 return FALSE;
64 }
65
66
67 int main(int argc, char* argv[])
68 {
69 // store the executable name
70 program_name = argv[0];
71
72 // initialize variables for command line options
73 const char* out_file = NULL;
74 const char* stats_file = NULL;
75 boolean disable_profiler = FALSE;
76 boolean disable_coverage = FALSE;
77 unsigned int stats_flags = Profiler_Tools::STATS_ALL;
78 boolean has_stats_flag = FALSE;
79 boolean print_version = FALSE;
80
81 if (1 == argc) {
82 // no command line options
83 usage();
84 return EXIT_FAILURE;
85 }
86
87 for (;;) {
88 // read the next command line option (and its argument)
89 int c = getopt(argc, argv, "o:s:pcf:v");
90 if (-1 == c) {
91 break;
92 }
93 switch (c) {
94 case 'o': // output database file
95 out_file = optarg;
96 break;
97 case 's': // statistics file
98 stats_file = optarg;
99 break;
100 case 'p':
101 disable_profiler = TRUE;
102 break;
103 case 'c':
104 disable_coverage = TRUE;
105 break;
106 case 'f': { // statistics filter (hex number)
107 has_stats_flag = TRUE;
108 size_t len = strlen(optarg);
109 size_t start = 0;
110 if (len > STATS_MAX_HEX_DIGITS) {
111 // the rest of the bits are not needed, and stats_flags might run out of bits
112 start = len - STATS_MAX_HEX_DIGITS;
113 }
114 stats_flags = 0;
115 // extract the hex digits from the argument
116 for (size_t i = start; i < len; ++i) {
117 stats_flags *= 16;
118 if ('0' <= optarg[i] && '9' >= optarg[i]) {
119 stats_flags += optarg[i] - '0';
120 }
121 else if ('a' <= optarg[i] && 'f' >= optarg[i]) {
122 stats_flags += optarg[i] - 'a' + 10;
123 }
124 else if ('A' <= optarg[i] && 'F' >= optarg[i]) {
125 stats_flags += optarg[i] - 'A' + 10;
126 }
127 else {
128 error("Invalid statistics filter. Expected hexadecimal value.");
129 return EXIT_FAILURE;
130 }
131 }
132 break; }
133 case 'v':
134 print_version = TRUE;
135 break;
136 default:
137 usage();
138 return EXIT_FAILURE;
139 }
140 }
141
142 if (print_version) {
143 // no other flags are allowed when printing version info
144 if (disable_profiler || disable_coverage || has_stats_flag ||
145 NULL != out_file || NULL != stats_file) {
146 usage();
147 return EXIT_FAILURE;
148 }
149 else {
150 fputs("Profiler and Code Coverage Merge Tool for the TTCN-3 Test Executor\n"
151 "Product number: " PRODUCT_NUMBER "\n"
152 "Build date: " __DATE__ " " __TIME__ "\n"
153 "Compiled with: " C_COMPILER_VERSION "\n\n"
154 COPYRIGHT_STRING "\n\n", stderr);
155 #ifdef LICENSE
156 print_license_info();
157 #endif
158 return EXIT_SUCCESS;
159 }
160 }
161
162 if (optind == argc) {
163 error("No input files specified.");
164 usage();
165 return EXIT_FAILURE;
166 }
167
168 if (disable_profiler && disable_coverage) {
169 error("Both profiling and code coverage data are discarded, nothing to do.");
170 return EXIT_FAILURE;
171 }
172
173 if (NULL == out_file && NULL == stats_file) {
174 error("No output files specified (either the output database file or the "
175 "statistics file must be set).");
176 usage();
177 return EXIT_FAILURE;
178 }
179
180 if (has_stats_flag && NULL == stats_file) {
181 fprintf(stderr, "Notify: No statistics file specified, the statistics filter "
182 "will be ignored.");
183 }
184
185 // create the local database
186 Profiler_Tools::profiler_db_t profiler_db;
187
188 for (int i = optind; i < argc; i++) {
189 // import each input file's contents into the local database
190 fprintf(stderr, "Notify: Importing database file '%s'...\n", argv[i]);
191 Profiler_Tools::import_data(profiler_db, argv[i], FALSE, error);
192 if (erroneous) {
193 // an import failed -> exit
194 return EXIT_FAILURE;
195 }
196 }
197
198 boolean out_file_success = TRUE;
199 if (NULL != out_file) {
200 // print the local database into the output file
201 boolean update = file_exists(out_file);
202 Profiler_Tools::export_data(profiler_db, out_file, disable_profiler,
203 disable_coverage, error);
204 out_file_success = !erroneous;
205 if (out_file_success) {
206 fprintf(stderr, "Notify: Database file '%s' was %s.\n", out_file,
207 update ? "updated" : "generated");
208 }
209 }
210
211 boolean stats_file_success = TRUE;
212 if (NULL != stats_file) {
213 // reset the error flag, in case export_data failed
214 erroneous = FALSE;
215 // print the statistics into the designated file
216 boolean update = file_exists(stats_file);
217 Profiler_Tools::print_stats(profiler_db, stats_file, disable_profiler,
218 disable_coverage, stats_flags, error);
219 stats_file_success = !erroneous;
220 if (stats_file_success) {
221 fprintf(stderr, "Notify: Statistics file '%s' was %s.\n", stats_file,
222 update ? "updated" : "generated");
223 }
224 }
225
226 // return an error code if printing either output file failed
227 return (out_file_success && stats_file_success) ? EXIT_SUCCESS : EXIT_FAILURE;
228 }
229
230 // this is needed by version.h
231 reffer::reffer(const char*) {}
This page took 0.040306 seconds and 5 git commands to generate.