Instead of null pass down the formal parameter list of the type.
[deliverable/titan.core.git] / compiler2 / makefile.c
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 *
10 * >
11 * Baji, Laszlo
12 * Balasko, Jeno
13 * Baranyi, Botond
14 * Beres, Szabolcs
15 * Delic, Adam
16 * Forstner, Matyas
17 * Koppany, Csaba
18 * Kovacs, Ferenc
19 * Kremer, Peter
20 * Lovassy, Arpad
21 * Pandi, Krisztian
22 * Raduly, Csaba
23 * Szabados, Kristof
24 * Szabo, Bence Janos
25 * Szabo, Janos Zoltan – initial implementation
26 * Szalay, Akos
27 * Zalanyi, Balazs Andor
28 * Pandi, Krisztian
29 *
30 ******************************************************************************/
970ed795
EL
31#include <stdio.h>
32#include <stdlib.h>
33#include <string.h>
34#include <stdarg.h>
35#include <unistd.h>
36#include <errno.h>
37#include <ctype.h>
38#if defined SOLARIS || defined SOLARIS8
af710487 39#include <sys/utsname.h>
970ed795
EL
40#endif
41
42#include "../common/memory.h"
43#include "../common/path.h"
44#include "../common/version_internal.h"
45#include "../common/userinfo.h"
46#include "ttcn3/ttcn3_preparser.h"
47#include "asn1/asn1_preparser.h"
48
49#ifdef LICENSE
50#include "../common/license.h"
51#endif
52
53#include "xpather.h"
54
55static const char *program_name = NULL;
56static unsigned int error_count = 0;
57static boolean suppress_warnings = FALSE;
af710487 58void free_string2_list(struct string2_list* act_elem);
59void free_string_list(struct string_list* act_elem);
970ed795
EL
60void ERROR(const char *fmt, ...)
61{
62 va_list parameters;
63 fprintf(stderr, "%s: error: ", program_name);
64 va_start(parameters, fmt);
65 vfprintf(stderr, fmt, parameters);
66 va_end(parameters);
67 fprintf(stderr, "\n");
68 fflush(stderr);
69 error_count++;
70}
71
72void WARNING(const char *fmt, ...)
73{
74 va_list parameters;
75 if (suppress_warnings) return;
76 fprintf(stderr, "%s: warning: ", program_name);
77 va_start(parameters, fmt);
78 vfprintf(stderr, fmt, parameters);
79 va_end(parameters);
80 putc('\n', stderr);
81 fflush(stderr);
82}
83
84void NOTIFY(const char *fmt, ...)
85{
86 va_list parameters;
87 va_start(parameters, fmt);
88 vfprintf(stderr, fmt, parameters);
89 va_end(parameters);
90 putc('\n', stderr);
91 fflush(stderr);
92}
93
94void DEBUG(unsigned level, const char *fmt, ...)
95{
96 va_list parameters;
97 fprintf(stderr, "%*s", 2 * level, "");
98 va_start(parameters, fmt);
99 vfprintf(stderr, fmt, parameters);
100 va_end(parameters);
101 putc('\n', stderr);
102 fflush(stderr);
103}
104
105void path_error(const char *fmt, ...)
106{
107 va_list ap;
108 char *err_msg;
109 va_start(ap, fmt);
110 err_msg = mprintf_va_list(fmt, ap);
111 va_end(ap);
112 ERROR("%s", err_msg);
113 Free(err_msg);
114}
115
116
117#if defined SOLARIS || defined SOLARIS8
118/** Automatic detection of Solaris version based on uname() system call.
119 * Distinguishing is needed because some socket functions use socklen_t
120 * (which is an alias for unsigned int) as length arguments on Solaris 8.
121 * On Solaris 2.6 the argument type is simply int and no socklen_t or other
122 * alias exists.
123 * Note: It was discovered later that Solaris 7 (which is used rarely within
124 * Ericsson) already uses socklen_t thus the SOLARIS8 platform identifier is a
125 * bit misleading. */
126static const char *get_platform_string(void)
127{
128 struct utsname name;
129 int major, minor;
130 if (uname(&name) < 0) {
131 WARNING("System call uname() failed: %s", strerror(errno));
132 errno = 0;
133 return "SOLARIS";
134 }
135 if (sscanf(name.release, "%d.%d", &major, &minor) == 2 && major == 5) {
136 if (minor <= 6) return "SOLARIS";
137 else return "SOLARIS8";
138 } else {
139 ERROR("Invalid OS release: %s", name.release);
140 return "SOLARIS";
141 }
142}
143#elif defined LINUX
144#define get_platform_string() "LINUX"
145#elif defined FREEBSD
146#define get_platform_string() "FREEBSD"
147#elif defined WIN32
148#define get_platform_string() "WIN32"
149#elif defined INTERIX
150#define get_platform_string() "INTERIX"
151#else
152#error Platform was not set.
153#endif
154
155/** structure for describing TTCN-3 and ASN.1 modules */
156struct module_struct {
157 char *dir_name; /* directory of the TTCN-3 or ASN.1 file, it is NULL if the
158 file is in the current working directory */
159 char *file_name; /* name of the TTCN-3 or ASN.1 file */
160 char *module_name; /* name of the TTCN-3 or ASN.1 module */
161 boolean is_regular; /* indicates whether the name of the source file follows
162 the default naming convention */
163};
164
165/** structure for describing test ports and other C/C++ modules */
166struct user_struct {
167 char *dir_name; /* directory of the C/C++ source files, it is NULL if the
168 files are in the current working directory */
169 char *file_prefix; /* the common prefix of the header and source file */
170 char *header_name; /* name of the C/C++ header file, which has .hh or .h or .hpp
171 suffix, it is NULL if there is no header file */
172 char *source_name; /* name of the C/C++ source file, which has .cc or .c or .cpp
173 suffix, it is NULL if there is no source file */
174 boolean has_hh_suffix; /* indicates whether the header file is present and
175 has .hh or .hpp suffix */
176 boolean has_cc_suffix; /* indicates whether the source file is present and
177 has .cc or .cpp suffix */
178};
179
180/** structure for directories that pre-compiled files are taken from */
181struct base_dir_struct {
182 const char *dir_name; /* name of the directory */
183 boolean has_modules; /* indicates whether there are TTCN-3/ASN.1 modules in
184 the directory (it is set to FALSE if dir_name
185 contains user C/C++ files only */
186};
187
188/** data structure that describes the information needed for the Makefile */
189struct makefile_struct {
af710487 190 char *project_name;
970ed795
EL
191 size_t nTTCN3Modules;
192 struct module_struct *TTCN3Modules;
193
194 boolean preprocess;
195 size_t nTTCN3PPModules;
196 struct module_struct *TTCN3PPModules;
197
198 boolean TTCN3ModulesRegular;
199 boolean BaseTTCN3ModulesRegular;
200 size_t nTTCN3IncludeFiles;
201 char **TTCN3IncludeFiles;
202
203 size_t nASN1Modules;
204 struct module_struct *ASN1Modules;
205 boolean ASN1ModulesRegular;
206 boolean BaseASN1ModulesRegular;
207
208 size_t nUserFiles;
209 struct user_struct *UserFiles;
210 boolean UserHeadersRegular;
211 boolean UserSourcesRegular;
212 boolean BaseUserHeadersRegular;
213 boolean BaseUserSourcesRegular;
214
215 size_t nOtherFiles;
216 char **OtherFiles;
217
218 boolean central_storage;
219 size_t nBaseDirs;
220 struct base_dir_struct *BaseDirs;
221 char *working_dir;
222 boolean gnu_make;
223 boolean single_mode;
224 char *output_file;
225 char *ets_name;
226 boolean force_overwrite;
227 boolean use_runtime_2;
228 boolean dynamic;
229 boolean gcc_dep;
230 char *code_splitting_mode;
231 boolean coverage;
232 char *tcov_file_name;
3abe9331 233 struct string_list* profiled_file_list; /* not owned */
970ed795 234 boolean library;
af710487 235 boolean linkingStrategy;
236 boolean hierarchical;
970ed795
EL
237 struct string_list* sub_project_dirs; /* not owned */
238 struct string_list* ttcn3_prep_includes; /* not owned */
239 struct string_list* ttcn3_prep_defines; /* not owned */
af710487 240 struct string_list* ttcn3_prep_undefines; /* not owned */
970ed795
EL
241 struct string_list* prep_includes; /* not owned */
242 struct string_list* prep_defines; /* not owned */
af710487 243 struct string_list* prep_undefines; /* not owned */
970ed795
EL
244 boolean codesplittpd;
245 boolean quietly;
246 boolean disablesubtypecheck;
247 const char *cxxcompiler;
248 const char *optlevel;
249 const char *optflags;
250 boolean disableber;
251 boolean disableraw;
252 boolean disabletext;
253 boolean disablexer;
254 boolean disablejson;
255 boolean forcexerinasn;
256 boolean defaultasomit;
257 boolean gccmsgformat;
258 boolean linenumbersonlymsg;
259 boolean includesourceinfo;
260 boolean addsourcelineinfo;
261 boolean suppresswarnings;
262 boolean outparamboundness;
3abe9331 263 boolean omit_in_value_list;
feade998 264 boolean warnings_for_bad_variants;
f08ff9ca 265 boolean activate_debugger;
feade998 266 boolean disable_predef_ext_folder;
970ed795
EL
267 struct string_list* solspeclibraries; /* not owned */
268 struct string_list* sol8speclibraries; /* not owned */
269 struct string_list* linuxspeclibraries; /* not owned */
270 struct string_list* freebsdspeclibraries; /* not owned */
271 struct string_list* win32speclibraries; /* not owned */
272 const char *ttcn3preprocessor;
273 struct string_list* linkerlibraries; /* not owned */
274 struct string_list* additionalObjects; /* not owned */
275 struct string_list* linkerlibsearchpath; /* not owned */
276 char* generatorCommandOutput; /* not owned */
277 struct string2_list* target_placement_list; /* not owned */
278};
279
280/** Initializes structure \a makefile with empty lists and default settings. */
281static void init_makefile_struct(struct makefile_struct *makefile)
282{
af710487 283 makefile->project_name = NULL;
970ed795
EL
284 makefile->nTTCN3Modules = 0;
285 makefile->TTCN3Modules = NULL;
286 makefile->preprocess = FALSE;
287 makefile->nTTCN3PPModules = 0;
288 makefile->TTCN3PPModules = NULL;
289 makefile->TTCN3ModulesRegular = TRUE;
290 makefile->BaseTTCN3ModulesRegular = TRUE;
291 makefile->nTTCN3IncludeFiles = 0;
292 makefile->TTCN3IncludeFiles = NULL;
293 makefile->nASN1Modules = 0;
294 makefile->ASN1Modules = NULL;
295 makefile->ASN1ModulesRegular = TRUE;
296 makefile->BaseASN1ModulesRegular = TRUE;
297 makefile->nUserFiles = 0;
298 makefile->UserFiles = NULL;
299 makefile->UserHeadersRegular = TRUE;
300 makefile->UserSourcesRegular = TRUE;
301 makefile->BaseUserHeadersRegular = TRUE;
302 makefile->BaseUserSourcesRegular = TRUE;
303 makefile->nOtherFiles = 0;
304 makefile->OtherFiles = NULL;
305 makefile->central_storage = FALSE;
306 makefile->nBaseDirs = 0;
307 makefile->BaseDirs = NULL;
308 makefile->working_dir = get_working_dir();
309 makefile->gnu_make = FALSE;
310 makefile->single_mode = FALSE;
311 makefile->ets_name = NULL;
312 makefile->output_file = NULL;
313 makefile->force_overwrite = FALSE;
314 makefile->use_runtime_2 = FALSE;
315 makefile->dynamic = FALSE;
316 makefile->gcc_dep = FALSE;
317 makefile->code_splitting_mode = NULL;
318 makefile->coverage = FALSE;
319 makefile->tcov_file_name = NULL;
3abe9331 320 makefile->profiled_file_list = NULL;
970ed795 321 makefile->library = FALSE;
af710487 322 makefile->linkingStrategy = FALSE;
323 makefile->hierarchical = FALSE;
970ed795
EL
324 makefile->sub_project_dirs = NULL;
325 makefile->ttcn3_prep_includes = NULL;
326 makefile->prep_includes = NULL;
327 makefile->prep_defines = NULL;
328 makefile->outparamboundness = FALSE;
3abe9331 329 makefile->omit_in_value_list = FALSE;
feade998 330 makefile->warnings_for_bad_variants = FALSE;
f08ff9ca 331 makefile->activate_debugger = FALSE;
970ed795
EL
332 makefile->solspeclibraries = NULL;
333 makefile->sol8speclibraries = NULL;
334 makefile->linuxspeclibraries = NULL;
335 makefile->freebsdspeclibraries = NULL;
336 makefile->win32speclibraries = NULL;
337 makefile->linkerlibraries = NULL;
338 makefile->additionalObjects = NULL;
339 makefile->linkerlibsearchpath = NULL;
340 makefile->generatorCommandOutput = NULL;
341 makefile->target_placement_list = NULL;
342}
343
344/** Deallocates all memory associated with structure \a makefile. */
345static void free_makefile_struct(const struct makefile_struct *makefile)
346{
af710487 347 Free(makefile->project_name);
970ed795
EL
348 size_t i;
349 for (i = 0; i < makefile->nTTCN3Modules; i++) {
350 Free(makefile->TTCN3Modules[i].dir_name);
351 Free(makefile->TTCN3Modules[i].file_name);
352 Free(makefile->TTCN3Modules[i].module_name);
353 }
354 Free(makefile->TTCN3Modules);
355 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
356 Free(makefile->TTCN3PPModules[i].dir_name);
357 Free(makefile->TTCN3PPModules[i].file_name);
358 Free(makefile->TTCN3PPModules[i].module_name);
359 }
360 Free(makefile->TTCN3PPModules);
361 for (i = 0; i < makefile->nTTCN3IncludeFiles; i++)
362 Free(makefile->TTCN3IncludeFiles[i]);
363 Free(makefile->TTCN3IncludeFiles);
364 for (i = 0; i < makefile->nASN1Modules; i++) {
365 Free(makefile->ASN1Modules[i].dir_name);
366 Free(makefile->ASN1Modules[i].file_name);
367 Free(makefile->ASN1Modules[i].module_name);
368 }
369 Free(makefile->ASN1Modules);
370 for (i = 0; i < makefile->nUserFiles; i++) {
371 Free(makefile->UserFiles[i].dir_name);
372 Free(makefile->UserFiles[i].file_prefix);
373 Free(makefile->UserFiles[i].header_name);
374 Free(makefile->UserFiles[i].source_name);
375 }
376 Free(makefile->UserFiles);
377 for (i = 0; i < makefile->nOtherFiles; i++) Free(makefile->OtherFiles[i]);
378 Free(makefile->OtherFiles);
379 Free(makefile->BaseDirs);
380 Free(makefile->working_dir);
381 Free(makefile->ets_name);
382 Free(makefile->output_file);
383 Free(makefile->code_splitting_mode);
384 Free(makefile->tcov_file_name);
385}
386
387/** Displays the contents of structure \a makefile as debug messages. */
388static void dump_makefile_struct(const struct makefile_struct *makefile,
389 unsigned level)
390{
391 size_t i;
392 DEBUG(level, "Data used for Makefile generation:");
af710487 393 DEBUG(level + 1, "TTCN-3 project name: %s", makefile->project_name);
970ed795
EL
394 DEBUG(level + 1, "TTCN-3 modules: (%u pcs.)", makefile->nTTCN3Modules);
395 for (i = 0; i < makefile->nTTCN3Modules; i++) {
396 const struct module_struct *module = makefile->TTCN3Modules + i;
397 DEBUG(level + 2, "Module name: %s", module->module_name);
398 if (module->dir_name != NULL)
399 DEBUG(level + 3, "Directory: %s", module->dir_name);
400 DEBUG(level + 3, "File name: %s", module->file_name);
401 DEBUG(level + 3, "Follows the naming convention: %s",
402 module->is_regular ? "yes" : "no");
403 }
404 DEBUG(level + 1, "TTCN-3 preprocessing: %s",
405 makefile->preprocess ? "yes" : "no");
406 if (makefile->preprocess) {
407 DEBUG(level + 1, "TTCN-3 modules to be preprocessed: (%u pcs.)",
408 makefile->nTTCN3PPModules);
409 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
410 const struct module_struct *module = makefile->TTCN3PPModules + i;
411 DEBUG(level + 2, "Module name: %s", module->module_name);
412 if (module->dir_name != NULL)
413 DEBUG(level + 3, "Directory: %s", module->dir_name);
414 DEBUG(level + 3, "File name: %s", module->file_name);
415 DEBUG(level + 3, "Follows the naming convention: %s",
416 module->is_regular ? "yes" : "no");
417 }
418 DEBUG(level + 1, "TTCN-3 include files: (%u pcs.)",
419 makefile->nTTCN3IncludeFiles);
420 for (i = 0; i < makefile->nTTCN3IncludeFiles; i++)
421 DEBUG(level + 2, "File name: %s", makefile->TTCN3IncludeFiles[i]);
422 }
423 DEBUG(level + 1, "All local TTCN-3 modules follow the naming convention: %s",
424 makefile->TTCN3ModulesRegular ? "yes" : "no");
425 if (makefile->central_storage) DEBUG(level + 1, "All TTCN-3 modules from other "
426 "directories follow the naming convention: %s",
427 makefile->BaseTTCN3ModulesRegular ? "yes" : "no");
428 DEBUG(level + 1, "ASN.1 modules: (%u pcs.)", makefile->nASN1Modules);
429 for (i = 0; i < makefile->nASN1Modules; i++) {
430 const struct module_struct *module = makefile->ASN1Modules + i;
431 DEBUG(level + 2, "Module name: %s", module->module_name);
432 if (module->dir_name != NULL)
433 DEBUG(level + 3, "Directory: %s", module->dir_name);
434 DEBUG(level + 3, "File name: %s", module->file_name);
435 DEBUG(level + 3, "Follows the naming convention: %s",
436 module->is_regular ? "yes" : "no");
437 }
438 DEBUG(level + 1, "All local ASN.1 modules follow the naming convention: %s",
439 makefile->ASN1ModulesRegular ? "yes" : "no");
440 if (makefile->central_storage) DEBUG(level + 1, "All ASN.1 modules from other "
441 "directories follow the naming convention: %s",
442 makefile->BaseASN1ModulesRegular ? "yes" : "no");
443 DEBUG(level + 1, "User C/C++ modules: (%u pcs.)", makefile->nUserFiles);
444 for (i = 0; i < makefile->nUserFiles; i++) {
445 const struct user_struct *user = makefile->UserFiles + i;
446 DEBUG(level + 2, "File prefix: %s", user->file_prefix);
447 if (user->dir_name != NULL)
448 DEBUG(level + 3, "Directory: %s", user->dir_name);
449 if (user->header_name != NULL) {
450 DEBUG(level + 3, "Header file: %s", user->header_name);
451 DEBUG(level + 3, "Header file has .hh or .hpp suffix: %s",
af710487 452 user->has_hh_suffix ? "yes" : "no");
970ed795
EL
453 }
454 if (user->source_name != NULL) {
455 DEBUG(level + 3, "Source file: %s", user->source_name);
456 DEBUG(level + 3, "Source file has .cc or .cpp suffix: %s",
af710487 457 user->has_cc_suffix ? "yes" : "no");
970ed795
EL
458 DEBUG(level + 3, "Object file: %s.o", user->file_prefix);
459 }
460 }
461 DEBUG(level + 1, "All local C/C++ header files follow the naming "
462 "convention: %s", makefile->UserHeadersRegular ? "yes" : "no");
463 DEBUG(level + 1, "All local C/C++ source files follow the naming "
464 "convention: %s", makefile->UserSourcesRegular ? "yes" : "no");
465 if (makefile->central_storage) {
466 DEBUG(level + 1, "All C/C++ header files from other directories follow the "
467 "naming convention: %s", makefile->BaseUserHeadersRegular ? "yes" : "no");
468 DEBUG(level + 1, "All C/C++ source files from other directories follow the "
469 "naming convention: %s", makefile->BaseUserSourcesRegular ? "yes" : "no");
470 }
471 DEBUG(level + 1, "Other files: (%u pcs.)", makefile->nOtherFiles);
472 for (i = 0; i < makefile->nOtherFiles; i++)
473 DEBUG(level + 2, "File name: %s", makefile->OtherFiles[i]);
474 DEBUG(level + 1, "Use pre-compiled files from central storage: %s",
475 makefile->central_storage ? "yes" : "no");
476 if (makefile->central_storage) {
477 DEBUG(level + 1, "Directories of pre-compiled files: (%u pcs.)",
478 makefile->nBaseDirs);
479 for (i = 0; i < makefile->nBaseDirs; i++) {
480 const struct base_dir_struct *base_dir = makefile->BaseDirs + i;
481 DEBUG(level + 2, "Directory: %s", base_dir->dir_name);
482 DEBUG(level + 3, "Has TTCN-3/ASN.1 modules: %s",
af710487 483 base_dir->has_modules ? "yes" : "no");
970ed795
EL
484 }
485 }
486 DEBUG(level + 1, "Working directory: %s",
487 makefile->working_dir != NULL ? makefile->working_dir : "<unknown>");
488 DEBUG(level + 1, "GNU make: %s", makefile->gnu_make ? "yes" : "no");
489 DEBUG(level + 1, "Execution mode: %s",
490 makefile->single_mode ? "single" : "parallel");
491 DEBUG(level + 1, "Name of executable: %s",
492 makefile->ets_name != NULL ? makefile->ets_name : "<unknown>");
493 DEBUG(level + 1, "Output file: %s",
494 makefile->output_file != NULL ? makefile->output_file : "<unknown>");
495 DEBUG(level + 1, "Force overwrite: %s",
496 makefile->force_overwrite ? "yes" : "no");
497 DEBUG(level + 1, "Use function test runtime: %s",
498 makefile->use_runtime_2 ? "yes" : "no");
499 DEBUG(level + 1, "Use dynamic linking: %s",
500 makefile->dynamic ? "yes" : "no");
501 DEBUG(level + 1, "Code splitting mode: %s",
502 makefile->code_splitting_mode != NULL ?
503 makefile->code_splitting_mode : "<unknown>");
504 DEBUG(level + 1, "Code coverage file: %s",
505 makefile->tcov_file_name != NULL ?
506 makefile->tcov_file_name : "<unknown>");
3abe9331 507 if (makefile->profiled_file_list) {
508 char* lists = mcopystr(makefile->profiled_file_list->str);
509 struct string_list* iter = makefile->profiled_file_list->next;
510 while(iter != NULL) {
511 lists = mputprintf(lists, " %s", iter->str);
512 iter = iter->next;
513 }
514 DEBUG(level + 1, "Profiled file list(s): %s", lists);
515 Free(lists);
516 }
970ed795
EL
517#ifdef COVERAGE_BUILD
518 DEBUG(level + 1, "Enable coverage: %s", makefile->coverage ? "yes" : "no");
519#endif
520}
521
522/** Returns the name of an existing file that is related to command line
523 * argument \a argument. Tries the given list of suffixes. NULL pointer is
524 * returned if no file was found. The returned string shall be deallocated
525 * by the caller. */
526static char *get_file_name_for_argument(const char *argument)
527{
528 static const char * const suffix_list[] = {
529 "", ".ttcnpp", ".ttcnin", ".ttcn", ".ttcn3", ".3mp", ".asn", ".asn1",
530 ".cc", ".c", ".cpp", ".hh", ".h",".hpp", ".cfg", ".prj", NULL
531 };
532 const char * const *suffix_ptr;
533 for (suffix_ptr = suffix_list; *suffix_ptr != NULL; suffix_ptr++) {
534 char *file_name = mputstr(mcopystr(argument), *suffix_ptr);
535 if (get_path_status(file_name) == PS_FILE) return file_name;
536 Free(file_name);
537 }
538 return NULL;
539}
540
541/** Converts \a path_name to an absolute directory using \a working_dir.
542 * NULL pointer is returned if \a path_name does not contain a directory or
543 * the resulting absolute directory is identical to \a working_dir.
544 * The returned string shall be deallocated by the caller. */
545static char *get_dir_name(const char *path_name, const char *working_dir)
546{
547 char *dir_name = get_dir_from_path(path_name);
548 if (dir_name != NULL) {
feade998 549 char *absolute_dir = get_absolute_dir(dir_name, working_dir, TRUE);
970ed795
EL
550 Free(dir_name);
551 if (absolute_dir == NULL || working_dir == NULL) {
552 /* an error occurred */
553 return NULL;
554 } else if (!strcmp(absolute_dir, working_dir)) {
555 /* the directory is identical to the working dir */
556 Free(absolute_dir);
557 return NULL;
558 } else return absolute_dir;
559 } else return NULL;
560}
561
562/** Returns whether \a dirname1 and \a dirname2 contain the same (canonized
563 * absolute) directories. NULL pointer is handled in a special way: it is
564 * identical only to itself. */
565static boolean is_same_directory(const char *dirname1, const char *dirname2)
566{
567 if (dirname1 == NULL) {
568 if (dirname2 == NULL) return TRUE;
569 else return FALSE;
570 } else {
571 if (dirname2 == NULL) return FALSE;
572 else if (strcmp(dirname1, dirname2)) return FALSE;
573 else return TRUE;
574 }
575}
576
577/** Returns whether the file \a filename1 in directory \a dirname1 is identical
578 * to file \a filename2 in directory \a dirname2. Only the directory names can
579 * be NULL. */
580static boolean is_same_file(const char *dirname1, const char *filename1,
581 const char *dirname2, const char *filename2)
582{
583 /* first examine the file names for efficiency reasons */
584 if (strcmp(filename1, filename2)) return FALSE;
585 else return is_same_directory(dirname1, dirname2);
586}
587
588/** Determines whether the TTCN-3 or ASN.1 module identifiers \a module1 and
589 * \a module2 are the same. Characters '-' and '_' in module names are not
590 * distinguished. */
591static boolean is_same_module(const char *module1, const char *module2)
592{
593 size_t i;
594 for (i = 0; ; i++) {
595 switch (module1[i]) {
596 case '\0':
597 if (module2[i] == '\0') return TRUE;
598 else return FALSE;
599 case '-':
600 case '_':
601 if (module2[i] != '-' && module2[i] != '_') return FALSE;
602 break;
603 default:
604 if (module1[i] != module2[i]) return FALSE;
605 break;
606 }
607 }
608 return FALSE; /* to avoid warnings */
609}
610
611/** Determines the suffix (i.e. the character sequence following the last dot)
612 * of file or path name \a file_name. NULL pointer is returned if \a file_name
613 * does not contain any dot character or the last character of it is a dot.
614 * The suffix is not copied, the returned pointer points to the tail of
615 * \a file_name. */
616static const char *get_suffix(const char *file_name)
617{
618 size_t last_dot = (size_t)-1;
619 size_t i;
620 for (i = 0; file_name[i] != '\0'; i++)
621 if (file_name[i] == '.') last_dot = i;
622 if (last_dot == (size_t)-1 || file_name[last_dot + 1] == '\0') return NULL;
623 else return file_name + last_dot + 1;
624}
625
626/** Truncates the suffix (i.e. the last dot and the characters following it)
627 * from \a file_name and returns a copy of the prefix of \a file_name.
628 * If \a file_name does not have a suffix an exact copy of it is returned.
629 * The returned string shall be deallocated by the caller. */
630static char *cut_suffix(const char *file_name)
631{
632 char *ret_val;
633 size_t last_dot = (size_t)-1;
634 size_t i;
635 for (i = 0; file_name[i] != '\0'; i++)
636 if (file_name[i] == '.') last_dot = i;
637 ret_val = mcopystr(file_name);
638 if (last_dot != (size_t)-1) ret_val = mtruncstr(ret_val, last_dot);
639 return ret_val;
640}
641
642/** Determines the name of the preprocessed file from \a file_name.
643 * It is assumed that \a file_name has ttcnpp suffix.
644 * The returned string shall be deallocated by the caller. */
645static char *get_preprocessed_file_name(const char *file_name)
646{
647 char *ret_val = cut_suffix(file_name);
648 ret_val = mputstr(ret_val, ".ttcn");
649 return ret_val;
650}
651
652/** Check if any of the preprocessed ttcn file names with the preprocessed
653 * (TTCN-3) suffix is equal to any other file given in the \a makefile */
654static void check_preprocessed_filename_collision(
655 struct makefile_struct *makefile)
656{
657 size_t i;
658 if (makefile->nTTCN3PPModules == 0) {
659 WARNING("TTCN-3 preprocessing (option `-p') is enabled, but no TTCN-3 "
660 "files to be preprocessed were given for the Makefile.");
661 }
662 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
663 const struct module_struct *pp_module = makefile->TTCN3PPModules + i;
664 /* name of the intermediate preprocessed file */
665 char *preprocessed_name = get_preprocessed_file_name(pp_module->file_name);
666 size_t j;
667 for (j = 0; j < makefile->nTTCN3Modules; j++) {
668 struct module_struct *module = makefile->TTCN3Modules + j;
669 if (is_same_file(pp_module->dir_name, preprocessed_name,
670 module->dir_name, module->file_name)) {
671 if (is_same_module(pp_module->module_name, module->module_name)) {
672 /* same file with the same module */
673 char *pp_pathname = compose_path_name(pp_module->dir_name,
674 pp_module->file_name);
675 char *m_pathname = compose_path_name(module->dir_name,
676 module->file_name);
677 WARNING("File `%s' containing TTCN-3 module `%s' is generated by "
678 "the preprocessor from `%s'. Removing the file from the list of "
679 "normal TTCN-3 modules.", m_pathname, module->module_name,
680 pp_pathname);
681 Free(pp_pathname);
682 Free(m_pathname);
683 Free(module->dir_name);
684 Free(module->file_name);
685 Free(module->module_name);
686 makefile->nTTCN3Modules--;
687 memmove(module, module + 1, (makefile->nTTCN3Modules - j) *
688 sizeof(*makefile->TTCN3Modules));
689 makefile->TTCN3Modules =
690 (struct module_struct*)Realloc(makefile->TTCN3Modules,
691 makefile->nTTCN3Modules * sizeof(*makefile->TTCN3Modules));
692 } else {
693 /* same file with different module */
694 char *pp_pathname = compose_path_name(pp_module->dir_name,
695 pp_module->file_name);
696 char *m_pathname = compose_path_name(module->dir_name,
697 module->file_name);
698 ERROR("Preprocessed intermediate file of `%s' (module `%s') clashes "
699 "with file `%s' containing TTCN-3 module `%s'.", pp_pathname,
700 pp_module->module_name, m_pathname, module->module_name);
701 Free(pp_pathname);
702 Free(m_pathname);
703 }
704 } else if (is_same_module(pp_module->module_name, module->module_name)) {
705 /* different file with the same module */
706 char *pp_pathname = compose_path_name(pp_module->dir_name,
707 pp_module->file_name);
708 char *m_pathname = compose_path_name(module->dir_name,
709 module->file_name);
710 ERROR("Both files `%s' and `%s' contain TTCN-3 module `%s'.",
711 pp_pathname, m_pathname, pp_module->module_name);
712 Free(pp_pathname);
713 Free(m_pathname);
714 }
715 }
716 for (j = 0; j < makefile->nASN1Modules; j++) {
717 struct module_struct *module = makefile->ASN1Modules + j;
718 if (is_same_file(pp_module->dir_name, preprocessed_name,
719 module->dir_name, module->file_name)) {
720 char *pp_pathname = compose_path_name(pp_module->dir_name,
721 pp_module->file_name);
722 char *m_pathname = compose_path_name(module->dir_name,
723 module->file_name);
724 ERROR("Preprocessed intermediate file of `%s' (module `%s') clashes "
725 "with file `%s' containing ASN.1 module `%s'.", pp_pathname,
726 pp_module->module_name, m_pathname, module->module_name);
727 Free(pp_pathname);
728 Free(m_pathname);
729 }
730 }
731 for (j = 0; j < makefile->nOtherFiles; j++) {
732 char *dir_name = get_dir_name(makefile->OtherFiles[j],
733 makefile->working_dir);
734 char *file_name = get_file_from_path(makefile->OtherFiles[j]);
735 if (is_same_file(pp_module->dir_name, preprocessed_name, dir_name,
736 file_name)) {
737 char *pp_pathname = compose_path_name(pp_module->dir_name,
738 pp_module->file_name);
739 ERROR("Preprocessed intermediate file of `%s' (module `%s') clashes "
740 "with other file `%s'.", pp_pathname, pp_module->module_name,
741 makefile->OtherFiles[j]);
742 Free(pp_pathname);
743 }
744 Free(dir_name);
745 Free(file_name);
746 }
747 Free(preprocessed_name);
748 }
749}
750
751/** Checks the name clash between existing module \a module and newly added
752 * module with parameters \a path_name, \a dir_name, \a file_name,
753 * \a module_name. Both the existing and the new module shall be of the same
754 * kind, parameter \a kind shall contain the respective string (either "ASN.1"
755 * or "TTCN-3"). If a clash is found the parameters of the new module except
756 * \a path_name are deallocated and TRUE is returned. Otherwise FALSE is
757 * returned. */
758static boolean check_module_clash_same(const struct module_struct *module,
759 const char *kind, const char *path_name, char *dir_name, char *file_name,
760 char *module_name)
761{
762 if (is_same_module(module_name, module->module_name)) {
763 if (is_same_file(dir_name, file_name,
764 module->dir_name, module->file_name)) {
765 /* the same file was given twice: just issue a warning */
766 WARNING("File `%s' was given more than once for the Makefile.",
767 path_name);
768 } else {
769 /* two different files contain the same module: this cannot be
770 * resolved as the generated C++ files will clash */
771 char *path_name1 = compose_path_name(module->dir_name,
772 module->file_name);
773 char *path_name2 = compose_path_name(dir_name, file_name);
774 ERROR("Both files `%s' and `%s' contain %s module `%s'.",
775 path_name1, path_name2, kind, module_name);
776 Free(path_name1);
777 Free(path_name2);
778 }
779 Free(file_name);
780 Free(dir_name);
781 Free(module_name);
782 return TRUE;
783 } else return FALSE;
784}
785
786/** Checks the name clash between existing module \a module and newly added
787 * module with parameters \a dir_name, \a file_name, \a module_name. The two
788 * modules shall be of different kinds (one is ASN.1, the other is TTCN-3).
789 * Parameters \a kind1 and \a kind2 shall contain the respective strings. If a
790 * clash is found the parameters of the new module are deallocated and TRUE is
791 * returned. Otherwise FALSE is returned. */
792static boolean check_module_clash_different(const struct module_struct *module,
793 const char *kind1, char *dir_name, char *file_name, char *module_name,
794 const char *kind2)
795{
796 if (is_same_module(module_name, module->module_name)) {
797 /* two different files contain the same module: this cannot be resolved
798 * as the generated C++ files will clash */
799 char *path_name1 = compose_path_name(module->dir_name, module->file_name);
800 char *path_name2 = compose_path_name(dir_name, file_name);
801 ERROR("File `%s' containing %s module `%s' and file `%s' containing "
802 "%s module `%s' cannot be used together in the same Makefile.",
803 path_name1, kind1, module->module_name, path_name2, kind2, module_name);
804 Free(path_name1);
805 Free(path_name2);
806 Free(file_name);
807 Free(dir_name);
808 Free(module_name);
809 return TRUE;
810 } else return FALSE;
811}
812
813/** Adds a TTCN-3 module to Makefile descriptor structure \a makefile.
814 * The name of the TTCN-3 source file is \a path_name, the module identifier
815 * is \a module_name. It is checked whether a file or module with the same name
816 * already exists in \a makefile and an appropriate warning or error is
817 * reported. */
818static void add_ttcn3_module(struct makefile_struct *makefile,
819 const char *path_name, char *module_name)
820{
821 struct module_struct *module;
822 char *dir_name = get_dir_name(path_name, makefile->working_dir);
823 char *file_name = get_file_from_path(path_name);
824 const char *suffix = get_suffix(file_name);
825 size_t i;
826 boolean is_preprocessed = FALSE;
827
828 if (suffix != NULL) {
829 if (!strcmp(suffix, "ttcnpp")) {
830 if (makefile->preprocess) is_preprocessed = TRUE;
831 else WARNING("The suffix of TTCN-3 file `%s' indicates that it should be "
832 "preprocessed, but TTCN-3 preprocessing is not enabled. The file "
833 "will be added to the list of normal TTCN-3 modules in the Makefile.",
834 path_name);
835 } else if (!strcmp(suffix, "ttcnin")) {
836 WARNING("The suffix of file `%s' indicates that it should be a "
837 "preprocessor include file, but it contains a TTCN-3 module named `%s'. "
838 "The file will be added to the list of normal TTCN-3 modules in the "
839 "Makefile.", path_name, module_name);
840 }
841 }
842
843 for (i = 0; i < makefile->nASN1Modules; i++) {
844 if (check_module_clash_different(makefile->ASN1Modules + i, "ASN.1",
845 dir_name, file_name, module_name, "TTCN-3")) return;
846 }
847 /* never entered if suffix is NULL */
848 if (is_preprocessed) {
849 char *file_prefix;
850 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
851 if (check_module_clash_same(makefile->TTCN3PPModules + i, "TTCN-3",
852 path_name, dir_name, file_name, module_name)) return;
853 }
854 /* clashes with normal TTCN-3 modules will be checked (and maybe resolved)
855 * in \a check_preprocessed_filename_collision() */
856 /* add it to the list of TTCN-3 modules to be preprocessed */
857 makefile->TTCN3PPModules = (struct module_struct*)
858 Realloc(makefile->TTCN3PPModules,
859 (makefile->nTTCN3PPModules + 1) * sizeof(*makefile->TTCN3PPModules));
860 module = makefile->TTCN3PPModules + makefile->nTTCN3PPModules;
861 makefile->nTTCN3PPModules++;
862 module->dir_name = dir_name;
863 module->file_name = file_name;
864 module->module_name = module_name;
865 file_prefix = cut_suffix(file_name);
866 if (!strcmp(file_prefix, module_name)) module->is_regular = TRUE;
867 else module->is_regular = FALSE;
868 Free(file_prefix);
869 } else {
870 /* the file is not preprocessed */
871 for (i = 0; i < makefile->nTTCN3Modules; i++) {
872 if (check_module_clash_same(makefile->TTCN3Modules + i, "TTCN-3",
873 path_name, dir_name, file_name, module_name)) return;
874 }
875 /* clashes with preprocessed TTCN-3 modules will be checked (and maybe
876 * resolved) in \a check_preprocessed_filename_collision() */
877 /* add it to the list of normal TTCN-3 modules */
878 makefile->TTCN3Modules = (struct module_struct*)
879 Realloc(makefile->TTCN3Modules,
880 (makefile->nTTCN3Modules + 1) * sizeof(*makefile->TTCN3Modules));
881 module = makefile->TTCN3Modules + makefile->nTTCN3Modules;
882 makefile->nTTCN3Modules++;
883 module->dir_name = dir_name;
884 module->file_name = file_name;
885 module->module_name = module_name;
886 if (suffix != NULL && !strcmp(suffix, "ttcn")) {
887 char *file_prefix = cut_suffix(file_name);
888 if (!strcmp(file_prefix, module_name)) module->is_regular = TRUE;
889 else module->is_regular = FALSE;
890 Free(file_prefix);
891 } else {
892 module->is_regular = FALSE;
893 }
894 }
895}
896
897/** ASN.1 filename shall contain no hyphen */
898static boolean is_valid_asn1_filename(const char* file_name)
899{
900 if (0 == strchr(file_name, '-')) {
901 return TRUE;
902 }
903 return FALSE;
904}
905
906/** Adds an ASN.1 module to Makefile descriptor structure \a makefile.
907 * The name of the ASN.1 source file is \a path_name, the module identifier
908 * is \a module_name. It is checked whether a file or module with the same name
909 * already exists in \a makefile and an appropriate warning or error is
910 * reported. */
911static void add_asn1_module(struct makefile_struct *makefile,
912 const char *path_name, char *module_name)
913{
914 struct module_struct *module;
915 char *dir_name = get_dir_name(path_name, makefile->working_dir);
916 char *file_name = get_file_from_path(path_name);
917 const char *suffix = get_suffix(file_name);
918 size_t i;
919 for (i = 0; i < makefile->nASN1Modules; i++) {
920 if (check_module_clash_same(makefile->ASN1Modules + i, "ASN.1", path_name,
921 dir_name, file_name, module_name)) return;
922 }
923 for (i = 0; i < makefile->nTTCN3Modules; i++) {
924 if (check_module_clash_different(makefile->TTCN3Modules + i, "TTCN-3",
925 dir_name, file_name, module_name, "ASN.1")) return;
926 }
927 if (makefile->preprocess) {
928 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
929 if (check_module_clash_different(makefile->TTCN3PPModules + i, "TTCN-3",
930 dir_name, file_name, module_name, "ASN.1")) return;
931 }
932 }
933 makefile->ASN1Modules = (struct module_struct*)
934 Realloc(makefile->ASN1Modules,
935 (makefile->nASN1Modules + 1) * sizeof(*makefile->ASN1Modules));
936 module = makefile->ASN1Modules + makefile->nASN1Modules;
937 makefile->nASN1Modules++;
938 module->dir_name = dir_name;
939 module->file_name = file_name;
940 module->module_name = module_name;
941 if (suffix != NULL && !strcmp(suffix, "asn")) {
942 char *file_prefix = cut_suffix(file_name);
943 /* replace all '_' with '-' in file name prefix */
944 for (i = 0; file_prefix[i] != '\0'; i++)
945 if (file_prefix[i] == '_') file_prefix[i] = '-';
946 if (!strcmp(file_prefix, module_name)) module->is_regular = TRUE;
947 else module->is_regular = FALSE;
948 Free(file_prefix);
949 } else {
950 module->is_regular = FALSE;
951 }
952}
953
954/** Adds the file named \a path_name to the list of files pointed by \a list_ptr
955 * and \a list_size. The suffix or contents of \a path_name are not examined,
956 * only duplicate entries are checked. In case of duplicate entries warning is
957 * reported only if argument \a report_warning is set to TRUE. */
958static void add_path_to_list(size_t *list_size, char ***list_ptr,
959 const char *path_name, const char *working_dir, boolean report_warning)
960{
961 size_t i;
962 char *dir_name = get_dir_name(path_name, working_dir);
963 char *file_name = get_file_from_path(path_name);
964 char *canonized_path_name = compose_path_name(dir_name, file_name);
965 Free(dir_name);
966 Free(file_name);
967 for (i = 0; i < *list_size; i++) {
968 if (!strcmp(canonized_path_name, (*list_ptr)[i])) {
969 if (report_warning) WARNING("File `%s' was given more than once for the "
af710487 970 "Makefile.", path_name);
970ed795
EL
971 Free(canonized_path_name);
972 return;
973 }
974 }
975 *list_ptr = (char**)Realloc(*list_ptr, (*list_size + 1) * sizeof(**list_ptr));
976 (*list_ptr)[*list_size] = canonized_path_name;
977 (*list_size)++;
978}
979
980/** Adds a C/C++ header or source file or an other file named \a path_name to
981 * Makefile descriptor structure \a makefile. The file is classified based on
982 * its suffix and not by content. If the file clashes with existing files or
983 * modules the appropriate warning or error is generated. */
984static void add_user_file(struct makefile_struct *makefile,
985 const char *path_name)
986{
987 const char *suffix = get_suffix(path_name);
988 if (suffix != NULL) {
989 if (!strcmp(suffix, "ttcn") || !strcmp(suffix, "ttcn3") ||
af710487 990 !strcmp(suffix, "3mp") || !strcmp(suffix, "ttcnpp")) {
970ed795
EL
991 /* The file content was already checked. Since it doesn't look like
992 * a valid TTCN-3 file, these suffixes are suspect */
993 WARNING("File `%s' does not contain a valid TTCN-3 module. "
af710487 994 "It will be added to the Makefile as other file.", path_name);
995 }
996 else if (!strcmp(suffix, "ttcnin")) {
970ed795
EL
997 /* this is a TTCN-3 include file */
998 if (makefile->preprocess) {
af710487 999 add_path_to_list(&makefile->nTTCN3IncludeFiles,
1000 &makefile->TTCN3IncludeFiles, path_name, makefile->working_dir, TRUE);
1001 return;
1002 }
1003 else {
1004 WARNING("The suffix of file `%s' indicates that it is a TTCN-3 "
1005 "include file, but TTCN-3 preprocessing is not enabled. The file "
1006 "will be added to the Makefile as other file.", path_name);
970ed795 1007 }
af710487 1008 }
1009 else if (!strcmp(suffix, "asn") || !strcmp(suffix, "asn1")) {
970ed795
EL
1010 /* The file content was already checked. Since it doesn't look like
1011 * a valid ASN.1 file, these suffixes are suspect */
1012 WARNING("File `%s' does not contain a valid ASN.1 module. "
af710487 1013 "It will be added to the Makefile as other file.", path_name);
1014 }
1015 else if (!strcmp(suffix, "cc") || !strcmp(suffix, "c") || !strcmp(suffix, "cpp")) {
970ed795
EL
1016 /* this is a source file */
1017 char *dir_name = get_dir_name(path_name, makefile->working_dir);
1018 char *file_name = get_file_from_path(path_name);
1019 char *file_prefix = cut_suffix(file_name);
1020 struct user_struct *user;
1021 size_t i;
1022 for (i = 0; i < makefile->nUserFiles; i++) {
af710487 1023 user = makefile->UserFiles + i;
1024 if (!strcmp(file_prefix, user->file_prefix)) {
1025 if (user->source_name != NULL) {
1026 /* the source file is already present */
1027 if (is_same_file(dir_name, file_name,
1028 user->dir_name, user->source_name)) {
1029 WARNING("File `%s' was given more than once for the Makefile.", path_name);
1030 }
1031 else {
1032 char *path_name1 = compose_path_name(user->dir_name, user->source_name);
1033 char *path_name2 = compose_path_name(dir_name, file_name);
1034 ERROR("C/C++ source files `%s' and `%s' cannot be used together "
1035 "in the same Makefile.", path_name1, path_name2);
1036 Free(path_name1);
1037 Free(path_name2);
1038 }
1039 }
1040 else {
1041 /* a header file with the same prefix is already present */
1042 if (is_same_directory(dir_name, user->dir_name)) {
1043 user->source_name = file_name;
1044 file_name = NULL;
1045 if (!strcmp(suffix, "cc") || !strcmp(suffix, "cpp"))
1046 user->has_cc_suffix = TRUE;
1047 }
1048 else {
1049 char *path_name1 = compose_path_name(dir_name, file_name);
1050 char *path_name2 = compose_path_name(user->dir_name, user->header_name);
1051 ERROR("C/C++ source file `%s' cannot be used together with "
1052 "header file `%s' in the same Makefile.", path_name1,
1053 path_name2);
1054 Free(path_name1);
1055 Free(path_name2);
1056 }
1057 }
1058 Free(dir_name);
1059 Free(file_name);
1060 Free(file_prefix);
1061 return;
1062 }
970ed795
EL
1063 }
1064 makefile->UserFiles = (struct user_struct*)Realloc(makefile->UserFiles,
af710487 1065 (makefile->nUserFiles + 1) * sizeof(*makefile->UserFiles));
970ed795
EL
1066 user = makefile->UserFiles + makefile->nUserFiles;
1067 makefile->nUserFiles++;
1068 user->dir_name = dir_name;
1069 user->file_prefix = file_prefix;
1070 user->header_name = NULL;
1071 user->source_name = file_name;
1072 user->has_hh_suffix = FALSE;
1073 if (!strcmp(suffix, "cc") || !strcmp(suffix, "cpp")) user->has_cc_suffix = TRUE;
1074 else user->has_cc_suffix = FALSE;
1075 return;
af710487 1076 }
1077 else if (!strcmp(suffix, "hh") || !strcmp(suffix, "h")) {
970ed795
EL
1078 /* this is a header file */
1079 char *dir_name = get_dir_name(path_name, makefile->working_dir);
1080 char *file_name = get_file_from_path(path_name);
1081 char *file_prefix = cut_suffix(file_name);
1082 struct user_struct *user;
1083 size_t i;
1084 for (i = 0; i < makefile->nUserFiles; i++) {
af710487 1085 user = makefile->UserFiles + i;
1086 if (!strcmp(file_prefix, user->file_prefix)) {
1087 if (user->header_name != NULL) {
1088 /* the header file is already present */
1089 if (is_same_file(dir_name, file_name, user->dir_name, user->header_name)) {
1090 WARNING("File `%s' was given more than once for the Makefile.", path_name);
1091 }
1092 else {
1093 char *path_name1 = compose_path_name(user->dir_name, user->header_name);
1094 char *path_name2 = compose_path_name(dir_name, file_name);
1095 ERROR("C/C++ header files `%s' and `%s' cannot be used together "
1096 "in the same Makefile.", path_name1, path_name2);
1097 Free(path_name1);
1098 Free(path_name2);
1099 }
1100 }
1101 else {
1102 /* a source file with the same prefix is already present */
1103 if (is_same_directory(dir_name, user->dir_name)) {
1104 user->header_name = file_name;
1105 file_name = NULL;
1106 if (!strcmp(suffix, "hh") || !strcmp(suffix, "hpp"))
1107 user->has_hh_suffix = TRUE;
1108 }
1109 else {
1110 char *path_name1 = compose_path_name(dir_name, file_name);
1111 char *path_name2 = compose_path_name(user->dir_name, user->source_name);
1112 ERROR("C/C++ header file `%s' cannot be used together with "
1113 "source file `%s' in the same Makefile.", path_name1, path_name2);
1114 Free(path_name1);
1115 Free(path_name2);
1116 }
1117 }
1118 Free(dir_name);
1119 Free(file_name);
1120 Free(file_prefix);
1121 return;
1122 }
970ed795
EL
1123 }
1124 makefile->UserFiles = (struct user_struct*)Realloc(makefile->UserFiles,
af710487 1125 (makefile->nUserFiles + 1) * sizeof(*makefile->UserFiles));
970ed795
EL
1126 user = makefile->UserFiles + makefile->nUserFiles;
1127 makefile->nUserFiles++;
1128 user->dir_name = dir_name;
1129 user->file_prefix = file_prefix;
1130 user->header_name = file_name;
1131 user->source_name = NULL;
1132 if (!strcmp(suffix, "hh") || !strcmp(suffix, "hpp")) user->has_hh_suffix = TRUE;
1133 else user->has_hh_suffix = FALSE;
1134 user->has_cc_suffix = FALSE;
1135 return;
1136 }
1137 } /* end if (suffix != NULL) */
1138 /* treat the file as other file if it was not handled yet */
1139 add_path_to_list(&makefile->nOtherFiles, &makefile->OtherFiles, path_name,
1140 makefile->working_dir, TRUE);
1141}
1142
1143/** Removes the generated C++ header and/or source files of module \a module
1144 * from Makefile descriptor structure \a makefile. A warning is displayed if
1145 * such file is found. */
1146static void drop_generated_files(struct makefile_struct *makefile,
1147 const struct module_struct *module)
1148{
1149 char *module_name = mcopystr(module->module_name);
1150 size_t i;
1151 /* transform all '-' characters in ASN.1 module name to '_' */
1152 for (i = 0; module_name[i] != '\0'; i++)
1153 if (module_name[i] == '-') module_name[i] = '_';
1154 for (i = 0; i < makefile->nUserFiles; i++) {
1155 struct user_struct *user = makefile->UserFiles + i;
1156 if (!strcmp(module_name, user->file_prefix)) {
1157 char *m_pathname = compose_path_name(module->dir_name, module->file_name);
1158 /** Note: if central storage is used the generated C++ files are placed
1159 * into the same directory as the TTCN-3/ASN.1 modules, otherwise the
1160 * files are generated into the working directory. */
1161 boolean is_same_dir = is_same_directory(user->dir_name,
1162 makefile->central_storage ? module->dir_name : NULL);
1163 if (user->header_name != NULL) {
1164 char *u_pathname = compose_path_name(user->dir_name,
1165 user->header_name);
1166 if (is_same_dir && user->has_hh_suffix) {
1167 WARNING("Header file `%s' is generated from module `%s' (file `%s'). "
1168 "Removing it from the list of user files.", u_pathname,
1169 module->module_name, m_pathname);
1170 } else {
1171 ERROR("Header file `%s' cannot be used together with module `%s' "
1172 "(file `%s') in the same Makefile.", u_pathname,
1173 module->module_name, m_pathname);
1174 }
1175 Free(u_pathname);
1176 }
1177 if (user->source_name != NULL) {
1178 char *u_pathname = compose_path_name(user->dir_name,
1179 user->source_name);
1180 if (is_same_dir && user->has_cc_suffix) {
1181 WARNING("Source file `%s' is generated from module `%s' (file "
1182 "`%s'). Removing it from the list of user files.", u_pathname,
1183 module->module_name, m_pathname);
1184 } else {
1185 ERROR("Source file `%s' cannot be used together with module "
1186 "`%s' (file `%s') in the same Makefile.", u_pathname,
1187 module->module_name, m_pathname);
1188 }
1189 Free(u_pathname);
1190 }
1191 Free(m_pathname);
1192 Free(user->dir_name);
1193 Free(user->file_prefix);
1194 Free(user->header_name);
1195 Free(user->source_name);
1196 makefile->nUserFiles--;
1197 memmove(user, user + 1, (makefile->nUserFiles - i) *
1198 sizeof(*makefile->UserFiles));
1199 makefile->UserFiles = (struct user_struct*)Realloc(makefile->UserFiles,
1200 makefile->nUserFiles * sizeof(*makefile->UserFiles));
1201 break;
1202 }
1203 }
1204 Free(module_name);
1205}
1206
1207/** Drops all C++ header and source files of the Makefile descriptor structure
1208 * \a makefile that are generated from its TTCN-3 or ASN.1 modules. */
1209static void filter_out_generated_files(struct makefile_struct *makefile)
1210{
1211 size_t i;
1212 for (i = 0; i < makefile->nTTCN3Modules; i++) {
1213 drop_generated_files(makefile, makefile->TTCN3Modules + i);
1214 }
1215 if (makefile->preprocess) {
1216 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
1217 drop_generated_files(makefile, makefile->TTCN3PPModules + i);
1218 }
1219 }
1220 for (i = 0; i < makefile->nASN1Modules; i++) {
1221 drop_generated_files(makefile, makefile->ASN1Modules + i);
1222 }
1223}
1224
1225/** Completes the list of user C/C++ header and source files in \a makefile.
1226 * If only the source file was given the function looks for the corresponding
1227 * header file or vice versa. */
1228static void complete_user_files(const struct makefile_struct *makefile)
1229{
1230 size_t i;
1231 for (i = 0; i < makefile->nUserFiles; i++) {
1232 struct user_struct *user = makefile->UserFiles + i;
1233 if (user->header_name == NULL) {
1234 static const char * const suffix_list[] = { "hh", "h", "hpp", NULL };
1235 const char * const *suffix_ptr;
1236 for (suffix_ptr = suffix_list; *suffix_ptr != NULL; suffix_ptr++) {
af710487 1237 char *file_name = mprintf("%s.%s", user->file_prefix, *suffix_ptr);
1238 char *path_name = compose_path_name(user->dir_name, file_name);
1239 if (get_path_status(path_name) == PS_FILE) {
1240 Free(path_name);
1241 user->header_name = file_name;
1242 if (!strcmp(*suffix_ptr, "hh") || !strcmp(*suffix_ptr, "hpp"))
1243 user->has_hh_suffix = TRUE;
1244 break;
1245 }
1246 Free(file_name);
1247 Free(path_name);
970ed795 1248 }
af710487 1249 }
1250 else if (user->source_name == NULL) {
970ed795
EL
1251 static const char * const suffix_list[] = { "cc", "c", "cpp", NULL };
1252 const char * const *suffix_ptr;
1253 for (suffix_ptr = suffix_list; *suffix_ptr != NULL; suffix_ptr++) {
af710487 1254 char *file_name = mprintf("%s.%s", user->file_prefix, *suffix_ptr);
1255 char *path_name = compose_path_name(user->dir_name, file_name);
1256 if (get_path_status(path_name) == PS_FILE) {
1257 Free(path_name);
1258 user->source_name = file_name;
1259 if (!strcmp(*suffix_ptr, "cc") || !strcmp(*suffix_ptr, "cpp"))
1260 user->has_cc_suffix = TRUE;
1261 break;
1262 }
1263 Free(file_name);
1264 Free(path_name);
970ed795
EL
1265 }
1266 }
1267 }
1268}
1269
1270/** Converts the directory name pointed by \a dir_ptr to a relative pathname
1271 * based on \a working_dir. The original directory name is deallocated and
1272 * replaced with a new string. Nothing happens if \a dir_ptr points to NULL. */
1273static void replace_dir_with_relative(char **dir_ptr, const char *working_dir)
1274{
1275 if (*dir_ptr != NULL) {
1276 char *rel_dir = get_relative_dir(*dir_ptr, working_dir);
1277 Free(*dir_ptr);
1278 *dir_ptr = rel_dir;
1279 }
1280}
1281
1282/** Converts the directory part of path name pointed by \a path_ptr to a relative
1283 * pathname based on \a working_dir. The original path name is deallocated and
1284 * replaced with a new string. */
1285static void convert_path_to_relative(char **path_ptr, const char *working_dir)
1286{
1287 char *dir_name = get_dir_name(*path_ptr, working_dir);
1288 if (dir_name != NULL) {
1289 char *file_name = get_file_from_path(*path_ptr);
1290 replace_dir_with_relative(&dir_name, working_dir);
1291 Free(*path_ptr);
1292 *path_ptr = compose_path_name(dir_name, file_name);
1293 Free(file_name);
1294 Free(dir_name);
1295 }
1296}
1297
1298/** Converts all directories used by the Makefile descriptor structure
1299 * \a makefile to relative pathnames based on the working directory stored in
1300 * \a makefile. */
1301static void convert_dirs_to_relative(struct makefile_struct *makefile)
1302{
1303 size_t i;
1304 for (i = 0; i < makefile->nTTCN3Modules; i++) {
1305 replace_dir_with_relative(&makefile->TTCN3Modules[i].dir_name,
1306 makefile->working_dir);
1307 }
1308 if (makefile->preprocess) {
1309 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
1310 replace_dir_with_relative(&makefile->TTCN3PPModules[i].dir_name,
1311 makefile->working_dir);
1312 }
1313 for (i = 0; i < makefile->nTTCN3IncludeFiles; i++) {
1314 convert_path_to_relative(makefile->TTCN3IncludeFiles + i,
1315 makefile->working_dir);
1316 }
1317 }
1318 for (i = 0; i < makefile->nASN1Modules; i++) {
1319 replace_dir_with_relative(&makefile->ASN1Modules[i].dir_name,
1320 makefile->working_dir);
1321 }
1322 for (i = 0; i < makefile->nUserFiles; i++) {
1323 replace_dir_with_relative(&makefile->UserFiles[i].dir_name,
1324 makefile->working_dir);
1325 }
1326 for (i = 0; i < makefile->nOtherFiles; i++) {
1327 convert_path_to_relative(makefile->OtherFiles + i, makefile->working_dir);
1328 }
1329 if (makefile->ets_name != NULL)
1330 convert_path_to_relative(&makefile->ets_name, makefile->working_dir);
1331}
1332
1333/* Returns whether the string \a file_name contains special characters. */
1334static boolean has_special_chars(const char *file_name)
1335{
1336 if (file_name != NULL) {
1337 size_t i;
1338 for (i = 0; ; i++) {
1339 int c = (unsigned char)file_name[i];
1340 switch (c) {
1341 case '\0':
1342 return FALSE;
1343 case ' ':
1344 case '*':
1345 case '?':
1346 case '[':
1347 case ']':
1348 case '<':
1349 case '=':
1350 case '>':
1351 case '|':
1352 case '&':
1353 case '$':
1354 case '%':
1355 case '{':
1356 case '}':
1357 case ';':
1358 case ':':
1359 case '(':
1360 case ')':
1361 case '#':
1362 case '!':
1363 case '\'':
1364 case '"':
1365 case '`':
1366 case '\\':
1367 return TRUE;
1368 default:
1369 if (!isascii(c) || !isprint(c)) return TRUE;
1370 break;
1371 }
1372 }
1373 }
1374 return FALSE;
1375}
1376
1377/** Checks whether the path name composed of \a dir_name and \a file_name
1378 * contains special characters that are not allowed in the Makefile. Parameter
1379 * \a what contains the description of the corresponding file. */
1380static void check_special_chars_in_path(const char *dir_name,
1381 const char *file_name, const char *what)
1382{
1383 if (has_special_chars(dir_name) || has_special_chars(file_name)) {
1384 char *path_name = compose_path_name(dir_name, file_name);
1385 ERROR("The name of %s `%s' contains special characters that cannot be "
1386 "handled properly by the `make' utility and/or the shell.", what,
1387 path_name);
1388 Free(path_name);
1389 }
1390}
1391
1392/** Checks whether the directory names or file names that will be used in the
1393 * generated Makefile contain special characters that cannot be handled by the
1394 * "make" utility. */
1395static void check_special_chars(const struct makefile_struct *makefile)
1396{
1397 size_t i;
1398 for (i = 0; i < makefile->nTTCN3Modules; i++) {
1399 check_special_chars_in_path(makefile->TTCN3Modules[i].dir_name,
1400 makefile->TTCN3Modules[i].file_name, "TTCN-3 file");
1401 }
1402 if (makefile->preprocess) {
1403 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
1404 check_special_chars_in_path(makefile->TTCN3PPModules[i].dir_name,
1405 makefile->TTCN3PPModules[i].file_name,
1406 "TTCN-3 file to be preprocessed");
1407 }
1408 }
1409 for (i = 0; i < makefile->nASN1Modules; i++) {
1410 check_special_chars_in_path(makefile->ASN1Modules[i].dir_name,
1411 makefile->ASN1Modules[i].file_name, "ASN.1 file");
1412 }
1413 for (i = 0; i < makefile->nUserFiles; i++) {
1414 const struct user_struct *user = makefile->UserFiles + i;
1415 if (user->source_name != NULL)
1416 check_special_chars_in_path(user->dir_name, user->source_name,
1417 "C/C++ source file");
1418 else check_special_chars_in_path(user->dir_name, user->header_name,
1419 "C/C++ header file");
1420 }
1421 for (i = 0; i < makefile->nOtherFiles; i++) {
1422 check_special_chars_in_path(NULL, makefile->OtherFiles[i], "other file");
1423 }
1424}
1425
1426/** Adds base directory \a dir_name to Makefile descriptor structure
1427 * \a makefile. Flag \a has_modules indicates whether \a dir_name contains
1428 * TTCN-3 and/or ASN.1 modules. The new directory is ignored if it is already
1429 * added to \a makefile. */
1430static void add_base_dir(struct makefile_struct *makefile,
1431 const char *dir_name, boolean has_modules)
1432{
1433 struct base_dir_struct *base_dir;
1434 if (dir_name != NULL) {
1435 size_t i;
1436 for (i = 0; i < makefile->nBaseDirs; i++) {
1437 base_dir = makefile->BaseDirs + i;
1438 if (!strcmp(dir_name, base_dir->dir_name)) {
1439 if (has_modules) base_dir->has_modules = TRUE;
1440 return;
1441 }
1442 }
1443 makefile->BaseDirs = (struct base_dir_struct*)Realloc(makefile->BaseDirs,
1444 (makefile->nBaseDirs + 1) * sizeof(*makefile->BaseDirs));
1445 base_dir = makefile->BaseDirs + makefile->nBaseDirs;
1446 makefile->nBaseDirs++;
1447 base_dir->dir_name = dir_name;
1448 base_dir->has_modules = has_modules;
1449 }
1450}
1451
1452/** Collects all directories that are used in the Makefile descriptor structure
1453 * \a makefile in order to use pre-compiled files from them. */
1454static void collect_base_dirs(struct makefile_struct *makefile)
1455{
1456 size_t i;
1457 for (i = 0; i < makefile->nTTCN3Modules; i++) {
1458 add_base_dir(makefile, makefile->TTCN3Modules[i].dir_name, TRUE);
1459 }
1460 if (makefile->preprocess) {
1461 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
1462 add_base_dir(makefile, makefile->TTCN3PPModules[i].dir_name, TRUE);
1463 }
1464 }
1465 for (i = 0; i < makefile->nASN1Modules; i++) {
1466 add_base_dir(makefile, makefile->ASN1Modules[i].dir_name, TRUE);
1467 }
1468 for (i = 0; i < makefile->nUserFiles; i++) {
1469 add_base_dir(makefile, makefile->UserFiles[i].dir_name, FALSE);
1470 }
1471 if (makefile->nBaseDirs == 0) {
1472 WARNING("Usage of pre-compiled files from central storage (option `-c') "
1473 "is enabled, but all given files are located in the current working "
1474 "directory.");
1475 }
1476}
1477
1478/** Checks whether the TTCN-3, ASN.1 and C++ files follow the default naming
1479 * convention and sets the appropriate flags accordingly. */
1480static void check_naming_convention(struct makefile_struct *makefile)
1481{
1482 /* initially set all flags to true */
1483 makefile->TTCN3ModulesRegular = TRUE;
1484 makefile->BaseTTCN3ModulesRegular = TRUE;
1485 makefile->ASN1ModulesRegular = TRUE;
1486 makefile->BaseASN1ModulesRegular = TRUE;
1487 makefile->UserHeadersRegular = TRUE;
1488 makefile->UserSourcesRegular = TRUE;
1489 makefile->BaseUserHeadersRegular = TRUE;
1490 makefile->BaseUserSourcesRegular = TRUE;
1491 if (makefile->central_storage) {
1492 /* this project (Makefile) will use pre-compiled files from other
1493 directories */
1494 size_t i;
1495 for (i = 0; i < makefile->nTTCN3Modules; i++) {
1496 const struct module_struct *module = makefile->TTCN3Modules + i;
1497 if (module->dir_name != NULL) {
af710487 1498 if (!module->is_regular) makefile->BaseTTCN3ModulesRegular = FALSE;
1499 }
1500 else {
1501 if (!module->is_regular) makefile->TTCN3ModulesRegular = FALSE;
970ed795
EL
1502 }
1503 if (!makefile->TTCN3ModulesRegular && !makefile->BaseTTCN3ModulesRegular)
af710487 1504 break;
970ed795
EL
1505 }
1506 /* ttcnpp files are ttcn files */
1507 if ((makefile->TTCN3ModulesRegular || makefile->BaseTTCN3ModulesRegular) &&
af710487 1508 makefile->preprocess) {
970ed795
EL
1509 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
1510 const struct module_struct *module = makefile->TTCN3PPModules + i;
1511 if (module->dir_name != NULL) {
1512 if (!module->is_regular) makefile->BaseTTCN3ModulesRegular = FALSE;
1513 } else {
1514 if (!module->is_regular) makefile->TTCN3ModulesRegular = FALSE;
1515 }
1516 if (!makefile->TTCN3ModulesRegular && !makefile->BaseTTCN3ModulesRegular)
1517 break;
1518 }
1519 }
1520 for (i = 0; i < makefile->nASN1Modules; i++) {
1521 const struct module_struct *module = makefile->ASN1Modules + i;
1522 if (module->dir_name != NULL) {
af710487 1523 if (!module->is_regular) makefile->BaseASN1ModulesRegular = FALSE;
1524 }
1525 else {
1526 if (!module->is_regular) makefile->ASN1ModulesRegular = FALSE;
970ed795
EL
1527 }
1528 if (!makefile->ASN1ModulesRegular && !makefile->BaseASN1ModulesRegular)
af710487 1529 break;
970ed795
EL
1530 }
1531 for (i = 0; i < makefile->nUserFiles; i++) {
1532 const struct user_struct *user = makefile->UserFiles + i;
1533 if (user->dir_name != NULL) {
af710487 1534 if (!user->has_cc_suffix)
1535 makefile->BaseUserSourcesRegular = FALSE;
1536 if (!user->has_cc_suffix || !user->has_hh_suffix)
1537 makefile->BaseUserHeadersRegular = FALSE;
1538 }
1539 else {
1540 if (!user->has_cc_suffix)
1541 makefile->UserSourcesRegular = FALSE;
1542 if (!user->has_cc_suffix || !user->has_hh_suffix)
1543 makefile->UserHeadersRegular = FALSE;
970ed795
EL
1544 }
1545 if (!makefile->UserHeadersRegular && !makefile->UserSourcesRegular &&
af710487 1546 !makefile->BaseUserHeadersRegular &&
1547 !makefile->BaseUserSourcesRegular) break;
970ed795
EL
1548 }
1549 } else {
1550 /* this project (Makefile) will-be stand-alone */
1551 size_t i;
1552 for (i = 0; i < makefile->nTTCN3Modules; i++) {
1553 const struct module_struct *module = makefile->TTCN3Modules + i;
1554 if (!module->is_regular || module->dir_name != NULL) {
af710487 1555 makefile->TTCN3ModulesRegular = FALSE;
1556 break;
970ed795
EL
1557 }
1558 }
1559 if (makefile->TTCN3ModulesRegular && makefile->preprocess) {
1560 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
1561 const struct module_struct *module = makefile->TTCN3PPModules + i;
1562 if (!module->is_regular || module->dir_name != NULL) {
1563 makefile->TTCN3ModulesRegular = FALSE;
1564 break;
1565 }
1566 }
1567 }
1568 for (i = 0; i < makefile->nASN1Modules; i++) {
1569 const struct module_struct *module = makefile->ASN1Modules + i;
1570 if (!module->is_regular || module->dir_name != NULL) {
af710487 1571 makefile->ASN1ModulesRegular = FALSE;
1572 break;
970ed795
EL
1573 }
1574 }
1575 for (i = 0; i < makefile->nUserFiles; i++) {
1576 const struct user_struct *user = makefile->UserFiles + i;
1577 if (!user->has_cc_suffix)
af710487 1578 makefile->UserSourcesRegular = FALSE;
970ed795 1579 if (!user->has_cc_suffix || !user->has_hh_suffix)
af710487 1580 makefile->UserHeadersRegular = FALSE;
970ed795 1581 if (!makefile->UserHeadersRegular && !makefile->UserSourcesRegular)
af710487 1582 break;
970ed795
EL
1583 }
1584 }
1585}
1586
1587/** Prints the name of the TTCN-3 or ASN.1 source file that belongs to module
1588 * \a module to file \a fp. */
1589static void print_file_name(FILE *fp, const struct module_struct *module)
1590{
1591 char *path_name = compose_path_name(module->dir_name, module->file_name);
1592 fprintf(fp, " %s", path_name);
1593 Free(path_name);
1594}
1595
1596/** Prints the name of the preprocessed TTCN-3 source file that belongs to
1597 * module \a module to file \a fp. */
1598static void print_preprocessed_file_name(FILE *fp,
1599 const struct module_struct *module)
1600{
1601 char *preprocessed_name = get_preprocessed_file_name(module->file_name);
1602 char *path_name = compose_path_name(module->dir_name, preprocessed_name);
1603 fprintf(fp, " %s", path_name);
1604 Free(path_name);
1605 Free(preprocessed_name);
1606}
1607
1608/** Prints the name of the generated header, source or object file of module
1609 * \a module to file \a fp. The name of the directory is added only if
1610 * \a add_directory is TRUE. Parameter \a suffix shall be "hh", "cc", "hpp", "cpp" or "o". */
1611static void print_generated_file_name(FILE *fp,
1612 const struct module_struct *module, boolean add_directory, const char *suffix)
1613{
1614 char *file_name = mcopystr(module->module_name);
1615 /* replace '-' with '_' */
1616 size_t i;
1617 for (i = 0; file_name[i] != '\0'; i++)
1618 if (file_name[i] == '-') file_name[i] = '_';
1619 /* append the suffix */
1620 file_name = mputprintf(file_name, "%s", suffix);
1621 /* add the directory name if necessary */
1622 if (add_directory) {
1623 char *path_name = compose_path_name(module->dir_name, file_name);
1624 Free(file_name);
1625 file_name = path_name;
1626 }
1627 fprintf(fp, " %s", file_name);
1628 Free(file_name);
1629}
1630
1631/** Prints the name of the user C/C++ header file of user module \a user if the
1632 * above file exists. */
1633static void print_header_name(FILE *fp, const struct user_struct *user)
1634{
1635 if (user->header_name != NULL) {
1636 char *path_name = compose_path_name(user->dir_name, user->header_name);
1637 fprintf(fp, " %s", path_name);
1638 Free(path_name);
1639 }
1640}
1641
1642/** Prints the name of the user C/C++ source file of user module \a user if the
1643 * above file exists. */
1644static void print_source_name(FILE *fp, const struct user_struct *user)
1645{
1646 if (user->source_name != NULL) {
1647 char *path_name = compose_path_name(user->dir_name, user->source_name);
1648 fprintf(fp, " %s", path_name);
1649 Free(path_name);
1650 }
1651}
1652
1653/** Prints the name of the user C/C++ object file of user module \a user if the
1654 * above file exists (i.e. the respective source file is present). */
1655static void print_object_name(FILE *fp, const struct user_struct *user)
1656{
1657 if (user->source_name != NULL) {
1658 char *file_name = mprintf("%s.o", user->file_prefix);
1659 char *path_name = compose_path_name(user->dir_name, file_name);
1660 Free(file_name);
1661 fprintf(fp, " %s", path_name);
1662 Free(path_name);
1663 }
1664}
1665
1666static void print_shared_object_name(FILE *fp, const struct user_struct *user)
1667{
1668 if (user->source_name != NULL) {
1669 char *file_name = mprintf("%s.so", user->file_prefix);
1670 char *path_name = compose_path_name(user->dir_name, file_name);
1671 Free(file_name);
1672 fprintf(fp, " %s", path_name);
1673 Free(path_name);
1674 }
1675}
1676/** Prints the splitted files' names for a given module. */
1677static void print_splitted_file_names(FILE *fp,
1678 const struct makefile_struct *makefile, const struct module_struct *module)
1679{
1680 if (strcmp(makefile->code_splitting_mode, "-U type") == 0) {
1681 print_generated_file_name(fp, module, FALSE, "_seq.cc");
1682 print_generated_file_name(fp, module, FALSE, "_set.cc");
1683 print_generated_file_name(fp, module, FALSE, "_seqof.cc");
1684 print_generated_file_name(fp, module, FALSE, "_setof.cc");
1685 print_generated_file_name(fp, module, FALSE, "_union.cc");
1686 }
1687}
1688
1689static void fprint_extra_targets(FILE* fp, struct string2_list* target_placement_list, const char* placement)
1690{
1691 struct string2_list* act_elem = target_placement_list;
1692 while (act_elem) {
1693 if (act_elem->str1 && act_elem->str2 && (strcmp(act_elem->str2,placement)==0)) {
1694 fprintf(fp, " %s", act_elem->str1);
1695 }
1696 act_elem = act_elem->next;
1697 }
1698}
1699
1700#undef COMMENT_PREFIX
1701#define COMMENT_PREFIX "# "
1702
1703/** Prints the Makefile based on structure \a makefile. */
1704static void print_makefile(struct makefile_struct *makefile)
1705{
af710487 1706 boolean add_refd_prjs = FALSE;
1707 if (makefile->linkingStrategy && makefile->hierarchical) {
1708 add_refd_prjs = hasSubProject(makefile->project_name);
1709 }
1710 else {
1711 add_refd_prjs = makefile->sub_project_dirs && makefile->sub_project_dirs->str;
1712 }
970ed795
EL
1713 NOTIFY("Generating Makefile skeleton...");
1714
1715 if (makefile->force_overwrite ||
1716 get_path_status(makefile->output_file) == PS_NONEXISTENT) {
1717 size_t i;
1718 char *user_info;
1719 const char* cxx;
1720 const char* cpp;
1721 const char *rm_command = makefile->gnu_make ? "$(RM)" : "rm -f";
1722 FILE *fp;
1723 boolean run_compiler = (makefile->nASN1Modules > 0)
1724 || (makefile->nTTCN3Modules) || (makefile->nTTCN3PPModules > 0);
1725
1726 expstring_t titan_dir = 0;
1727 const char * last_slash = strrchr(program_name, '/');
1728 if (last_slash != NULL) {
1729 size_t path_len = last_slash - program_name;
1730 titan_dir = mcopystr(program_name);
1731 /* Chop off the program name, and the /bin before it (if any) */
1732 if (path_len >= 4
1733 && memcmp(titan_dir + path_len - 4, "/bin", 4) == 0) {
1734 titan_dir = mtruncstr(titan_dir, path_len - 4);
1735 }
1736 else {
1737 titan_dir = mtruncstr(titan_dir, path_len);
1738 }
1739 }
1740
1741
1742 fp = fopen(makefile->output_file, "w");
1743 if (fp == NULL){
1744 ERROR("Cannot open output file `%s' for writing: %s",
af710487 1745 makefile->output_file, strerror(errno));
970ed795
EL
1746 return;
1747 }
1748 user_info = get_user_info();
1749 fprintf(fp, "# This Makefile was generated by the Makefile Generator\n"
1750 "# of the TTCN-3 Test Executor version " PRODUCT_NUMBER "\n"
1751 "# for %s\n"
1752 COPYRIGHT_STRING "\n\n"
1753 "# The following make commands are available:\n"
1754 "# - make, make all Builds the %s.\n"
1755 "# - make archive Archives all source files.\n"
d44e3c4f 1756 "# - make check Checks the semantics of TTCN-3 and ASN.1"
1757 "modules.\n"
1758 "# - make port Generates port skeletons.\n"
af710487 1759 "%s" // clean:
1760 "%s" //clean-all
970ed795
EL
1761 "# - make compile Translates TTCN-3 and ASN.1 modules to C++.\n"
1762 "# - make dep Creates/updates dependency list.\n"
1763 "# - make executable Builds the executable test suite.\n"
1764 "# - make library Builds the library archive.\n"
1765 "# - make objects Builds the object files without linking the "
1766 "executable.\n", user_info,
af710487 1767 makefile->library ? "library archive." : "executable test suite",
1768 (makefile->linkingStrategy && makefile->hierarchical) ?
1769 "# - make clean Removes generated files from project.\n" :
1770 "# - make clean Removes all generated files.\n",
1771 (makefile->linkingStrategy && makefile->hierarchical) ?
1772 "# - make clean-all Removes all generated files from the project hierarchy.\n" : "");
970ed795
EL
1773 Free(user_info);
1774 if (makefile->dynamic)
1775 fprintf(fp, "# - make shared_objects Builds the shared object files "
1776 "without linking the executable.\n");
1777 if (makefile->preprocess)
1778 fputs("# - make preprocess Preprocess TTCN-3 files.\n", fp);
1779 if (makefile->central_storage) {
1780 fputs("# WARNING! This Makefile uses pre-compiled files from the "
af710487 1781 "following directories:\n", fp);
970ed795
EL
1782 for (i = 0; i < makefile->nBaseDirs; i++)
1783 fprintf(fp, "# %s\n", makefile->BaseDirs[i].dir_name);
1784 fputs("# The executable tests will be consistent only if all directories "
af710487 1785 "use\n"
1786 "# the same platform and the same version of TTCN-3 Test Executor "
1787 "and\n"
1788 "# C++ compiler with the same command line switches.\n\n", fp);
970ed795
EL
1789 }
1790 if (makefile->gnu_make) {
1791 fputs("# WARNING! This Makefile can be used with GNU make only.\n"
1792 "# Other versions of make may report syntax errors in it.\n\n"
1793 "#\n"
1794 "# Do NOT touch this line...\n"
1795 "#\n"
d44e3c4f 1796 ".PHONY: all shared_objects executable library objects check port clean dep archive", fp);
970ed795
EL
1797 if (makefile->preprocess) fputs(" preprocess", fp);
1798 if (add_refd_prjs) {
af710487 1799 fprintf(fp, "\\\n referenced-all referenced-shared_objects referenced-executable referenced-library referenced-objects referenced-check"
1800 "\\\n referenced-clean%s",
1801 (makefile->linkingStrategy && makefile->hierarchical) ?
1802 "-all" : "");
970ed795
EL
1803 }
1804 fprint_extra_targets(fp, makefile->target_placement_list, "PHONY");
1805
1806 if (makefile->gcc_dep) {
1807 fputs("\n\n.SUFFIXES: .d", fp);
1808 }
1809 fputs("\n\n", fp);
1810 }
1811
af710487 1812 if (makefile->linkingStrategy) {
1813 const char* tpd_name = getTPDFileName(makefile->project_name);
1814 if (tpd_name) {
1815 fputs("# Titan Project Descriptor file what this Makefile is generated from.\n", fp);
1816 fprintf(fp, "TPD = %s\n\n", tpd_name);
1817 }
1818 const char* root_dir = getPathToRootDir(makefile->project_name);
1819 if (root_dir) {
1820 fputs("# Relative path to top directory at OS level.\n", fp);
1821 fprintf(fp, "ROOT_DIR = %s\n\n", root_dir);
1822 }
1823 }
1824
970ed795 1825 if (add_refd_prjs) {
af710487 1826 struct string_list* act_elem = NULL;
1827 struct string_list* head = NULL;
1828 if (makefile->linkingStrategy && makefile->hierarchical) {// pair with free_string_list
1829 head = act_elem = getRefWorkingDirs(makefile->project_name);
1830 }
1831 else {
1832 act_elem = makefile->sub_project_dirs;
1833 }
1834 if (!makefile->linkingStrategy)
1835 fputs("# This is the top level makefile of a Makefile hierarchy generated from\n", fp);
1836 fputs("# Titan Project Descriptor hierarchy. List of referenced project\n"
970ed795
EL
1837 "# working directories (ordered by dependencies):\n", fp);
1838 while (act_elem) {
1839 if (act_elem->str) {
1840 fprintf(fp, "# %s\n", act_elem->str);
1841 }
1842 act_elem = act_elem->next;
1843 }
af710487 1844 if (makefile->linkingStrategy && makefile->hierarchical) { // pair with getRefWorkingDirs
1845 free_string_list(head);
1846 }
970ed795 1847 fputs("REFERENCED_PROJECT_DIRS = ", fp);
af710487 1848 if (makefile->linkingStrategy && makefile->hierarchical) {
1849 head = act_elem = getRefWorkingDirs(makefile->project_name); // pair with free_string_list
1850 }
1851 else {
1852 act_elem = makefile->sub_project_dirs;
1853 }
970ed795
EL
1854 while (act_elem) {
1855 if (act_elem->str) {
1856 fprintf(fp, "%s ", act_elem->str);
1857 }
1858 act_elem = act_elem->next;
1859 }
1860 fputs("\n\n", fp);
af710487 1861 if (makefile->linkingStrategy && makefile->hierarchical) {// pair with getRefWorkingDirs
1862 free_string_list(head);
1863 }
970ed795
EL
1864 }
1865
1866 fprintf(fp, "#\n"
1867 "# Set these variables...\n"
1868 "#\n\n"
1869 "# The path of your TTCN-3 Test Executor installation:\n"
1870 "# Uncomment this line to override the environment variable.\n"
1871 "%s"
1872 "# TTCN3_DIR = %s\n"
1873 , titan_dir ?
1874 "# The value below points to the location of the TITAN version\n"
1875 "# that generated this makefile.\n" : ""
1876 , titan_dir ? titan_dir : "");
1877 if (titan_dir) Free(titan_dir);
1878
01fb194f 1879 boolean cxx_free = FALSE;
970ed795
EL
1880 if (makefile->cxxcompiler) {
1881 cxx = makefile->cxxcompiler;
1882 } else {
01fb194f 1883#ifdef __clang__
1884 unsigned int
1885 compiler_major = __clang_major__,
1886 compiler_minor = __clang_minor__;
1887 cxx = mprintf("clang++-%u.%u", compiler_major, compiler_minor);
1888 cxx_free = TRUE;
1889#else
970ed795 1890 cxx = "g++";
01fb194f 1891#endif
970ed795
EL
1892 }
1893
1894 fprintf(fp, "\n# Your platform: (SOLARIS, SOLARIS8, LINUX, FREEBSD or "
1895 "WIN32)\n"
1896 "PLATFORM = %s\n\n"
1897 "# Your C++ compiler:\n"
1898 "# (if you change the platform, you may need to change the compiler)\n"
1899 "CXX = %s \n\n", get_platform_string(), cxx);
1900
1901
1902 if (makefile->preprocess || makefile->ttcn3preprocessor) {
1903 if (makefile->ttcn3preprocessor) {
1904 cpp = makefile->ttcn3preprocessor;
1905 } else {
1906 cpp = "cpp";
1907 }
1908 fprintf(fp,"# C preprocessor used for TTCN-3 files:\n"
1909 "CPP = %s\n\n", cpp);
1910 }
1911
1912 fputs("# Flags for the C++ preprocessor (and makedepend as well):\n"
1913 "CPPFLAGS = -D$(PLATFORM) -I$(TTCN3_DIR)/include", fp);
1914
1915 if (makefile->use_runtime_2) fputs(" -DTITAN_RUNTIME_2", fp);
1916
1917 for (i = 0; i < makefile->nBaseDirs; i++) {
1918 fprintf(fp, " -I%s", makefile->BaseDirs[i].dir_name);
1919 }
1920
1921 if (makefile->prep_includes) {
1922 struct string_list* act_elem = makefile->prep_includes;
1923 while (act_elem) {
1924 if (act_elem->str) {
1925 fprintf(fp, " -I%s", act_elem->str);
1926 }
1927 act_elem = act_elem->next;
1928 }
1929 }
1930
1931 if (makefile->prep_defines) {
1932 struct string_list* act_elem = makefile->prep_defines;
1933 while (act_elem) {
1934 if (act_elem->str) {
1935 fprintf(fp, " -D%s", act_elem->str);
1936 }
1937 act_elem = act_elem->next;
1938 }
1939 }
1940
af710487 1941 if (makefile->prep_undefines) {
1942 struct string_list* act_elem = makefile->prep_undefines;
1943 while (act_elem) {
1944 if (act_elem->str) {
1945 fprintf(fp, " -U%s", act_elem->str);
1946 }
1947 act_elem = act_elem->next;
1948 }
1949 }
1950
970ed795
EL
1951 fputs("\n\n", fp);
1952
1953 if (makefile->gcc_dep) {
1954 fprintf(fp, "# Flags for dependency generation\n"
1955 "CXXDEPFLAGS = -%s\n\n", strstr(cxx, "g++") ? "MM" : "xM1");
1956 }
1957
01fb194f 1958 if (cxx_free) {
1959 Free((char*)cxx);
1960 cxx = NULL;
1961 }
1962
970ed795
EL
1963 if (makefile->preprocess || makefile->ttcn3_prep_includes || makefile->ttcn3_prep_defines) {
1964 fputs("# Flags for preprocessing TTCN-3 files:\n"
1965 "CPPFLAGS_TTCN3 =", fp);
1966
1967 if (makefile->preprocess) {
1968 for (i = 0; i < makefile->nBaseDirs; i++) {
1969 fprintf(fp, " -I%s", makefile->BaseDirs[i].dir_name);
1970 }
1971 }
1972 if (makefile->ttcn3_prep_includes) {
1973 struct string_list* act_elem = makefile->ttcn3_prep_includes;
1974 while (act_elem) {
1975 if (act_elem->str) {
1976 fprintf(fp, " -I%s", act_elem->str);
1977 }
1978 act_elem = act_elem->next;
1979 }
1980 }
1981 if (makefile->ttcn3_prep_defines) {
1982 struct string_list* act_elem = makefile->ttcn3_prep_defines;
1983 while (act_elem) {
1984 if (act_elem->str) {
1985 fprintf(fp, " -D%s", act_elem->str);
1986 }
1987 act_elem = act_elem->next;
1988 }
1989 }
af710487 1990 if (makefile->ttcn3_prep_undefines) {
1991 struct string_list* act_elem = makefile->ttcn3_prep_undefines;
1992 while (act_elem) {
1993 if (act_elem->str) {
1994 fprintf(fp, " -U%s", act_elem->str);
1995 }
1996 act_elem = act_elem->next;
1997 }
1998 }
970ed795
EL
1999 fputs("\n\n", fp);
2000 }
2001
2002 /* code splitting: command line argument wins */
2003 if (makefile->code_splitting_mode == NULL) {
2004 if (makefile->codesplittpd) {
2005 makefile->code_splitting_mode = mcopystr("-U type");
2006 }
2007 }
2008
2009 fprintf(fp, "# Flags for the C++ compiler:\n"
2010 "CXXFLAGS = %s%s %s %s\n\n"
2011 "# Flags for the linker:\n"
2012 "LDFLAGS = %s%s\n\n"
2013 "ifeq ($(PLATFORM), WIN32)\n"
2014 "# Silence linker warnings.\n"
2015 "LDFLAGS += -Wl,--enable-auto-import,--enable-runtime-pseudo-reloc\n"
2016 "endif\n\n"
2017 "# Utility to create library files\n"
2018 "AR = ar\n"
2019 "ARFLAGS = \n\n"
2020 "# Flags for the TTCN-3 and ASN.1 compiler:\n"
f57971fe 2021 "COMPILER_FLAGS =%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n\n"
970ed795
EL
2022 "# Execution mode: (either ttcn3 or ttcn3-parallel)\n"
2023 "TTCN3_LIB = ttcn3%s%s%s\n\n"
2024#ifdef LICENSE
2025 "# The path of your OpenSSL installation:\n"
2026 "# If you do not have your own one, leave it unchanged.\n"
feade998 2027 "%sOPENSSL_DIR = $(TTCN3_DIR)\n\n"
970ed795
EL
2028#endif
2029 "# The path of your libxml2 installation:\n"
2030 "# If you do not have your own one, leave it unchanged.\n"
2031 "XMLDIR = $(TTCN3_DIR)\n\n"
2032 "# Directory to store the archived source files:\n",
2033 makefile->dynamic ? "-Wall -fPIC" : "-Wall", /* CXXFLAGS */
2034 makefile->coverage ? " -fprofile-arcs -ftest-coverage -g" : "", /* CXXFLAGS COVERAGE */
2035 makefile->optlevel ? makefile->optlevel : "", /* CXXFLAGS optimization level */
2036 makefile->optflags ? makefile->optflags : "", /* CXXFLAGS optimization level */
2037 makefile->dynamic ? "-fPIC" : "", /* LDFLAGS */
2038 makefile->coverage ? " -fprofile-arcs -ftest-coverage -g -lgcov" : "", /* LDFLAGS COVERAGE */
2039 /* COMPILER_FLAGS */
2040 makefile->use_runtime_2 ? " -L -R " : " -L ",
2041 (makefile->code_splitting_mode ? makefile->code_splitting_mode : ""),
2042 (makefile->quietly ? " -q" : ""),
2043 (makefile->disablesubtypecheck ? " -y" : ""),
2044 (makefile->disableber ? " -b" : ""),
2045 (makefile->disableraw ? " -r" : ""),
2046 (makefile->disabletext ? " -x" : ""),
2047 (makefile->disablexer ? " -X" : ""),
2048 (makefile->disablejson ? " -j" : ""),
2049 (makefile->forcexerinasn ? " -a" : ""),
2050 (makefile->defaultasomit ? " -d" : ""),
2051 (makefile->gccmsgformat ? " -g" : ""),
2052 (makefile->linenumbersonlymsg ? " -i" : ""),
2053 (makefile->includesourceinfo ? " -l" : ""),
2054 /*(makefile->addsourcelineinfo ? " -L" : ""),*/
2055 (makefile->suppresswarnings ? " -w" : ""),
2056 (makefile->outparamboundness ? " -Y" : ""),
3abe9331 2057 (makefile->omit_in_value_list ? " -M" : ""),
feade998 2058 (makefile->warnings_for_bad_variants ? " -E" : ""),
f08ff9ca 2059 (makefile->activate_debugger ? " -n" : ""),
970ed795 2060 (makefile->tcov_file_name ? makefile->tcov_file_name : ""),
3abe9331 2061 (makefile->profiled_file_list ? " -z $(PROFILED_FILE_LIST)" : ""),
970ed795
EL
2062 /* end of COMPILER FLAGS */
2063 (makefile->use_runtime_2 ? "-rt2" : ""), /* TTCN3_LIB */
2064 (makefile->single_mode ? "" : "-parallel"),
2065 (makefile->dynamic ? "-dynamic": "")
feade998 2066#ifdef LICENSE
2067 ,(makefile->disable_predef_ext_folder ? "# " : "")
2068#endif
970ed795
EL
2069 );
2070 if (!makefile->gnu_make) {
2071 fputs("# Note: you can set any directory except ./archive\n", fp);
2072 }
2073 fputs("ARCHIVE_DIR = backup\n\n"
2074 "#\n"
2075 "# You may change these variables. Add your files if necessary...\n"
2076 "#\n\n"
2077 "# TTCN-3 modules of this project:\n"
2078 "TTCN3_MODULES =", fp);
2079 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2080 const struct module_struct *module = makefile->TTCN3Modules + i;
2081 if (module->dir_name == NULL || !makefile->central_storage)
2082 /* If the file is in the current directory or
2083 * is not in the current directory but central directory is not used,
2084 * it goes into TTCN3_MODULES */
2085 print_file_name(fp, module);
2086 }
2087 fprint_extra_targets(fp, makefile->target_placement_list, "TTCN3_MODULES");
2088 if (makefile->preprocess) {
2089 fputs("\n\n"
af710487 2090 "# TTCN-3 modules to preprocess:\n"
970ed795
EL
2091 "TTCN3_PP_MODULES =", fp);
2092 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2093 const struct module_struct *module = makefile->TTCN3PPModules + i;
2094 if (module->dir_name == NULL || !makefile->central_storage)
2095 print_file_name(fp, module);
2096 }
2097 fprint_extra_targets(fp, makefile->target_placement_list, "TTCN3_PP_MODULES");
2098 }
2099 if (makefile->central_storage) {
2100 fputs("\n\n"
af710487 2101 "# TTCN-3 modules used from central project(s):\n"
2102 "BASE_TTCN3_MODULES =", fp);
2103 if (!makefile->linkingStrategy) {
2104 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2105 const struct module_struct *module = makefile->TTCN3Modules + i;
2106 /* Central storage used AND file is not in the current directory => it goes into BASE_TTCN3_MODULES */
2107 if (module->dir_name != NULL) print_file_name(fp, module);
2108 }
2109 if (makefile->preprocess) {
2110 fputs("\n\n"
2111 "# TTCN-3 modules to preprocess used from central project(s):\n"
2112 "BASE_TTCN3_PP_MODULES =", fp);
2113 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2114 const struct module_struct *module = makefile->TTCN3PPModules + i;
2115 if (module->dir_name != NULL && !isTtcnPPFileInLibrary(module->file_name))
2116 print_file_name(fp, module);
2117 }
2118 }
970ed795 2119 }
af710487 2120 else { // new linking strategy
2121 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2122 const struct module_struct *module = makefile->TTCN3Modules + i;
2123 /* Central storage used AND file is not in the current directory => it goes into BASE_TTCN3_MODULES */
2124 if (module->dir_name != NULL && !isTtcn3ModuleInLibrary(module->module_name))
2125 print_file_name(fp, module);
2126 }
970ed795 2127 fputs("\n\n"
af710487 2128 "# TTCN-3 library linked modules used from central project(s):\n"
2129 "BASE2_TTCN3_MODULES =", fp);
2130 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2131 const struct module_struct *module = makefile->TTCN3Modules + i;
2132 /* Central storage used AND file is not in the current directory => it goes into BASE_TTCN3_MODULES */
2133 if (module->dir_name != NULL && isTtcn3ModuleInLibrary(module->module_name))
2134 print_file_name(fp, module);
2135 }
2136 if (makefile->preprocess) {
2137 fputs("\n\n"
2138 "# TTCN-3 modules to preprocess used from central project(s):\n"
2139 "BASE_TTCN3_PP_MODULES =", fp);
2140 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2141 const struct module_struct *module = makefile->TTCN3PPModules + i;
2142 if (module->dir_name != NULL && !isTtcnPPFileInLibrary(module->file_name))
2143 print_file_name(fp, module);
2144 }
2145 fputs("\n\n"
2146 "# TTCN-3 library linked modules to preprocess used from central project(s):\n"
2147 "BASE2_TTCN3_PP_MODULES =", fp);
2148 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2149 const struct module_struct *module = makefile->TTCN3PPModules + i;
2150 if (module->dir_name != NULL && isTtcnPPFileInLibrary(module->file_name))
2151 print_file_name(fp, module);
2152 }
970ed795
EL
2153 }
2154 }
2155 }
2156 if (makefile->preprocess) {
2157 fputs("\n\n"
2158 "# Files to include in TTCN-3 preprocessed modules:\n"
2159 "TTCN3_INCLUDES =", fp);
2160 for (i = 0; i < makefile->nTTCN3IncludeFiles; i++)
af710487 2161 fprintf(fp, " %s", makefile->TTCN3IncludeFiles[i]);
970ed795
EL
2162 fprint_extra_targets(fp, makefile->target_placement_list, "TTCN3_INCLUDES");
2163 }
2164 fputs("\n\n"
2165 "# ASN.1 modules of this project:\n"
2166 "ASN1_MODULES =", fp);
2167 for (i = 0; i < makefile->nASN1Modules; i++) {
2168 const struct module_struct *module = makefile->ASN1Modules + i;
2169 if (module->dir_name == NULL || !makefile->central_storage)
af710487 2170 print_file_name(fp, module);
970ed795
EL
2171 }
2172 fprint_extra_targets(fp, makefile->target_placement_list, "ASN1_MODULES");
2173 if (makefile->central_storage) {
2174 fputs("\n\n"
af710487 2175 "# ASN.1 modules used from central project(s):\n"
2176 "BASE_ASN1_MODULES =", fp);
2177 if (!makefile->linkingStrategy) {
2178 for (i = 0; i < makefile->nASN1Modules; i++) {
2179 const struct module_struct *module = makefile->ASN1Modules + i;
2180 if (module->dir_name != NULL) print_file_name(fp, module);
2181 }
2182 }
2183 else {
2184 for (i = 0; i < makefile->nASN1Modules; i++) {
2185 const struct module_struct *module = makefile->ASN1Modules + i;
2186 if (module->dir_name != NULL && !isAsn1ModuleInLibrary(module->module_name))
2187 print_file_name(fp, module);
2188 }
2189 fputs("\n\n"
2190 "# ASN.1 library linked modules used from central project(s):\n"
2191 "BASE2_ASN1_MODULES =", fp);
2192 for (i = 0; i < makefile->nASN1Modules; i++) {
2193 const struct module_struct *module = makefile->ASN1Modules + i;
2194 if (module->dir_name != NULL && isAsn1ModuleInLibrary(module->module_name))
2195 print_file_name(fp, module);
2196 }
970ed795
EL
2197 }
2198 }
2199 if (makefile->preprocess) {
2200 fputs("\n\n"
2201 "# TTCN-3 source files generated by the C preprocessor:\n"
2202 "PREPROCESSED_TTCN3_MODULES =", fp);
2203 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2204 const struct module_struct *module = makefile->TTCN3PPModules + i;
af710487 2205 if (module->dir_name == NULL || !makefile->central_storage)
2206 print_preprocessed_file_name(fp, module);
970ed795
EL
2207 }
2208 if (makefile->central_storage) {
2209 fputs("\n\n"
2210 "# TTCN-3 files generated by the CPP used from central project(s):\n"
2211 "BASE_PREPROCESSED_TTCN3_MODULES =", fp);
af710487 2212 if (!makefile->linkingStrategy) {
2213 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2214 const struct module_struct *module = makefile->TTCN3PPModules + i;
2215 if (module->dir_name != NULL)
2216 print_preprocessed_file_name(fp, module);
2217 }
2218 }
2219 else { // new linking strategy
2220 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2221 const struct module_struct *module = makefile->TTCN3PPModules + i;
2222 if (module->dir_name != NULL && !isTtcnPPFileInLibrary(module->file_name))
2223 print_preprocessed_file_name(fp, module);
2224 }
2225 fputs("\n\n"
2226 "# TTCN-3 library linked files generated by the CPP used from central project(s):\n"
2227 "BASE2_PREPROCESSED_TTCN3_MODULES =", fp);
2228 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2229 const struct module_struct *module = makefile->TTCN3PPModules + i;
2230 if (module->dir_name != NULL && isTtcnPPFileInLibrary(module->file_name))
2231 print_preprocessed_file_name(fp, module);
2232 }
970ed795
EL
2233 }
2234 }
2235 }
3abe9331 2236 if (makefile->profiled_file_list) {
2237 if (makefile->profiled_file_list->next && !makefile->central_storage) {
2238 // merge all profiled file lists into one list
2239 fprintf(fp, "\n\n"
2240 "# Text file containing the list of profiled TTCN-3 files of "
2241 "this project:\n"
2242 "PROFILED_FILE_LIST = %s.merged\n"
2243 "PROFILED_FILE_LIST_SEGMENTS =",
2244 makefile->profiled_file_list->str);
2245 struct string_list* iter = makefile->profiled_file_list;
2246 while(iter != NULL) {
2247 fprintf(fp, " %s", iter->str);
2248 iter = iter->next;
2249 }
2250 }
2251 else {
2252 // only one profiled file list is needed
2253 fprintf(fp, "\n\n"
2254 "# Text file containing the list of profiled TTCN-3 files of "
2255 "this project:\n"
2256 "PROFILED_FILE_LIST = %s", makefile->profiled_file_list->str);
2257 }
2258 }
970ed795
EL
2259 fputs("\n\n"
2260 "# C++ source & header files generated from the TTCN-3 & ASN.1 "
2261 "modules of\n"
2262 "# this project:\n"
2263 "GENERATED_SOURCES =", fp);
2264 if (makefile->gnu_make && makefile->TTCN3ModulesRegular) {
2265 fputs(" $(TTCN3_MODULES:.ttcn=.cc)", fp);
2266 if (makefile->code_splitting_mode) {
2267 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2268 const struct module_struct *module = makefile->TTCN3Modules + i;
2269 if (module->dir_name == NULL || !makefile->central_storage)
2270 print_splitted_file_names(fp, makefile, module);
2271 }
2272 }
2273 if (makefile->preprocess) {
2274 fputs(" $(TTCN3_PP_MODULES:.ttcnpp=.cc)", fp);
2275 if (makefile->code_splitting_mode) {
2276 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2277 const struct module_struct *module = makefile->TTCN3PPModules + i;
2278 if (module->dir_name == NULL || !makefile->central_storage)
2279 print_splitted_file_names(fp, makefile, module);
2280 }
2281 }
2282 }
2283 } else {
2284 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2285 const struct module_struct *module = makefile->TTCN3Modules + i;
2286 if (module->dir_name == NULL || !makefile->central_storage) {
2287 print_generated_file_name(fp, module, FALSE, ".cc");
2288 if (makefile->code_splitting_mode)
2289 print_splitted_file_names(fp, makefile, module);
2290 }
2291 }
2292 if (makefile->preprocess) {
2293 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2294 const struct module_struct *module = makefile->TTCN3PPModules + i;
2295 if (module->dir_name == NULL || !makefile->central_storage) {
2296 print_generated_file_name(fp, module, FALSE, ".cc");
2297 if (makefile->code_splitting_mode)
2298 print_splitted_file_names(fp, makefile, module);
2299 }
2300 }
2301 }
2302 }
2303 if (makefile->gnu_make && makefile->ASN1ModulesRegular) {
2304 fputs(" $(ASN1_MODULES:.asn=.cc)", fp);
2305 if (makefile->code_splitting_mode) {
2306 for (i = 0; i < makefile->nASN1Modules; i++) {
2307 const struct module_struct *module = makefile->ASN1Modules + i;
2308 if (module->dir_name == NULL || !makefile->central_storage) {
2309 print_splitted_file_names(fp, makefile, module);
2310 }
2311 }
2312 }
2313 } else {
2314 for (i = 0; i < makefile->nASN1Modules; i++) {
2315 const struct module_struct *module = makefile->ASN1Modules + i;
2316 if (module->dir_name == NULL || !makefile->central_storage) {
2317 print_generated_file_name(fp, module, FALSE, ".cc");
2318 if (makefile->code_splitting_mode)
2319 print_splitted_file_names(fp, makefile, module);
2320 }
2321 }
2322 }
2323
2324 fputs("\nGENERATED_HEADERS =", fp);
2325 if (makefile->gnu_make) {
2326 fputs(" $(GENERATED_SOURCES:.cc=.hh)", fp);
af710487 2327 }
2328 else {
970ed795 2329 for (i = 0; i < makefile->nTTCN3Modules; i++) {
af710487 2330 const struct module_struct *module = makefile->TTCN3Modules + i;
2331 if (module->dir_name == NULL || !makefile->central_storage)
2332 print_generated_file_name(fp, module, FALSE, ".hh");
970ed795
EL
2333 }
2334 if (makefile->preprocess) {
2335 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2336 const struct module_struct *module = makefile->TTCN3PPModules + i;
2337 if (module->dir_name == NULL || !makefile->central_storage)
2338 print_generated_file_name(fp, module, FALSE, ".hh");
2339 }
2340 }
2341 for (i = 0; i < makefile->nASN1Modules; i++) {
af710487 2342 const struct module_struct *module = makefile->ASN1Modules + i;
2343 if (module->dir_name == NULL || !makefile->central_storage)
2344 print_generated_file_name(fp, module, FALSE, ".hh");
970ed795
EL
2345 }
2346 }
2347 if (makefile->central_storage) {
2348 fputs("\n\n"
2349 "# C++ source & header files generated from the TTCN-3 & ASN.1 "
2350 "modules of\n"
2351 "# central project(s):\n"
2352 "BASE_GENERATED_SOURCES =", fp);
2353 if (makefile->gnu_make && makefile->BaseTTCN3ModulesRegular) {
2354 fputs(" $(BASE_TTCN3_MODULES:.ttcn=.cc)", fp);
2355 if (makefile->code_splitting_mode) {
2356 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2357 const struct module_struct *module = makefile->TTCN3Modules + i;
2358 if (module->dir_name != NULL) {
2359 print_splitted_file_names(fp, makefile, module);
2360 }
2361 }
2362 }
2363 if (makefile->preprocess) {
2364 fputs(" $(BASE_TTCN3_PP_MODULES:.ttcnpp=.cc)", fp);
2365 if (makefile->code_splitting_mode) {
2366 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2367 const struct module_struct *module = makefile->TTCN3PPModules + i;
2368 if (module->dir_name != NULL) {
2369 print_splitted_file_names(fp, makefile, module);
2370 }
2371 }
2372 }
2373 }
2374 } else {
2375 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2376 const struct module_struct *module = makefile->TTCN3Modules + i;
2377 if (module->dir_name != NULL) {
2378 print_generated_file_name(fp, module, TRUE, ".cc");
2379 if (makefile->code_splitting_mode)
2380 print_splitted_file_names(fp, makefile, module);
2381 }
2382 }
2383 if (makefile->preprocess) {
2384 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2385 const struct module_struct *module = makefile->TTCN3PPModules + i;
2386 if (module->dir_name != NULL) {
2387 print_generated_file_name(fp, module, TRUE, ".cc");
2388 if (makefile->code_splitting_mode)
2389 print_splitted_file_names(fp, makefile, module);
2390 }
2391 }
2392 }
2393 }
2394 if (makefile->gnu_make && makefile->BaseASN1ModulesRegular) {
2395 fputs(" $(BASE_ASN1_MODULES:.asn=.cc)", fp);
2396 if (makefile->code_splitting_mode) {
2397 for (i = 0; i < makefile->nASN1Modules; i++) {
2398 const struct module_struct *module = makefile->ASN1Modules + i;
2399 if (module->dir_name != NULL) {
2400 print_splitted_file_names(fp, makefile, module);
2401 }
2402 }
2403 }
2404 } else {
2405 for (i = 0; i < makefile->nASN1Modules; i++) {
2406 const struct module_struct *module = makefile->ASN1Modules + i;
2407 if (module->dir_name != NULL) {
2408 print_generated_file_name(fp, module, TRUE, ".cc");
2409 if (makefile->code_splitting_mode)
2410 print_splitted_file_names(fp, makefile, module);
2411 }
2412 }
2413 }
2414 fputs("\nBASE_GENERATED_HEADERS =", fp);
2415 if (makefile->gnu_make) {
af710487 2416 fputs(" $(BASE_GENERATED_SOURCES:.cc=.hh)", fp);
970ed795 2417 } else {
af710487 2418 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2419 const struct module_struct *module = makefile->TTCN3Modules + i;
2420 if (module->dir_name != NULL)
2421 print_generated_file_name(fp, module, TRUE, ".hh");
2422 }
2423 if (makefile->preprocess) {
2424 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2425 const struct module_struct *module = makefile->TTCN3PPModules + i;
2426 if (module->dir_name != NULL)
2427 print_generated_file_name(fp, module, TRUE, ".hh");
2428 }
2429 }
2430 for (i = 0; i < makefile->nASN1Modules; i++) {
2431 const struct module_struct *module = makefile->ASN1Modules + i;
2432 if (module->dir_name != NULL)
2433 print_generated_file_name(fp, module, TRUE, ".hh");
2434 }
2435 }
2436 }
2437
2438 if (makefile->linkingStrategy) {
2439 fputs("\n\n"
2440 "# C++ source & header files generated from the TTCN-3 "
2441 " library linked modules of\n"
2442 "# central project(s):\n"
2443 "BASE2_GENERATED_SOURCES =", fp);
2444 if (makefile->gnu_make && makefile->BaseTTCN3ModulesRegular) {
2445 fputs(" $(BASE2_TTCN3_MODULES:.ttcn=.cc)", fp);
2446 fputs(" $(BASE2_ASN1_MODULES:.asn=.cc)", fp);
2447 if (makefile->preprocess)
2448 fputs(" $(BASE2_TTCN3_PP_MODULES:.ttcnpp=.cc)", fp);
2449 }
2450 else {
2451 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2452 const struct module_struct *module = makefile->TTCN3Modules + i;
2453 if (module->dir_name != NULL && isTtcn3ModuleInLibrary(module->module_name)) {
2454 print_generated_file_name(fp, module, TRUE, ".cc");
2455 }
2456 }
2457 if (makefile->preprocess) {
2458 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2459 const struct module_struct *module = makefile->TTCN3PPModules + i;
2460 if (module->dir_name != NULL && isTtcnPPFileInLibrary(module->file_name)) {
2461 print_generated_file_name(fp, module, TRUE, ".cc");
2462 }
2463 }
2464 }
970ed795 2465 }
af710487 2466
2467 fputs("\nBASE2_GENERATED_HEADERS =", fp);
2468 if (makefile->gnu_make) {
2469 fputs(" $(BASE2_GENERATED_SOURCES:.cc=.hh)", fp);
2470 }
2471 else
2472 ERROR("the usage of 'Z' flag requires GNU make");
970ed795 2473 }
af710487 2474
970ed795
EL
2475 fputs("\n\n"
2476 "# C/C++ Source & header files of Test Ports, external functions "
af710487 2477 "and\n"
2478 "# other modules:\n"
970ed795
EL
2479 "USER_SOURCES =", fp);
2480 for (i = 0; i < makefile->nUserFiles; i++) {
2481 const struct user_struct *user = makefile->UserFiles + i;
2482 if (user->dir_name == NULL || !makefile->central_storage)
af710487 2483 print_source_name(fp, user);
970ed795
EL
2484 }
2485 fprint_extra_targets(fp, makefile->target_placement_list, "USER_SOURCES");
2486 fputs("\nUSER_HEADERS =", fp);
2487 if (makefile->gnu_make && makefile->UserHeadersRegular) {
2488 fputs(" $(USER_SOURCES:.cc=.hh)", fp);
2489 } else {
2490 for (i = 0; i < makefile->nUserFiles; i++) {
af710487 2491 const struct user_struct *user = makefile->UserFiles + i;
2492 if (user->dir_name == NULL || !makefile->central_storage)
2493 print_header_name(fp, user);
970ed795
EL
2494 }
2495 }
2496 fprint_extra_targets(fp, makefile->target_placement_list, "USER_HEADERS");
2497 if (makefile->central_storage) {
2498 fputs("\n\n"
2499 "# C/C++ Source & header files of Test Ports, external functions "
af710487 2500 "and\n"
2501 "# other modules used from central project(s):\n"
970ed795 2502 "BASE_USER_SOURCES =", fp);
af710487 2503 if (!makefile->linkingStrategy) {
2504 for (i = 0; i < makefile->nUserFiles; i++) {
2505 const struct user_struct *user = makefile->UserFiles + i;
2506 if (user->dir_name != NULL) {
2507 print_source_name(fp, user);
2508 }
2509 }
2510 fputs("\nBASE_USER_HEADERS =", fp);
2511 if (makefile->gnu_make && makefile->BaseUserHeadersRegular) {
2512 fputs(" $(BASE_USER_SOURCES:.cc=.hh)", fp);
2513 }
2514 else {
2515 for (i = 0; i < makefile->nUserFiles; i++) {
2516 const struct user_struct *user = makefile->UserFiles + i;
2517 if (user->dir_name != NULL)
2518 print_header_name(fp, user);
2519 }
2520 }
970ed795 2521 }
af710487 2522 else {
2523 for (i = 0; i < makefile->nUserFiles; i++) {
2524 const struct user_struct *user = makefile->UserFiles + i;
2525 if (user->dir_name != NULL && !isSourceFileInLibrary(user->source_name)) {
2526 print_source_name(fp, user);
2527 }
2528 }
2529 fputs("\nBASE_USER_HEADERS =", fp);
2530 if (makefile->gnu_make && makefile->BaseUserHeadersRegular) {
2531 fputs(" $(BASE_USER_SOURCES:.cc=.hh)", fp);
2532 }
2533 else {
2534 for (i = 0; i < makefile->nUserFiles; i++) {
2535 const struct user_struct *user = makefile->UserFiles + i;
2536 if (user->dir_name != NULL && !isHeaderFileInLibrary(user->header_name))
2537 print_header_name(fp, user);
2538 }
2539 }
2540
2541 fputs("\n\n"
2542 "# C/C++ Source & header files of Test Ports, external functions "
2543 "and\n"
2544 "# other modules used from library linked central project(s):\n"
2545 "BASE2_USER_SOURCES =", fp);
2546 for (i = 0; i < makefile->nUserFiles; i++) {
2547 const struct user_struct *user = makefile->UserFiles + i;
2548 if (user->dir_name != NULL && isSourceFileInLibrary(user->source_name)) {
2549 print_source_name(fp, user);
2550 }
2551 }
2552 fputs("\nBASE2_USER_HEADERS =", fp);
2553 if (makefile->gnu_make && makefile->BaseUserHeadersRegular) {
2554 fputs(" $(BASE2_USER_SOURCES:.cc=.hh)", fp);
2555 }
2556 else {
2557 for (i = 0; i < makefile->nUserFiles; i++) {
2558 const struct user_struct *user = makefile->UserFiles + i;
2559 if (user->dir_name != NULL && isHeaderFileInLibrary(user->header_name))
2560 print_header_name(fp, user);
2561 }
2562 }
970ed795
EL
2563 }
2564 }
970ed795
EL
2565 if (makefile->dynamic) {
2566 fputs("\n\n"
2567 "# Shared object files of this project:\n"
2568 "SHARED_OBJECTS =", fp);
2569 if (makefile->gnu_make) {
2570 fputs(" $(GENERATED_SOURCES:.cc=.so)", fp);
2571 } else {
2572 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2573 const struct module_struct *module = makefile->TTCN3Modules + i;
2574 if (module->dir_name == NULL || !makefile->central_storage) {
2575 print_generated_file_name(fp, module, FALSE, ".so");
2576 if (makefile->code_splitting_mode != NULL)
2577 if (strcmp(makefile->code_splitting_mode, "-U type") == 0) {
2578 print_generated_file_name(fp, module, FALSE, "_seq.so");
2579 print_generated_file_name(fp, module, FALSE, "_set.so");
2580 print_generated_file_name(fp, module, FALSE, "_seqof.so");
2581 print_generated_file_name(fp, module, FALSE, "_setof.so");
2582 print_generated_file_name(fp, module, FALSE, "_union.so");
2583 }
2584 }
2585 }
2586 if (makefile->preprocess) {
2587 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2588 const struct module_struct *module = makefile->TTCN3PPModules + i;
2589 if (module->dir_name == NULL || !makefile->central_storage) {
2590 print_generated_file_name(fp, module, FALSE, ".so");
2591 if (makefile->code_splitting_mode != NULL)
2592 if (strcmp(makefile->code_splitting_mode, "-U type") == 0) {
2593 print_generated_file_name(fp, module, FALSE, "_seq.so");
2594 print_generated_file_name(fp, module, FALSE, "_set.so");
2595 print_generated_file_name(fp, module, FALSE, "_seqof.so");
2596 print_generated_file_name(fp, module, FALSE, "_setof.so");
2597 print_generated_file_name(fp, module, FALSE, "_union.so");
2598 }
2599 }
2600 }
2601 }
2602 for (i = 0; i < makefile->nASN1Modules; i++) {
2603 const struct module_struct *module = makefile->ASN1Modules + i;
2604 if (module->dir_name == NULL || !makefile->central_storage) {
2605 print_generated_file_name(fp, module, FALSE, ".so");
2606 if (makefile->code_splitting_mode != NULL)
2607 if (strcmp(makefile->code_splitting_mode, "-U type") == 0) {
2608 print_generated_file_name(fp, module, FALSE, "_seq.so");
2609 print_generated_file_name(fp, module, FALSE, "_set.so");
2610 print_generated_file_name(fp, module, FALSE, "_seqof.so");
2611 print_generated_file_name(fp, module, FALSE, "_setof.so");
2612 print_generated_file_name(fp, module, FALSE, "_union.so");
2613 }
2614 }
2615 }
2616 }
2617 if (makefile->gnu_make && makefile->UserSourcesRegular) {
2618 fputs(" $(USER_SOURCES:.cc=.so)", fp);
2619 } else {
2620 for (i = 0; i < makefile->nUserFiles; i++) {
2621 const struct user_struct *user = makefile->UserFiles + i;
2622 if (user->dir_name == NULL || !makefile->central_storage)
2623 print_shared_object_name(fp, user);
2624 }
2625 }
2626 }
2627
2628 fputs("\n\n"
2629 "# Object files of this project that are needed for the executable "
af710487 2630 "test suite:\n"
970ed795
EL
2631 "OBJECTS = $(GENERATED_OBJECTS) $(USER_OBJECTS)\n\n" /* never := */
2632 "GENERATED_OBJECTS =", fp);
2633 if (makefile->gnu_make) {
2634 fputs(" $(GENERATED_SOURCES:.cc=.o)", fp);
2635 } else {
2636 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2637 const struct module_struct *module = makefile->TTCN3Modules + i;
2638 if (module->dir_name == NULL || !makefile->central_storage) {
2639 print_generated_file_name(fp, module, FALSE, ".o");
2640 if (makefile->code_splitting_mode != NULL)
2641 if (strcmp(makefile->code_splitting_mode, "-U type") == 0) {
2642 print_generated_file_name(fp, module, FALSE, "_seq.o");
2643 print_generated_file_name(fp, module, FALSE, "_set.o");
2644 print_generated_file_name(fp, module, FALSE, "_seqof.o");
2645 print_generated_file_name(fp, module, FALSE, "_setof.o");
2646 print_generated_file_name(fp, module, FALSE, "_union.o");
2647 }
2648 }
2649 }
2650 if (makefile->preprocess) {
2651 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2652 const struct module_struct *module = makefile->TTCN3PPModules + i;
2653 if (module->dir_name == NULL || !makefile->central_storage) {
2654 print_generated_file_name(fp, module, FALSE, ".o");
2655 if (makefile->code_splitting_mode != NULL)
2656 if (strcmp(makefile->code_splitting_mode, "-U type") == 0) {
2657 print_generated_file_name(fp, module, FALSE, "_seq.o");
2658 print_generated_file_name(fp, module, FALSE, "_set.o");
2659 print_generated_file_name(fp, module, FALSE, "_seqof.o");
2660 print_generated_file_name(fp, module, FALSE, "_setof.o");
2661 print_generated_file_name(fp, module, FALSE, "_union.o");
2662 }
2663 }
2664 }
2665 }
2666 for (i = 0; i < makefile->nASN1Modules; i++) {
2667 const struct module_struct *module = makefile->ASN1Modules + i;
2668 if (module->dir_name == NULL || !makefile->central_storage) {
2669 print_generated_file_name(fp, module, FALSE, ".o");
2670 if (makefile->code_splitting_mode != NULL)
2671 if (strcmp(makefile->code_splitting_mode, "-U type") == 0) {
2672 print_generated_file_name(fp, module, FALSE, "_seq.o");
2673 print_generated_file_name(fp, module, FALSE, "_set.o");
2674 print_generated_file_name(fp, module, FALSE, "_seqof.o");
2675 print_generated_file_name(fp, module, FALSE, "_setof.o");
2676 print_generated_file_name(fp, module, FALSE, "_union.o");
2677 }
2678 }
2679 }
2680 }
2681
2682 fputs("\n\nUSER_OBJECTS =", fp);
2683 if (makefile->gnu_make && makefile->UserSourcesRegular) {
2684 fputs(" $(USER_SOURCES:.cc=.o)", fp);
2685 } else {
2686 for (i = 0; i < makefile->nUserFiles; i++) {
2687 const struct user_struct *user = makefile->UserFiles + i;
2688 if (user->dir_name == NULL || !makefile->central_storage)
2689 print_object_name(fp, user);
2690 }
2691 }
2692 fprint_extra_targets(fp, makefile->target_placement_list, "USER_OBJECTS");
2693
2694 if (makefile->gcc_dep) {
2695 /* GNU Make processes included makefiles in reverse order. By putting
2696 * user sources first, their .d will be generated last, after the
2697 * GENERATED_SOURCES (and GENERATED_HEADERS) have been created.
2698 * This avoid spurious errors during incremental dependency generation */
2699 fputs("\n\nDEPFILES = $(USER_OBJECTS:.o=.d) $(GENERATED_OBJECTS:.o=.d)", fp);
2700 }
2701
2702 if (makefile->central_storage) {
2703 if (makefile->dynamic) {
2704 fputs("\n\n"
2705 "# Shared object files of central project(s):\n"
2706 "BASE_SHARED_OBJECTS =", fp);
af710487 2707 if (!makefile->linkingStrategy) {
2708 if (makefile->gnu_make) {
2709 fputs(" $(BASE_GENERATED_SOURCES:.cc=.so)", fp);
2710 }
2711 else {
2712 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2713 const struct module_struct *module = makefile->TTCN3Modules + i;
2714 if (module->dir_name != NULL)
2715 print_generated_file_name(fp, module, TRUE, ".so");
2716 }
2717 if (makefile->preprocess) {
2718 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
2719 const struct module_struct *module =
2720 makefile->TTCN3PPModules + i;
2721 if (module->dir_name != NULL)
2722 print_generated_file_name(fp, module, TRUE, ".so");
2723 }
2724 }
2725 for (i = 0; i < makefile->nASN1Modules; i++) {
2726 const struct module_struct *module = makefile->ASN1Modules + i;
2727 if (module->dir_name != NULL)
2728 print_generated_file_name(fp, module, TRUE, ".so");
2729 }
2730 }
2731 if (makefile->gnu_make && makefile->BaseUserSourcesRegular) {
2732 fputs(" $(BASE_USER_SOURCES:.cc=.so)", fp);
2733 }
2734 else {
2735 for (i = 0; i < makefile->nUserFiles; i++) {
2736 const struct user_struct *user = makefile->UserFiles + i;
2737 if (user->dir_name != NULL)
2738 print_shared_object_name(fp, user);
2739 }
2740 }
2741 }
2742 else { // new linkingStrategy
2743 if (makefile->gnu_make) {
2744 fputs(" $(BASE_GENERATED_SOURCES:.cc=.so)", fp);
2745 }
2746 else
2747 ERROR("the usage of 'Z' flag requires GNU make");
2748
2749 if (makefile->gnu_make && makefile->BaseUserSourcesRegular) {
2750 fputs(" $(BASE_USER_SOURCES:.cc=.so)", fp);
2751 }
2752 else {
2753 for (i = 0; i < makefile->nUserFiles; i++) {
2754 const struct user_struct *user = makefile->UserFiles + i;
2755 if (user->dir_name != NULL && !isSourceFileInLibrary(user->source_name))
2756 print_shared_object_name(fp, user);
2757 }
2758 }
2759 }
2760 } /* if dynamic */
2761 fputs("\n\n"
2762 "# Object files of central project(s) that are needed for the "
2763 "executable test suite:\n"
2764 "BASE_OBJECTS =", fp);
2765 if (!makefile->linkingStrategy) {
970ed795 2766 if (makefile->gnu_make) {
af710487 2767 fputs(" $(BASE_GENERATED_SOURCES:.cc=.o)", fp);
2768 }
2769 else {
970ed795
EL
2770 for (i = 0; i < makefile->nTTCN3Modules; i++) {
2771 const struct module_struct *module = makefile->TTCN3Modules + i;
2772 if (module->dir_name != NULL)
af710487 2773 print_generated_file_name(fp, module, TRUE, ".o");
970ed795
EL
2774 }
2775 if (makefile->preprocess) {
2776 for (i = 0; i < makefile->nTTCN3PPModules; i++) {
af710487 2777 const struct module_struct *module = makefile->TTCN3PPModules + i;
970ed795 2778 if (module->dir_name != NULL)
af710487 2779 print_generated_file_name(fp, module, TRUE, ".o");
970ed795
EL
2780 }
2781 }
2782 for (i = 0; i < makefile->nASN1Modules; i++) {
2783 const struct module_struct *module = makefile->ASN1Modules + i;
2784 if (module->dir_name != NULL)
af710487 2785 print_generated_file_name(fp, module, TRUE, ".o");
970ed795
EL
2786 }
2787 }
2788 if (makefile->gnu_make && makefile->BaseUserSourcesRegular) {
af710487 2789 fputs(" $(BASE_USER_SOURCES:.cc=.o)", fp);
2790 }
2791 else {
970ed795
EL
2792 for (i = 0; i < makefile->nUserFiles; i++) {
2793 const struct user_struct *user = makefile->UserFiles + i;
2794 if (user->dir_name != NULL)
af710487 2795 print_object_name(fp, user);
970ed795
EL
2796 }
2797 }
af710487 2798 }
2799 else { // new linkingStrategy
2800 if (makefile->gnu_make) {
2801 fputs(" $(BASE_GENERATED_SOURCES:.cc=.o)", fp);
970ed795 2802 }
af710487 2803 else
2804 ERROR("the usage of 'Z' flag requires GNU make");
2805
2806 if (makefile->gnu_make && makefile->BaseUserSourcesRegular) {
2807 fputs(" $(BASE_USER_SOURCES:.cc=.o)", fp);
970ed795 2808 }
af710487 2809 else {
2810 for (i = 0; i < makefile->nUserFiles; i++) {
2811 const struct user_struct *user = makefile->UserFiles + i;
2812 if (user->dir_name != NULL && !isSourceFileInLibrary(user->source_name))
2813 print_object_name(fp, user);
2814 }
970ed795
EL
2815 }
2816 }
af710487 2817 }
2818 if (makefile->linkingStrategy) {
2819 fputs("\n\n"
2820 "# Object files of library linked central project(s) that are needed for the "
2821 "executable test suite:\n"
2822 "BASE2_OBJECTS =", fp);
2823 if (makefile->gnu_make) {
2824 if (makefile->dynamic)
2825 fputs(" $(BASE2_GENERATED_SOURCES:.cc=.so)", fp);
2826 else
2827 fputs(" $(BASE2_GENERATED_SOURCES:.cc=.o)", fp);
2828 }
2829 else ERROR("the usage of 'Z' flag requires GNU make");
2830
970ed795 2831 if (makefile->gnu_make && makefile->BaseUserSourcesRegular) {
af710487 2832 if (makefile->dynamic)
2833 fputs(" $(BASE2_USER_SOURCES:.cc=.so)", fp);
2834 else
2835 fputs(" $(BASE2_USER_SOURCES:.cc=.o)", fp);
2836 }
2837 else {
970ed795
EL
2838 for (i = 0; i < makefile->nUserFiles; i++) {
2839 const struct user_struct *user = makefile->UserFiles + i;
af710487 2840 if (user->dir_name != NULL && isSourceFileInLibrary(user->source_name)) {
2841 if (makefile->dynamic)
2842 print_shared_object_name(fp, user);
2843 else
2844 print_object_name(fp, user);
2845 }
2846 }
2847 }
2848 if (makefile->hierarchical) {
2849 fputs("\n\n"
2850 "#Libraries of referenced project(s) that are needed for the "
2851 "executable or library target:\n"
2852 "BASE2_LIBRARY =", fp);
2853 struct string2_list* head = getLinkerLibs(makefile->project_name);
2854 struct string2_list* act_elem = head;
2855 while (act_elem) {
2856 if (act_elem->str2) {
2857 fputs(" ", fp);
2858 fprintf(fp, "%s/lib%s.%s", act_elem->str1, act_elem->str2,
2859 isDynamicLibrary(act_elem->str2) ? "so" : "a");
2860 }
2861 act_elem = act_elem->next;
970ed795 2862 }
af710487 2863 free_string2_list(head);
970ed795
EL
2864 }
2865 }
af710487 2866
970ed795 2867 fputs("\n\n"
af710487 2868 "# Other files of the project (Makefile, configuration files, etc.)\n"
2869 "# that will be added to the archived source files:\n"
2870 "OTHER_FILES =", fp);
970ed795
EL
2871 for (i = 0; i < makefile->nOtherFiles; i++)
2872 fprintf(fp, " %s", makefile->OtherFiles[i]);
2873 fprint_extra_targets(fp, makefile->target_placement_list, "OTHER_FILES");
2874
2875 if (makefile->ets_name) {
2876 const char *ets_suffix = NULL;
2877 /* EXECUTABLE variable */
2878 fprintf(fp, "\n\n"
2879 "# The name of the executable test suite:\n"
2880 "EXECUTABLE = %s", makefile->ets_name);
2881#ifdef WIN32
2882 {
2883 /* add the .exe suffix unless it is already present */
2884 ets_suffix = get_suffix(makefile->ets_name);
2885 if (ets_suffix == NULL || strcmp(ets_suffix, "exe"))
2886 fputs(".exe", fp);
2887 }
2888#endif
af710487 2889 fputs("\n\n", fp);
2890 if (makefile->linkingStrategy) {
2891#ifndef WIN32
2892 fputs("DYNAMIC_LIBRARY = lib$(EXECUTABLE).so\n", fp);
2893 fputs("STATIC_LIBRARY = lib$(EXECUTABLE).a\n", fp);
2894#else
2895 char* name_prefix = cut_suffix(makefile->ets_name);
2896 fprintf(fp, "DYNAMIC_LIBRARY = lib%s.so\n", name_prefix);
2897 fprintf(fp, "STATIC_LIBRARY = lib%s.a\n", name_prefix);
2898 Free(name_prefix);
2899#endif
2900 }
970ed795
EL
2901 /* LIBRARY variable */
2902 ets_suffix = get_suffix(makefile->ets_name);
2903 if (ets_suffix != NULL && !strcmp(ets_suffix, "exe")) {
2904 char* name_prefix = cut_suffix(makefile->ets_name);
af710487 2905 fprintf(fp, "\n\nLIBRARY = %s%s%s\n", "lib", name_prefix ? name_prefix : "library",
2906 makefile->dynamic ? ".so" : ".a");
2907 Free(name_prefix);
970ed795 2908 }
af710487 2909 else {
2910#ifndef WIN32
2911 fprintf(fp, "\n\nLIBRARY = lib$(EXECUTABLE)%s\n",
2912 makefile->dynamic ? ".so" : ".a");
2913#else
2914 fprintf(fp, "\n\nLIBRARY = lib%s%s\n",
2915 makefile->ets_name, makefile->dynamic ? ".so" : ".a");
2916#endif
2917 }
970ed795
EL
2918
2919 } else {
2920 fputs("\n\n"
2921 "# The name of the executable test suite:\n"
2922 "EXECUTABLE =\n"
2923 "LIBRARY =\n", fp);
2924 }
af710487 2925 if (!makefile->linkingStrategy || !buildObjects(makefile->project_name, add_refd_prjs)) {
2926 fprintf(fp, "\n"
970ed795 2927 "TARGET = $(%s)", makefile->library ? "LIBRARY" : "EXECUTABLE");
af710487 2928 }
2929 else {
2930 if (makefile->dynamic) {
2931 fputs("\n"
2932 "TARGET = $(SHARED_OBJECTS)", fp);
2933 }
2934 else {
2935 fputs("\n"
2936 "TARGET = $(OBJECTS)", fp);
2937 }
2938 }
970ed795
EL
2939 fputs("\n\n"
2940 "#\n"
2941 "# Do not modify these unless you know what you are doing...\n"
2942 "# Platform specific additional libraries:\n"
2943 "#\n", fp);
2944
5ea46818 2945 fputs("SOLARIS_LIBS = -lsocket -lnsl -lxml2", fp);
970ed795
EL
2946#ifdef USAGE_STATS
2947 fputs(" -lresolv", fp);
5ea46818
BB
2948#endif
2949#ifdef ADVANCED_DEBUGGER_UI
2950 fputs(" -lcurses", fp);
970ed795
EL
2951#endif
2952 if (makefile->solspeclibraries) {
2953 struct string_list* act_elem = makefile->solspeclibraries;
2954 while (act_elem) {
2955 if (act_elem->str) {
2956 fprintf(fp, " -l%s", act_elem->str);
2957 }
2958 act_elem = act_elem->next;
2959 }
2960 }
2961 fputs("\n", fp);
2962
5ea46818 2963 fputs("SOLARIS8_LIBS = -lsocket -lnsl -lxml2", fp);
970ed795
EL
2964#ifdef USAGE_STATS
2965 fputs(" -lresolv", fp);
5ea46818
BB
2966#endif
2967#ifdef ADVANCED_DEBUGGER_UI
2968 fputs(" -lcurses", fp);
970ed795
EL
2969#endif
2970 if (makefile->sol8speclibraries) {
2971 struct string_list* act_elem = makefile->sol8speclibraries;
2972 while (act_elem) {
2973 if (act_elem->str) {
2974 fprintf(fp, " -l%s", act_elem->str);
2975 }
2976 act_elem = act_elem->next;
2977 }
2978 }
2979 fputs("\n", fp);
2980
5ea46818 2981 fputs("LINUX_LIBS = -lxml2", fp);
970ed795
EL
2982#ifdef USAGE_STATS
2983 fputs(" -lpthread -lrt", fp);
5ea46818
BB
2984#endif
2985#ifdef ADVANCED_DEBUGGER_UI
2986 fputs(" -lncurses", fp);
970ed795
EL
2987#endif
2988 if (makefile->linuxspeclibraries) {
2989 struct string_list* act_elem = makefile->linuxspeclibraries;
2990 while (act_elem) {
2991 if (act_elem->str) {
2992 fprintf(fp, " -l%s", act_elem->str);
2993 }
2994 act_elem = act_elem->next;
2995 }
2996 }
2997 fputs("\n", fp);
2998
5ea46818
BB
2999 fputs("FREEBSD_LIBS = -lxml2", fp);
3000#ifdef ADVANCED_DEBUGGER_UI
3001 fputs(" -lncurses", fp);
3002#endif
970ed795
EL
3003 if (makefile->freebsdspeclibraries) {
3004 struct string_list* act_elem = makefile->freebsdspeclibraries;
3005 while (act_elem) {
3006 if (act_elem->str) {
3007 fprintf(fp, " -l%s", act_elem->str);
3008 }
3009 act_elem = act_elem->next;
3010 }
3011 }
3012 fputs("\n", fp);
3013
5ea46818
BB
3014 fputs("WIN32_LIBS = -lxml2", fp);
3015#ifdef ADVANCED_DEBUGGER_UI
3016 fputs(" -lncurses", fp);
3017#endif
970ed795
EL
3018 if (makefile->win32speclibraries) {
3019 struct string_list* act_elem = makefile->win32speclibraries;
3020 while (act_elem) {
3021 if (act_elem->str) {
3022 fprintf(fp, " -l%s", act_elem->str);
3023 }
3024 act_elem = act_elem->next;
3025 }
3026 }
3027 fputs("\n\n", fp);
3028
3029 fputs("#\n"
3030 "# Rules for building the executable...\n"
3031 "#\n\n", fp);
3032 fprintf(fp, "all:%s $(TARGET) ;\n\n", add_refd_prjs?" referenced-all":"");
3033
3034 if (makefile->dynamic) {
3035 fprintf(fp, "shared_objects:%s $(SHARED_OBJECTS) ;\n\n", add_refd_prjs?" referenced-shared_objects":"");
3036 }
3037
3038 fprintf(fp,
3039 "executable:%s $(EXECUTABLE) ;\n\n"
3040 "library:%s $(LIBRARY) ;\n\n"
3041 "objects:%s $(OBJECTS) compile;\n\n", add_refd_prjs?" referenced-executable":"", add_refd_prjs?" referenced-library":"", add_refd_prjs?" referenced-objects":"");
3042
3043 /* target $(EXECUTABLE) */
3044 if (makefile->dynamic && makefile->library) {
3045 /* There is no need to create the .so for all the source files */
3046 fputs("$(EXECUTABLE): $(LIBRARY)\n"
3047 "\tif $(CXX) $(LDFLAGS) -o $@ $(LIBRARY)", fp);
af710487 3048 }
3049 else {
3050 fprintf(fp, "$(EXECUTABLE): %s", makefile->dynamic ? "$(SHARED_OBJECTS)" : "$(OBJECTS)");
3051 if (!makefile->linkingStrategy) { // use the old linking method
970ed795
EL
3052 if (makefile->central_storage) {
3053 if (makefile->dynamic) {
3054 fputs(" $(BASE_SHARED_OBJECTS)", fp);
3055 } else {
3056 fputs(" $(BASE_OBJECTS)", fp);
3057 }
3058 }
af710487 3059 }
3060 else {
3061 if (!makefile->library) {
970ed795 3062 if (makefile->dynamic) {
af710487 3063 fputs(" $(BASE_SHARED_OBJECTS)", fp);
3064 }
3065 else {
3066 fputs(" $(BASE_OBJECTS)", fp);
3067 }
3068 if (makefile->hierarchical) {
3069 fputs(" $(BASE2_LIBRARY)", fp);
3070 }
3071 }
3072 }
3073 fprintf(fp, "\n"
3074 "\tif $(CXX) $(LDFLAGS) -o $@ %s",
3075#if defined (SOLARIS) || defined (SOLARIS8)
3076 "");
3077#else
3078 makefile->dynamic ? "-Wl,--no-as-needed " : ""); /* start writing the link step */
3079#endif
3080 if (makefile->gnu_make) fputs("$^", fp);
3081 else {
3082 if (makefile->dynamic) {
3083 fputs("$(SHARED_OBJECTS)", fp);
970ed795 3084 if (makefile->central_storage)
af710487 3085 fputs(" $(BASE_SHARED_OBJECTS)", fp);
3086 }
3087 else {
3088 fputs("$(OBJECTS)", fp);
970ed795 3089 if (makefile->central_storage)
af710487 3090 fputs(" $(BASE_OBJECTS)", fp);
3091 }
970ed795
EL
3092 }
3093 }
3094
3095 if (makefile->additionalObjects) {
3096 struct string_list* act_elem = makefile->additionalObjects;
3097 while (act_elem) {
3098 if (act_elem->str) {
3099 fprintf(fp, " %s", act_elem->str);
3100 }
3101 act_elem = act_elem->next;
3102 }
3103 }
3104
3105 fprintf(fp, " \\\n"
3106 "\t-L$(TTCN3_DIR)/lib -l$(TTCN3_LIB)"
3107 " \\\n"
3108 "\t-L$(OPENSSL_DIR)/lib -lcrypto");
af710487 3109 if (!makefile->linkingStrategy) {
3110 if (makefile->linkerlibraries) {
3111 struct string_list* act_elem = makefile->linkerlibraries;
3112 while (act_elem) {
3113 if (act_elem->str) {
3114 fprintf(fp, " -l%s", act_elem->str);
3115 }
3116 act_elem = act_elem->next;
970ed795 3117 }
970ed795 3118 }
af710487 3119 if (makefile->linkerlibsearchpath) {
3120 struct string_list* act_elem = makefile->linkerlibsearchpath;
3121 while (act_elem) {
3122 if (act_elem->str) {
3123 fprintf(fp, " -L%s", act_elem->str);
3124 }
3125 act_elem = act_elem->next;
970ed795 3126 }
970ed795 3127 }
af710487 3128 fprintf(fp, " \\\n"
3129 "\t-L$(XMLDIR)/lib $($(PLATFORM)_LIBS); \\\n"
3130 "\tthen : ; else $(TTCN3_DIR)/bin/titanver $(OBJECTS); exit 1; fi\n");
3131 }
3132 else { // new linking strategy
3133 fputs (" \\\n", fp);
3134 if (makefile->linkerlibraries && !makefile->library) {
3135 struct string2_list* head = getLinkerLibs(makefile->project_name);
3136 struct string2_list* act_elem = head;
3137 while (act_elem) {
3138 if (act_elem->str1 && act_elem->str2) {
3139 fprintf(fp, "\t-L%s -Wl,-rpath=%s -l%s \\\n", act_elem->str1, act_elem->str1, act_elem->str2);
3140 }
3141 act_elem = act_elem->next;
3142 }
3143 free_string2_list(head);
3144
3abe9331 3145 struct string_list* act_head = getExternalLibPaths(makefile->project_name);
af710487 3146 struct string_list* act_ext_elem = act_head;
3147 while (act_ext_elem) {
3148 if (act_ext_elem->str) {
3149 fprintf(fp, "\t-L%s \\\n", act_ext_elem->str);
3150 }
3151 act_ext_elem = act_ext_elem->next;
3152 }
3153 free_string_list(act_head);
3154 act_head = getExternalLibs(makefile->project_name);
3155 act_ext_elem = act_head;
3156 while (act_ext_elem) {
3157 if (act_ext_elem->str) {
3158 fprintf(fp, "\t-l%s \\\n", act_ext_elem->str);
3159 }
3160 act_ext_elem = act_ext_elem->next;
3161 }
3162 free_string_list(act_head);
3163 }
3164 fprintf(fp,
3165 "\t-L$(XMLDIR)/lib $($(PLATFORM)_LIBS); \\\n"
3166 "\tthen : ; else $(TTCN3_DIR)/bin/titanver $(OBJECTS); exit 1; fi\n");
970ed795 3167 }
970ed795
EL
3168 /* If the compiler will not be run because there are no TTCN(PP) or ASN.1
3169 * files, create the "compile" marker file which is checked by the
3170 * superior makefile if using this project as central storage */
3171 if (!run_compiler) fputs("\ttouch compile\n", fp);
3172 /* End of target $(EXECUTABLE) */
3173
3174 /* target $(LIBRARY) */
3175 if (makefile->dynamic) {
af710487 3176 fprintf(fp, "\n"
3177 "$(LIBRARY): $(OBJECTS)%s\n"
3178 "\t$(CXX) -shared -o $@ $(OBJECTS)",
3179 makefile->hierarchical ? " $(BASE2_LIBRARY)" : "");
3180 if (makefile->central_storage && !makefile->linkingStrategy) {
3181 fputs(" $(BASE_SHARED_OBJECTS) ;\n"
3182 "\tln -s $@ $(subst lib, ,$@) > /dev/null 2>&1 ;", fp);
970ed795 3183 }
af710487 3184 if (makefile->linkingStrategy) {
3185 struct string2_list* head = getLinkerLibs(makefile->project_name);
3186 struct string2_list* act_elem = head;
3187 // If the project is Executable on Top Level the linker can link the *.a and *.so together
3188 while (act_elem && !isTopLevelExecutable(makefile->project_name)) {
3189 if (act_elem->str1 && act_elem->str2 && isDynamicLibrary(act_elem->str2)) {
3190 fputs(" \\\n", fp);
3191 fprintf(fp, "\t-L%s -Wl,-rpath=%s -l%s", act_elem->str1, act_elem->str1, act_elem->str2);
3192 }
3193 else {
3194 const char* mainLibName = getLibFromProject(makefile->project_name);
3195 ERROR("Library archive 'lib%s.a' cannot be linked to dynamic library 'lib%s.so' "
3196 "in project '%s' ",
3197 act_elem->str2, mainLibName ? mainLibName : "", makefile->project_name);
3198 free_string2_list(head);
3199 exit(EXIT_FAILURE);
3200 }
3201 act_elem = act_elem->next;
3202 }
3203 free_string2_list(head);
3abe9331 3204 struct string_list* act_head = getExternalLibPaths(makefile->project_name);
af710487 3205 struct string_list* act_ext_elem = act_head;
3206 while (act_ext_elem) {
3207 if (act_ext_elem->str) {
3208 fputs(" \\\n", fp);
3209 fprintf(fp, "\t-L%s", act_ext_elem->str);
3210 }
3211 act_ext_elem = act_ext_elem->next;
3212 }
3213 free_string_list(act_head);
3214 act_head = getExternalLibs(makefile->project_name);
3215 act_ext_elem = act_head;
3216 while (act_ext_elem) {
3217 if (act_ext_elem->str) {
3218 fputs(" \\\n", fp);
3219 fprintf(fp, "\t-l%s", act_ext_elem->str);
3220 }
3221 act_ext_elem = act_ext_elem->next;
3222 }
3223 free_string_list(act_head);
3224 }
3225 }
3226 else { // static linking
3227 fprintf(fp, "\n"
3228 "$(LIBRARY): $(OBJECTS)%s\n"
3229 "\t$(AR) -r%s $(ARFLAGS) $(LIBRARY) $(OBJECTS)",
3230 makefile->hierarchical ? " $(BASE2_LIBRARY)" : "",
3231 makefile->linkingStrategy ? "cT" : "");
3232 if (makefile->central_storage && !makefile->linkingStrategy) {
970ed795
EL
3233 fputs(" $(BASE_OBJECTS)", fp);
3234 }
af710487 3235 if (makefile->linkingStrategy) {
3236 if ( makefile->library) {
3237 struct string2_list* head = getLinkerLibs(makefile->project_name);
3238 struct string2_list* act_elem = head;
3239 while (act_elem) {
3240 if (act_elem->str2 && !isDynamicLibrary(act_elem->str2)) {
3241 fputs(" \\\n", fp);
3242 fprintf(fp, "\t%s/lib%s.a", act_elem->str1, act_elem->str2);
3243 }
3244 else {
3245 const char* mainLibName = getLibFromProject(makefile->project_name);
3246 if (act_elem->str2) {
3247 ERROR("Dynamic library 'lib%s.so' cannot be linked to static library 'lib%s.a' "
3248 "in project '%s' ",
3249 act_elem->str2, mainLibName ? mainLibName : "", makefile->project_name);
3250 exit(EXIT_FAILURE);
3251 }
3252 else {
3253 struct string_list* ext_libs = getExternalLibs(makefile->project_name);
3254 if (ext_libs && ext_libs->str) {
3255 ERROR("Third party dynamic library '%s' cannot be linked to static library 'lib%s.a' "
3256 "in project '%s' ", ext_libs->str,
3257 mainLibName ? mainLibName : "", makefile->project_name);
3258 free_string_list(ext_libs);
3259 exit(EXIT_FAILURE);
3260 }
3261 free_string_list(ext_libs);
3262 }
3263 }
3264 act_elem = act_elem->next;
3265 }
3266 free_string2_list(head);
3267
3268 struct string_list* act_head = getExternalLibs(makefile->project_name);
3269 struct string_list* act_ext_elem = act_head;
3270 while (act_ext_elem) {
3271 if (act_ext_elem->str && hasExternalLibrary(act_ext_elem->str, makefile->project_name)) {
3272 fputs(" \\\n", fp);
3273 fprintf(fp, "\tlib%s.a", act_ext_elem->str);
63b4c1f9 3274 ERROR("linking static 3d party or system library 'lib%s.a' to "
af710487 3275 "project library 'lib%s.a' is not supported ",
3276 act_ext_elem->str, makefile->ets_name);
3277 exit(EXIT_FAILURE);
3278 }
3279 act_ext_elem = act_ext_elem->next;
3280 }
3281 free_string_list(act_head);
3282 }
3283 }
970ed795 3284 }
970ed795
EL
3285 fputs("\n\n.cc.o .c.o:\n"
3286 "\t$(CXX) -c $(CPPFLAGS) $(CXXFLAGS) -o $@ $<\n\n", fp);
3287
3288 if (makefile->gcc_dep) {
3289 fputs(".cc.d .c.d:\n"
3290 "\t@echo Creating dependency file for '$<'; set -e; \\\n"
3291 "\t$(CXX) $(CXXDEPFLAGS) $(CPPFLAGS) $(CXXFLAGS) $< \\\n"
3292 "\t| sed 's/\\($*\\)\\.o[ :]*/\\1.o $@ : /g' > $@; \\\n"
3293 "\t[ -s $@ ] || rm -f $@\n\n", fp);
3294 /* "set -e" causes bash to exit the script if any statement
3295 * returns nonzero (failure).
3296 * The sed line transforms the first line of the dependency from
3297 * "x.o: x.cc" to "x.o x.d: x.cc", making the dependency file depend
3298 * on the source and headers.
3299 * [ -s x.d ] checks that the generated dependency is not empty;
3300 * otherwise it gets deleted.
3301 */
3302 }
3303
3304 if (makefile->dynamic) {
3305 fputs("%.so: %.o\n"
3306 "\t$(CXX) -shared -o $@ $<\n\n", fp);
3307 }
3308
3309 if (makefile->preprocess) {
3310 fputs("%.ttcn: %.ttcnpp $(TTCN3_INCLUDES)\n"
3311 "\t$(CPP) -x c -nostdinc $(CPPFLAGS_TTCN3) $< $@\n\n"
3312 "preprocess: $(PREPROCESSED_TTCN3_MODULES) ;\n\n", fp);
3313 }
3314
3abe9331 3315 boolean merge_profiled_file_lists = makefile->profiled_file_list
3316 && makefile->profiled_file_list->next && !makefile->central_storage;
970ed795
EL
3317 if (makefile->central_storage) {
3318 boolean is_first = TRUE;
af710487 3319 fprintf(fp, "$(GENERATED_SOURCES) $(GENERATED_HEADERS):%s compile-all compile ",
3320 makefile->hierarchical ? " update" : "");
3321
970ed795
EL
3322 if (add_refd_prjs) fputs("referenced-dep", fp);
3323 /* These extra compile dependencies for the generated .cc are here to
3324 * check if all the referenced projects are up to date.
3325 * If the referenced projects are built too then they are not needed
3326 * (and cause problems as the included .d depends on the .cc).
3327 */
3328 if (!add_refd_prjs) for (i = 0; i < makefile->nBaseDirs; i++) {
3329 const struct base_dir_struct *base_dir = makefile->BaseDirs + i;
af710487 3330 if (base_dir->has_modules) {
3331 if (is_first) {
3332 fputs(" \\\n", fp);
3333 is_first = FALSE;
3334 }
3335 else putc(' ', fp);
3336 fprintf(fp, "%s/compile", base_dir->dir_name);
3337 }
970ed795 3338 }
970ed795 3339 if (makefile->preprocess) {
af710487 3340 fprintf(fp, "\n"
3341 "\t@if [ ! -f $@ ]; then %s compile-all; $(MAKE) compile-all; fi\n"
3342 "\n"
3343 "check:%s $(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n"
3344 "\t$(PREPROCESSED_TTCN3_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) "
3345 "%s\\\n"
3346 "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\n"
3347 "\t$(TTCN3_DIR)/bin/compiler -s $(COMPILER_FLAGS) ",
3348 rm_command, add_refd_prjs?" referenced-check":"",
3349 makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"",
3350 makefile->linkingStrategy ? "$(BASE2_PREPROCESSED_TTCN3_MODULES) ":"",
3351 makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) ":"");
3352 if (makefile->gnu_make) {
3353 if (add_refd_prjs) // referenced-check cannot be compiled it is not a ttcn modul
3354 fprintf(fp, "$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n"
3355 "\t$(PREPROCESSED_TTCN3_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) "
3356 "%s\\\n"
3357 "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\n",
3358 makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"",
3359 makefile->linkingStrategy ? "$(BASE2_PREPROCESSED_TTCN3_MODULES) ":"",
3360 makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) ":"");
3361 else
3362 fputs("$^", fp);
3363 }
3364 else {
3365 fputs("\\\n"
3366 "\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) \\\n"
3367 "\t$(PREPROCESSED_TTCN3_MODULES) "
3368 "$(BASE_PREPROCESSED_TTCN3_MODULES) \\\n"
3369 "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES)", fp);
3370 }
d44e3c4f 3371 fprintf(fp, "\n\n"
3372 "port: $(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n"
3373 "\t$(PREPROCESSED_TTCN3_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) "
3374 "%s\n"
3375 "\t$(TTCN3_DIR)/bin/compiler -t $(COMPILER_FLAGS) ",
3376 makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"",
3377 makefile->linkingStrategy ? "$(BASE2_PREPROCESSED_TTCN3_MODULES) ":"");
3378 if (makefile->gnu_make) {
3379 if (add_refd_prjs) // referenced-check cannot be compiled it is not a ttcn modul
3380 fprintf(fp, "$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n"
3381 "\t$(PREPROCESSED_TTCN3_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) "
3382 "%s\n",
3383 makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"",
3384 makefile->linkingStrategy ? "$(BASE2_PREPROCESSED_TTCN3_MODULES) ":"");
3385 else
3386 fputs("$^", fp);
3387 }
3388 else {
3389 fputs("\\\n"
3390 "\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) \\\n"
3391 "\t$(PREPROCESSED_TTCN3_MODULES) "
3392 "$(BASE_PREPROCESSED_TTCN3_MODULES) \n", fp);
3393 }
af710487 3394 if (makefile->linkingStrategy && makefile->hierarchical) {
3395 fputs("\n\n"
3396 "update: $(BASE_TTCN3_MODULES) $(BASE_ASN1_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) \\\n"
3397 "\t$(BASE2_TTCN3_MODULES) $(BASE2_ASN1_MODULES) $(BASE2_PREPROCESSED_TTCN3_MODULES)\n"
3398 "ifneq ($(wildcard $(GENERATED_SOURCES)), ) \n"
3399 "ifeq ($(wildcard $?), ) \n"
3400 "\ttouch compile-all; \n"
3401 "\ttouch update; \n"
3402 "endif\n"
3403 "endif",fp);
3404 }
3abe9331 3405 if (makefile->profiled_file_list) {
3406 fputs("\n\n"
3407 "compile:: $(PROFILED_FILE_LIST)\n"
3408 "\ttouch $(TTCN3_MODULES) $(PREPROCESSED_TTCN3_MODULES) "
3409 "$(ASN1_MODULES)", fp);
3410 }
af710487 3411 fprintf(fp, "\n\n"
3abe9331 3412 "compile:%s $(TTCN3_MODULES) $(PREPROCESSED_TTCN3_MODULES) "
af710487 3413 "$(ASN1_MODULES)\n"
3414 "\t@echo \"compiling \"'$(patsubst %%.tpd, %%, $(TPD))';\n"
3415 "\t$(TTCN3_DIR)/bin/compiler $(COMPILER_FLAGS) \\\n"
3416 "\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n"
3417 "\t$(PREPROCESSED_TTCN3_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) %s\\\n"
3418 "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s - $?\n"
3419 "\ttouch $@\n\n",
3abe9331 3420 makefile->profiled_file_list ? ":" : "",
af710487 3421 makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"",
3422 makefile->linkingStrategy ? "$(BASE2_PREPROCESSED_TTCN3_MODULES) ":"",
3423 makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES)":"");
3424 fprintf (fp,
3425 "compile-all: $(BASE_TTCN3_MODULES) $(BASE_ASN1_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) "
3426 "%s"
3427 "\t$(MAKE) preprocess\n"
3428 "\t@echo \"compiling all \"'$(patsubst %%.tpd, %%, $(TPD))';\n"
3429 "\t$(TTCN3_DIR)/bin/compiler $(COMPILER_FLAGS) \\\n"
3430 "\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n"
3431 "\t$(PREPROCESSED_TTCN3_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) %s"
3432 "\\\n"
3433 "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\\\n"
3434 "\t- $(TTCN3_MODULES) $(PREPROCESSED_TTCN3_MODULES) $(ASN1_MODULES)\n"
3435 "\ttouch $@ compile\n\n",
3436 makefile->linkingStrategy ? "\\\n\t$(BASE2_TTCN3_MODULES) $(BASE2_ASN1_MODULES) "
3437 "$(BASE2_PREPROCESSED_TTCN3_MODULES) \n":"\n",
3438 makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"",
3439 makefile->linkingStrategy ? "$(BASE2_PREPROCESSED_TTCN3_MODULES) ":"",
3440 makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) ":"");
3abe9331 3441 }
af710487 3442 else {
3443 fprintf(fp, "\n"
3444 "\t@if [ ! -f $@ ]; then %s compile-all; $(MAKE) compile-all; fi\n", rm_command);
3445 fprintf(fp, "\n"
3446 "check:%s $(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n"
3447 "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\n"
3448 "\t$(TTCN3_DIR)/bin/compiler -s $(COMPILER_FLAGS) ",
3449 add_refd_prjs?" referenced-check":"",
3450 makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"",
3451 makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) ":"");
3452 if (makefile->gnu_make) {
3453 if (add_refd_prjs) // referenced-check cannot be compiled it is not a ttcn modul
3454 fprintf(fp, "$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n"
3455 "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\n",
3456 makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"",
3457 makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) ":"");
3458 else
3459 fputs("$^", fp);
970ed795 3460 }
af710487 3461 else {
3462 fputs("\\\n"
3463 "\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) \\\n"
3464 "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES)", fp);
3465 }
d44e3c4f 3466
3467 fprintf(fp, "\n\n"
3468 "port: $(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\n"
3469 "\t$(TTCN3_DIR)/bin/compiler -t $(COMPILER_FLAGS) ",
3470 makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"");
3471 if (makefile->gnu_make) {
3472 if (add_refd_prjs) // referenced-check cannot be compiled it is not a ttcn modul
3473 fprintf(fp, "$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\n",
3474 makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"");
3475 else
3476 fputs("$^", fp);
3477 }
3478 else {
3479 fputs("\\\n"
3480 "\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) \n", fp);
3481 }
af710487 3482
3483 if (makefile->linkingStrategy && makefile->hierarchical) {
3484 fputs("\n\n"
3485 "update: $(BASE_TTCN3_MODULES) $(BASE_ASN1_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) \\\n"
3486 "\t$(BASE2_TTCN3_MODULES) $(BASE2_ASN1_MODULES) $(BASE2_PREPROCESSED_TTCN3_MODULES)\n"
3487 "ifneq ($(wildcard $(GENERATED_SOURCES)), ) \n"
3488 "ifeq ($(wildcard $?), ) \n"
3489 "\ttouch compile-all; \n"
3490 "\ttouch update; \n"
3491 "endif\n"
3492 "endif",fp);
3493 }
3494
3abe9331 3495 if (makefile->profiled_file_list) {
3496 fputs("\n\n"
3497 "compile:: $(PROFILED_FILE_LIST)\n"
3498 "\ttouch $(TTCN3_MODULES) $(ASN1_MODULES)", fp);
3499 }
af710487 3500 fprintf(fp, "\n\n"
3abe9331 3501 "compile:%s $(TTCN3_MODULES) $(ASN1_MODULES)\n"
af710487 3502 "\t@echo \"compiling \"'$(patsubst %%.tpd, %%, $(TPD))';\n"
3503 "\t$(TTCN3_DIR)/bin/compiler $(COMPILER_FLAGS) \\\n"
3504 "\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n"
3505 "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\\\n"
3506 "\t- $?\n"
3507 "\ttouch $@\n\n",
3abe9331 3508 makefile->profiled_file_list ? ":" : "",
af710487 3509 makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) " : "",
3510 makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) " : "");
3511 fprintf(fp,
3512 "compile-all: $(BASE_TTCN3_MODULES) $(BASE_ASN1_MODULES) %s\n",
3513 makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) $(BASE2_ASN1_MODULES)" : "");
3514 fputs("\t@echo \"compiling all \"'$(patsubst %.tpd, %, $(TPD))';\n", fp);
3515 fprintf(fp,"\t$(TTCN3_DIR)/bin/compiler $(COMPILER_FLAGS) \\\n"
3516 "\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n"
3517 "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\\\n"
3518 "\t- $(TTCN3_MODULES) $(ASN1_MODULES)\n"
3519 "\ttouch $@ compile\n\n",
3520 makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) " : "",
3521 makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) " : "");
3522 }
3523 if (!makefile->hierarchical)
3524 for (i = 0; i < makefile->nBaseDirs; i++) {
3525 const struct base_dir_struct *base_dir = makefile->BaseDirs + i;
3526 if (base_dir->has_modules) {
3527 size_t j;
3528 fprintf(fp, "%s/compile:", base_dir->dir_name);
3529 for (j = 0; j < makefile->nTTCN3Modules; j++) {
3530 const struct module_struct *module = makefile->TTCN3Modules + j;
3531 if (module->dir_name != NULL &&
3532 !strcmp(base_dir->dir_name, module->dir_name))
3533 print_file_name(fp, module);
3534 }
3535 for (j = 0; j < makefile->nTTCN3PPModules; j++) {
3536 const struct module_struct *module = makefile->TTCN3PPModules + j;
3537 if (module->dir_name != NULL &&
3538 !strcmp(base_dir->dir_name, module->dir_name))
3539 print_file_name(fp, module);
3540 }
3541 for (j = 0; j < makefile->nASN1Modules; j++) {
3542 const struct module_struct *module = makefile->ASN1Modules + j;
3543 if (module->dir_name != NULL &&
3544 !strcmp(base_dir->dir_name, module->dir_name))
3545 print_file_name(fp, module);
3546 }
3547 fprintf(fp, "\n"
3548 "\t@echo 'Central directory %s is not up-to-date!'\n"
3549 "\t@exit 2\n\n", base_dir->dir_name);
3550 }
3551 }
3abe9331 3552 }
af710487 3553 else { /* not central storage */
970ed795 3554 fprintf(fp, "$(GENERATED_SOURCES) $(GENERATED_HEADERS): compile\n"
af710487 3555 "\t@if [ ! -f $@ ]; then %s compile; $(MAKE) compile; fi\n\n"
3abe9331 3556 "%s"
3557 "check:%s $(TTCN3_MODULES) ", rm_command,
3558 merge_profiled_file_lists ? "check:: $(PROFILED_FILE_LIST)\n\n" : "",
3559 merge_profiled_file_lists ? ":" : "");
970ed795
EL
3560 if (makefile->preprocess) fputs("$(PREPROCESSED_TTCN3_MODULES) ", fp);
3561 fputs("$(ASN1_MODULES)\n"
af710487 3562 "\t$(TTCN3_DIR)/bin/compiler -s $(COMPILER_FLAGS) ", fp);
970ed795
EL
3563 if (makefile->gnu_make) fputs("$^", fp);
3564 else {
af710487 3565 fputs("\\\n"
3566 "\t$(TTCN3_MODULES) $(PREPROCESSED_TTCN3_MODULES) $(ASN1_MODULES)",
3567 fp);
970ed795 3568 }
d44e3c4f 3569
3570 fputs("\n\n", fp);
3571 fprintf(fp, "port: $(TTCN3_MODULES) ");
3572 if (makefile->preprocess) fputs("$(PREPROCESSED_TTCN3_MODULES) ", fp);
3573 fputs("\n", fp);
3574 fputs("\t$(TTCN3_DIR)/bin/compiler -t $(COMPILER_FLAGS) ", fp);
3575 if (makefile->gnu_make) fputs("$^", fp);
3576 else {
3577 fputs("\\\n"
3578 "\t$(TTCN3_MODULES) $(PREPROCESSED_TTCN3_MODULES)",
3579 fp);
3580 }
3581
3abe9331 3582 if (makefile->profiled_file_list) {
3583 fputs("\n\ncompile:: $(PROFILED_FILE_LIST)\n"
3584 "\ttouch $(TTCN3_MODULES) ", fp);
3585 if (makefile->preprocess) fputs("$(PREPROCESSED_TTCN3_MODULES) ", fp);
3586 fputs("$(ASN1_MODULES)", fp);
3587 }
3588 fprintf(fp, "\n\n"
3589 "compile:%s $(TTCN3_MODULES) ", makefile->profiled_file_list ? ":" : "");
970ed795
EL
3590 if (makefile->preprocess) fputs("$(PREPROCESSED_TTCN3_MODULES) ", fp);
3591 fputs("$(ASN1_MODULES)\n"
af710487 3592 "\t$(TTCN3_DIR)/bin/compiler $(COMPILER_FLAGS) ", fp);
970ed795
EL
3593 if (makefile->gnu_make) fputs("$^", fp);
3594 else {
af710487 3595 fputs("\\\n"
3596 "\t$(TTCN3_MODULES) ", fp);
3597 if (makefile->preprocess) fputs("$(PREPROCESSED_TTCN3_MODULES) ", fp);
3598 fputs("$(ASN1_MODULES)", fp);
970ed795
EL
3599 }
3600 fputs(" - $?\n"
af710487 3601 "\ttouch $@\n"
3602 "\n", fp);
3abe9331 3603 if (merge_profiled_file_lists) {
3604 fputs("$(PROFILED_FILE_LIST): $(PROFILED_FILE_LIST_SEGMENTS)\n"
3605 "\tcat $(PROFILED_FILE_LIST_SEGMENTS) > $(PROFILED_FILE_LIST)\n\n", fp);
3606 }
af710487 3607 }
3608// clean:
3609 if (makefile->linkingStrategy) {
3610 fprintf(fp, "clean:%s\n", (add_refd_prjs && !makefile->hierarchical) ?
3611 " referenced-clean" : "");
3612 if (makefile->dynamic && (makefile->central_storage || makefile->linkingStrategy)) {
3613 fprintf(fp,"\tfind . -type l -name \"*.so\" -exec unlink {} \\;\n");
3614 }
3615 fprintf(fp, "\t%s $(EXECUTABLE) $(DYNAMIC_LIBRARY) $(STATIC_LIBRARY) "
3616 "$(OBJECTS) $(GENERATED_HEADERS) \\\n"
3617 "\t$(GENERATED_SOURCES) ", rm_command);
3618 if (makefile->dynamic) fputs("$(SHARED_OBJECTS) ", fp);
3619 if (makefile->preprocess) fputs("$(PREPROCESSED_TTCN3_MODULES) ", fp);
3620 fputs("compile", fp);
3621 if (makefile->central_storage) fputs(" compile-all", fp);
3622 if (makefile->gcc_dep) fputs(" $(DEPFILES)", fp);
3abe9331 3623 if (merge_profiled_file_lists) {
3624 fputs(" $(PROFILED_FILE_LIST)", fp);
3625 }
af710487 3626 fprintf(fp, " \\\n"
3627 "\ttags *.log%s%s\n\n",
3628 add_refd_prjs?" referenced*":"",
3629 makefile->hierarchical ? " update":"");
3630 }
3631 else {
3632 fprintf(fp, "clean:%s\n"
3633 "\t-%s $(EXECUTABLE) $(LIBRARY) $(OBJECTS) $(GENERATED_HEADERS) \\\n"
3634 "\t$(GENERATED_SOURCES) ", add_refd_prjs?" referenced-clean":"", rm_command);
3635 if (makefile->dynamic) fputs("$(SHARED_OBJECTS) ", fp);
3636 if (makefile->preprocess) fputs("$(PREPROCESSED_TTCN3_MODULES) ", fp);
3637 fputs("compile", fp);
3638 if (makefile->central_storage) fputs(" compile-all", fp);
3639 if (makefile->gcc_dep) fputs(" $(DEPFILES)", fp);
3abe9331 3640 if (merge_profiled_file_lists) {
3641 fputs(" $(PROFILED_FILE_LIST)", fp);
3642 }
af710487 3643 fprintf(fp, " \\\n"
3644 "\ttags *.log%s",
3645 add_refd_prjs?" referenced*":"");
3646 }
3647
3648// clean-all:
3649 if (makefile->linkingStrategy && makefile->hierarchical)
3650 fprintf(fp, "clean-all: %s clean\n", add_refd_prjs ? "referenced-clean-all":"");
3651
3652// dep:
970ed795 3653 fputs("\n\ndep: $(GENERATED_SOURCES) $(USER_SOURCES)",fp);
af710487 3654 if (add_refd_prjs) {
3655 fprintf(fp, "\n\t%s referenced-dep", rm_command);
3656 }
970ed795 3657 else fputs(" ;",fp);
af710487 3658
970ed795
EL
3659 if (makefile->gcc_dep) {
3660 fprintf(fp, " \n\n"
3661 "ifeq ($(findstring n,$(MAKEFLAGS)),)\n"
d44e3c4f 3662 "ifeq ($(filter clean%s check port compile archive diag%s,$(MAKECMDGOALS)),)\n"
970ed795
EL
3663 "-include $(DEPFILES)\n"
3664 "endif\n"
af710487 3665 "endif",
3666 (makefile->linkingStrategy && makefile->hierarchical) ? " clean-all" : "",
3667 (makefile->preprocess ? " preprocess" : ""));
970ed795
EL
3668 /* Don't include .d files when cleaning etc.; make will try to build them
3669 * and this involves running the Titan compiler. Same for preprocess.
3670 * The check target would be pointless if running the compiler
3671 * without generating code was always preceded by running the compiler
3672 * _and_ generating C++ code. */
3673 }
3674 else { /* old-style dep with makedepend. Do not check compiler version. */
3675 fputs("\n\tmakedepend $(CPPFLAGS) -DMAKEDEPEND_RUN ", fp);
3676 if (makefile->gnu_make) fputs("$^", fp);
3677 else fputs("$(GENERATED_SOURCES) $(USER_SOURCES)", fp);
3678 }
af710487 3679
3680 if (makefile->linkingStrategy) {
3681 fputs("\n\n"
3682 "archive:\n"
c9bcf405 3683 "\t@perl $(TTCN3_DIR)/bin/ttcn3_archive\n\n", fp);
af710487 3684 }
3685 else {
3686 fputs("\n\n"
3687 "archive:\n"
3688 "\tmkdir -p $(ARCHIVE_DIR)\n"
3689 "\ttar -cvhf - ", fp);
3690 if (makefile->central_storage) {
3691 fprintf(fp, "$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n",
3692 makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) " : "");
3693 if (makefile->preprocess) {
3694 fprintf(fp, "\t$(TTCN3_PP_MODULES) $(BASE_TTCN3_PP_MODULES) "
3695 "%s $(TTCN3_INCLUDES) \\\n",
3696 makefile->linkingStrategy ? "$(BASE2_TTCN3_PP_MODULES)" : "");
3697 }
3698 fprintf(fp, "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\\\n"
3699 "\t$(USER_HEADERS) $(BASE_USER_HEADERS) %s\\\n"
3700 "\t$(USER_SOURCES) $(BASE_USER_SOURCES) %s",
3701 makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) " : "",
3702 makefile->linkingStrategy ? "$(BASE2_USER_HEADERS) " : "",
3703 makefile->linkingStrategy ? "$(BASE2_USER_SOURCES)" : "");
970ed795 3704 }
af710487 3705 else {
3706 fputs("$(TTCN3_MODULES) ", fp);
3707 if (makefile->preprocess) {
3708 fputs("$(TTCN3_PP_MODULES) \\\n"
3709 "\t$(TTCN3_INCLUDES) ", fp);
3710 }
3711 fputs("$(ASN1_MODULES) \\\n"
3712 "\t$(USER_HEADERS) $(USER_SOURCES)", fp);
970ed795 3713 }
af710487 3714 fputs(" $(OTHER_FILES) \\\n"
3715 "\t| gzip >$(ARCHIVE_DIR)/`basename $(TARGET) .exe`-"
3716 "`date '+%y%m%d-%H%M'`.tgz\n\n", fp);
970ed795 3717 }
970ed795
EL
3718
3719 fprintf(fp, "diag:\n"
af710487 3720 "\t$(TTCN3_DIR)/bin/compiler -v 2>&1\n"
3721 "\t$(TTCN3_DIR)/bin/mctr_cli -v 2>&1\n"
3722 "\t$(CXX) -v 2>&1\n"
970ed795
EL
3723 "%s"
3724 "\t@echo TTCN3_DIR=$(TTCN3_DIR)\n"
3725 "\t@echo OPENSSL_DIR=$(OPENSSL_DIR)\n"
3726 "\t@echo XMLDIR=$(XMLDIR)\n"
3727 "\t@echo PLATFORM=$(PLATFORM)\n\n",
3728 makefile->dynamic ? "" : "\t$(AR) -V 2>&1\n");
3729
3730 if (add_refd_prjs) {
af710487 3731 fprintf(fp, "referenced-all referenced-shared_objects referenced-executable referenced-library \\\n"
3732 "referenced-objects referenced-check \\\n"
3733 "referenced-clean%s:\n"
3734 "\t@for dir in $(REFERENCED_PROJECT_DIRS); do \\\n"
3735 "\t $(MAKE) -C $$dir $(subst referenced-,,$@) || exit; \\\n"
3736 "\tdone; \n\n",
3737 (makefile->linkingStrategy && makefile->hierarchical) ? "-all" : "");
970ed795
EL
3738 fputs("referenced-dep:\n"
3739 "\t@for dir in $(REFERENCED_PROJECT_DIRS); do \\\n"
3740 "\t $(MAKE) -C $$dir $(subst referenced-,,$@) || exit; \\\n"
3741 "\tdone; \n"
3742 "\ttouch $@\n\n", fp);
3743 }
3744
3745 if (makefile->generatorCommandOutput) {
3746 fputs("### Project specific rules generated by user written script:\n\n", fp);
3747 fputs(makefile->generatorCommandOutput, fp);
3748 fputs("\n### End of project specific rules.\n\n", fp);
3749 }
3750
3751 fputs("#\n"
3752 "# Add your rules here if necessary...\n"
3753 "#\n\n", fp);
3754 fclose(fp);
3755 if (strcmp(makefile->output_file, "Makefile")) {
3756 NOTIFY("Makefile skeleton was written to `%s'.", makefile->output_file);
3757 } else {
3758 NOTIFY("Makefile skeleton was generated.");
3759 }
af710487 3760 }
3761 else {
3762 ERROR("Output file `%s' already exists. Use switch `%s' to force "
3763 "overwrite.",
3764 makefile->output_file,
3765 makefile->linkingStrategy ? "-F" : "-f");
970ed795
EL
3766 }
3767}
3768
3769#undef COMMENT_PREFIX
3770#define COMMENT_PREFIX
3771
3772/** run makefilegen commans for sub-projects */
3773static void run_makefilegen_commands(struct string2_list* run_command_list)
3774{
3775 struct string2_list* act_elem = run_command_list;
3776 while (act_elem) {
3777 struct string2_list* next_elem = act_elem->next;
3778 /* run commands if there were no ERRORs */
3779 if ((error_count == 0) && act_elem->str1 && act_elem->str2) {
3780 int rv;
3781 char* sub_proj_effective_work_dir = act_elem->str1;
3782 char* command = act_elem->str2;
3783 char* orig_dir = get_working_dir();
3784 rv = set_working_dir(sub_proj_effective_work_dir);
3785 if (rv) ERROR("Could not set working dir to `%s'", sub_proj_effective_work_dir);
3786 else {
af710487 3787 fprintf(stderr, "Executing `%s' in working directory `%s'...\n",
3788 command, sub_proj_effective_work_dir);
970ed795
EL
3789 rv = system(command);
3790 if (rv) ERROR("Execution failed with error code %d", rv); // TODO: it's not clear what system()'s return codes can be in different situations and platforms
3791 }
3792 rv = set_working_dir(orig_dir);
3793 if (rv) ERROR("Could not restore working dir to `%s'", orig_dir);
3794 Free(orig_dir);
3795 }
3796 Free(act_elem->str1);
3797 Free(act_elem->str2);
3798 Free(act_elem);
3799 act_elem = next_elem;
3800 }
3801}
3802
3803/** create symlinks and delete list */
3804static void generate_symlinks(struct string2_list* create_symlink_list)
3805{
3806 struct string2_list* act_elem = create_symlink_list;
3807 while (act_elem) {
3808 struct string2_list* next_elem = act_elem->next;
3809 /* create symlinks if there were no ERRORs */
3810 if ((error_count == 0) && act_elem->str1 && act_elem->str2) {
3811 int fail = symlink(act_elem->str1, act_elem->str2);
3812 if (fail) perror(act_elem->str2); /* complain but do not call ERROR() */
3813 }
3814 Free(act_elem->str1);
3815 Free(act_elem->str2);
3816 Free(act_elem);
3817 act_elem = next_elem;
3818 }
3819}
3820
3821/** Performs all tasks of Makefile generation based on the given list of
3822 * modules/files (taken from the command line) and options that represent
3823 * command line switches. */
3824static void generate_makefile(size_t n_arguments, char *arguments[],
3825 size_t n_other_files, const char *other_files[], const char *output_file,
af710487 3826 const char *ets_name, char *project_name, boolean gnu_make, boolean single_mode,
970ed795
EL
3827 boolean central_storage, boolean absolute_paths, boolean preprocess,
3828 boolean dump_makefile_data, boolean force_overwrite, boolean use_runtime_2,
3829 boolean dynamic, boolean makedepend, boolean coverage,
3abe9331 3830 const char *code_splitting_mode, const char *tcov_file_name, struct string_list* profiled_file_list,
af710487 3831 boolean Lflag, boolean Zflag, boolean Hflag, struct string_list* sub_project_dirs, struct string_list* ttcn3_prep_includes,
3832 struct string_list* ttcn3_prep_defines, struct string_list* ttcn3_prep_undefines, struct string_list* prep_includes,
3833 struct string_list* prep_defines, struct string_list* prep_undefines, boolean codesplittpd, boolean quietly, boolean disablesubtypecheck,
3834 const char* cxxcompiler, const char* optlevel, const char* optflags, boolean disableber, boolean disableraw, boolean disabletext,
970ed795
EL
3835 boolean disablexer, boolean disablejson, boolean forcexerinasn, boolean defaultasomit, boolean gccmsgformat,
3836 boolean linenumbersonlymsg, boolean includesourceinfo, boolean addsourcelineinfo, boolean suppresswarnings,
f08ff9ca
BB
3837 boolean outparamboundness, boolean omit_in_value_list, boolean warnings_for_bad_variants, boolean activate_debugger,
3838 boolean disable_predef_ext_folder, struct string_list* solspeclibraries,
feade998 3839 struct string_list* sol8speclibraries, struct string_list* linuxspeclibraries, struct string_list* freebsdspeclibraries,
970ed795
EL
3840 struct string_list* win32speclibraries, const char* ttcn3preprocessor, struct string_list* linkerlibraries,
3841 struct string_list* additionalObjects, struct string_list* linkerlibsearchpath, char* generatorCommandOutput,
3842 struct string2_list* target_placement_list)
3843{
3844 size_t i;
3845
3846 struct makefile_struct makefile;
3847 init_makefile_struct(&makefile);
3848
af710487 3849 makefile.project_name = project_name;
970ed795
EL
3850 makefile.central_storage = central_storage;
3851 makefile.gnu_make = gnu_make;
3852 makefile.preprocess = preprocess;
3853 makefile.single_mode = single_mode;
3854 makefile.force_overwrite = force_overwrite;
3855 makefile.use_runtime_2 = use_runtime_2;
3856 makefile.dynamic = dynamic;
3857 makefile.gcc_dep = gnu_make && !makedepend;
3858 makefile.coverage = coverage;
3859 makefile.library = Lflag;
af710487 3860 makefile.linkingStrategy = Zflag;
3861 makefile.hierarchical = Hflag;
970ed795
EL
3862 makefile.sub_project_dirs = sub_project_dirs;
3863 makefile.ttcn3_prep_includes = ttcn3_prep_includes;
3864 makefile.ttcn3_prep_defines = ttcn3_prep_defines;
af710487 3865 makefile.ttcn3_prep_undefines = ttcn3_prep_undefines;
970ed795
EL
3866 makefile.prep_includes = prep_includes;
3867 makefile.prep_defines = prep_defines;
af710487 3868 makefile.prep_undefines = prep_undefines;
970ed795
EL
3869 makefile.codesplittpd = codesplittpd;
3870 makefile.quietly = quietly;
3871 makefile.disablesubtypecheck = disablesubtypecheck;
3872 makefile.cxxcompiler = cxxcompiler;
3873 makefile.optlevel = optlevel;
3874 makefile.optflags = optflags;
3875 makefile.disableber = disableber;
3876 makefile.disableraw = disableraw;
3877 makefile.disabletext = disabletext;
3878 makefile.disablexer = disablexer;
3879 makefile.disablejson = disablejson;
3880 makefile.forcexerinasn = forcexerinasn;
3881 makefile.defaultasomit = defaultasomit;
3882 makefile.gccmsgformat = gccmsgformat;
3883 makefile.linenumbersonlymsg = linenumbersonlymsg;
3884 makefile.includesourceinfo = includesourceinfo;
3885 makefile.addsourcelineinfo = addsourcelineinfo;
3886 makefile.suppresswarnings = suppresswarnings;
3887 makefile.outparamboundness = outparamboundness;
3abe9331 3888 makefile.omit_in_value_list = omit_in_value_list;
feade998 3889 makefile.warnings_for_bad_variants = warnings_for_bad_variants;
f08ff9ca 3890 makefile.activate_debugger = activate_debugger;
feade998 3891 makefile.disable_predef_ext_folder = disable_predef_ext_folder;
970ed795
EL
3892 makefile.solspeclibraries = solspeclibraries;
3893 makefile.sol8speclibraries = sol8speclibraries;
3894 makefile.linuxspeclibraries = linuxspeclibraries;
3895 makefile.freebsdspeclibraries = freebsdspeclibraries;
3896 makefile.win32speclibraries = win32speclibraries;
3897 makefile.ttcn3preprocessor = ttcn3preprocessor;
3898 makefile.linkerlibraries = linkerlibraries;
3899 makefile.additionalObjects = additionalObjects;
3900 makefile.linkerlibsearchpath = linkerlibsearchpath;
3901 makefile.generatorCommandOutput = generatorCommandOutput;
3902 makefile.target_placement_list = target_placement_list;
3903
3904 for (i = 0; i < n_arguments; i++) {
3905 char *file_name = get_file_name_for_argument(arguments[i]);
3906 if (file_name != NULL) {
3907 FILE *fp = fopen(file_name, "r");
3908 if (fp != NULL) {
3909 char *module_name;
3910 if (is_ttcn3_module(file_name, fp, &module_name)) {
3911 if (is_asn1_module(file_name, fp, NULL)) {
3912 ERROR("File `%s' looks so strange that it can be both ASN.1 and "
3913 "TTCN-3 module. Add it to the Makefile manually.", file_name);
3914 Free(module_name);
3915 } else {
3916 add_ttcn3_module(&makefile, file_name, module_name);
3917 }
3918 } else if (is_asn1_module(file_name, fp, &module_name)) {
3919 if (is_valid_asn1_filename(file_name)) {
3920 add_asn1_module(&makefile, file_name, module_name);
3921 } else {
3922 ERROR("The file name (without suffix) shall be identical to the module name.\n"
3923 "If the name of the ASN.1 module contains a hyphen, the corresponding "
3924 "file name shall contain an underscore character instead.");
3925 }
3926 } else {
3927 add_user_file(&makefile, file_name);
3928 }
3929 fclose(fp);
3930 } else {
3931 ERROR("Cannot open file `%s' for reading: %s", file_name,
3932 strerror(errno));
3933 errno = 0;
3934 }
3935 Free(file_name);
3936 } else if (get_path_status(arguments[i]) == PS_DIRECTORY) {
3937 ERROR("Argument `%s' is a directory.", arguments[i]);
3938 } else {
3939 ERROR("Cannot find any source file for argument `%s'.", arguments[i]);
3940 }
3941 }
3942 for (i = 0; i < n_other_files; i++) {
3943 char *file_name = get_file_name_for_argument(other_files[i]);
3944 if (file_name != NULL) {
3945 add_path_to_list(&makefile.nOtherFiles, &makefile.OtherFiles, file_name,
3946 makefile.working_dir, TRUE);
3947 Free(file_name);
3948 } else if (get_path_status(other_files[i]) == PS_DIRECTORY) {
3949 ERROR("Argument `%s' given as other file is a directory.",
3950 other_files[i]);
3951 } else {
3952 ERROR("Cannot find any other file for argument `%s'.", other_files[i]);
3953 }
3954 }
3955
3956 if (ets_name != NULL) {
3957 char *dir_name = get_dir_name(ets_name, makefile.working_dir);
3958 char *file_name = get_file_from_path(ets_name);
3959 makefile.ets_name = compose_path_name(dir_name, file_name);
3960 Free(dir_name);
3961 Free(file_name);
3962 }
3963
3964 if (code_splitting_mode != NULL) {
3965 makefile.code_splitting_mode = mputprintf(makefile.code_splitting_mode, "-U %s", code_splitting_mode);
3966 }
3967
3968 if (tcov_file_name != NULL) {
3abe9331 3969 makefile.tcov_file_name = mprintf(" -K %s", tcov_file_name);
3970 }
3971
3972 if (profiled_file_list != NULL) {
3973 makefile.profiled_file_list = profiled_file_list;
970ed795
EL
3974 }
3975
3976 if (makefile.nTTCN3Modules >= 1) {
3977 if (makefile.ets_name == NULL)
3978 makefile.ets_name = mcopystr(makefile.TTCN3Modules[0].module_name);
3979 } else if (preprocess && (makefile.nTTCN3PPModules >= 1)) {
3980 if (makefile.ets_name == NULL)
3981 makefile.ets_name = mcopystr(makefile.TTCN3PPModules[0].module_name);
3982 } else if (makefile.nASN1Modules >= 1) {
3983 WARNING("No TTCN-3 module was given for the Makefile.");
3984 if (makefile.ets_name == NULL)
3985 makefile.ets_name = mcopystr(makefile.ASN1Modules[0].module_name);
3986 } else if (makefile.nUserFiles > 0) {
3987 WARNING("No TTCN-3 or ASN.1 module was given for the Makefile.");
3988 if (makefile.ets_name == NULL)
3989 makefile.ets_name = mcopystr(makefile.UserFiles[0].file_prefix);
3990 } else {
3991 WARNING("No source files were given for the Makefile");
3992 }
3993
3994 if (output_file != NULL) {
3995 if (get_path_status(output_file) == PS_DIRECTORY)
3996 makefile.output_file = mprintf("%s/Makefile", output_file);
3997 else makefile.output_file = mcopystr(output_file);
3998 } else makefile.output_file = mcopystr("Makefile");
3999 add_path_to_list(&makefile.nOtherFiles, &makefile.OtherFiles,
4000 makefile.output_file, makefile.working_dir, FALSE);
4001
4002 if (preprocess) check_preprocessed_filename_collision(&makefile);
4003 filter_out_generated_files(&makefile);
4004 complete_user_files(&makefile);
4005 if (!absolute_paths) convert_dirs_to_relative(&makefile);
4006 check_special_chars(&makefile);
4007 if (central_storage) collect_base_dirs(&makefile);
4008 check_naming_convention(&makefile);
4009
4010 if (dump_makefile_data) dump_makefile_struct(&makefile, 0);
4011
4012 if (error_count == 0) print_makefile(&makefile);
970ed795
EL
4013 free_makefile_struct(&makefile);
4014}
4015
4016#ifdef COVERAGE_BUILD
4017#define C_flag "C"
4018#else
4019#define C_flag
4020#endif
4021
4022
4023static void usage(void)
4024{
4025 fprintf(stderr, "\n"
f08ff9ca 4026 "usage: %s [-abc" C_flag "dDEfFglLmMnprRstTVwWXZ] [-K file] [-z file ] [-P dir]"
970ed795
EL
4027 " [-U none|type] [-e ets_name] [-o dir|file]\n"
4028 " [-t project_descriptor.tpd [-b buildconfig]]\n"
4029 " [-O file] ... module_name ... testport_name ...\n"
4030 " or %s -v\n"
4031 "\n"
4032 "OPTIONS:\n"
4033 " -a: use absolute pathnames in the generated Makefile\n"
4034 " -c: use the pre-compiled files from central directories\n"
4035#ifdef COVERAGE_BUILD
4036 " -C: enable coverage of generated C++ code\n"
4037#endif
4038 " -d: dump the data used for Makefile generation\n"
4039 " -e ets_name: name of the target executable\n"
feade998 4040 " -E: display only warnings for unrecognized encoding variants\n"
970ed795
EL
4041 " -f: force overwriting of the output Makefile\n"
4042 " -g: generate Makefile for use with GNU make\n"
feade998 4043 " -I path: Add path to the search paths when using TPD files\n"
3abe9331 4044 " -K file: enable selective code coverage\n"
970ed795
EL
4045 " -l: use dynamic linking\n"
4046 " -L: create makefile with library archive as the default target\n"
4047 " -m: always use makedepend for dependencies\n"
3abe9331 4048 " -M: allow 'omit' in template value lists (legacy behavior)\n"
f08ff9ca 4049 " -n: activate debugger (generates extra code for debugging)\n"
970ed795
EL
4050 " -o dir|file: write the Makefile to the given directory or file\n"
4051 " -O file: add the given file to the Makefile as other file\n"
4052 " -p: generate Makefile with TTCN-3 preprocessing\n"
4053 " -R: use function test runtime (TITAN_RUNTIME_2)\n"
4054 " -s: generate Makefile for single mode\n"
4055 " -U none|type: split generated code\n"
4056 " -v: show version\n"
4057 " -w: suppress warnings\n"
4058 " -Y: Enforces legacy behaviour of the \"out\" function parameters (see refguide)\n"
3abe9331 4059 " -z file: enable profiling and code coverage for the TTCN-3 files in the argument\n"
970ed795
EL
4060 "Options for processing the Titan Project Descriptor file(s):\n"
4061 " -t tpd: read project descriptor file\n"
4062 " -b buildconfig: use the specified build config instead of the default\n"
4063 " -D: use current directory as working directory\n"
4064 " -V: disable validation of TPD file with schema\n"
4065 " -r: generate Makefile hierarchy for TPD hierarchy (recursive)\n"
4066 " -F: force overwriting of all generated Makefiles, use with -r\n"
4067 " -T: generate only top-level Makefile of the hierarchy, use with -r\n"
4068 " -P dir: prints out a file list found in a given TPD relative to the given directory\n"
4069 " -X: generate XML file that describes the TPD hierarchy, use with -r\n"
4070 " -W: prefix working directories with project name\n"
af710487 4071 " -Z: recursive Makefile generation from TPD using object files and dynamic libraries too\n"
4072 " -H: hierachical Makefile generation from TPD use with -Z\n"
970ed795
EL
4073 , program_name, program_name);
4074}
4075
4076#define SET_FLAG(x) if (x##flag) {\
4077 ERROR("Flag -" #x " was specified more than once.");\
4078 error_flag = TRUE;\
4079 } else x##flag = TRUE
4080
4081void free_string_list(struct string_list* act_elem)
4082{
4083 while (act_elem) {
4084 struct string_list* next_elem = act_elem->next;
4085 Free(act_elem->str);
4086 Free(act_elem);
4087 act_elem = next_elem;
4088 }
4089}
4090
4091void free_string2_list(struct string2_list* act_elem)
4092{
4093 while (act_elem) {
4094 struct string2_list* next_elem = act_elem->next;
4095 Free(act_elem->str1);
4096 Free(act_elem->str2);
4097 Free(act_elem);
4098 act_elem = next_elem;
4099 }
4100}
4101
4102int main(int argc, char *argv[])
4103{
4104 boolean
4105 aflag = FALSE, bflag = FALSE, cflag = FALSE, Cflag = FALSE,
4106 dflag = FALSE, eflag = FALSE, fflag = FALSE, gflag = FALSE,
4107 oflag = FALSE, Kflag = FALSE, lflag = FALSE, pflag = FALSE,
4108 Pflag = FALSE, Rflag = FALSE, sflag = FALSE, tflag = FALSE,
4109 wflag = FALSE, vflag = FALSE, mflag = FALSE, Uflag = FALSE,
4110 Lflag = FALSE, rflag = FALSE, Fflag = FALSE, Xflag = FALSE,
4111 Tflag = FALSE, Yflag = FALSE, csflag = FALSE, quflag = FALSE,
4112 dsflag = FALSE, dbflag = FALSE, drflag = FALSE, dtflag = FALSE,
4113 dxflag = FALSE, fxflag = FALSE, doflag = FALSE,
4114 gfflag = FALSE, lnflag = FALSE, isflag = FALSE, asflag = FALSE,
4115 swflag = FALSE, Vflag = FALSE, Dflag = FALSE, Wflag = FALSE,
3abe9331 4116 djflag = FALSE, Zflag = FALSE, Hflag = FALSE, Mflag = FALSE,
f08ff9ca 4117 diflag = FALSE, zflag = FALSE, Eflag = FALSE, nflag = FALSE;
970ed795
EL
4118 boolean error_flag = FALSE;
4119 char *output_file = NULL;
4120 char *ets_name = NULL;
af710487 4121 char *project_name = NULL;
970ed795
EL
4122 size_t n_other_files = 0;
4123 const char **other_files = NULL;
4124 const char *code_splitting_mode = NULL;
4125 const char *tpd_file_name = NULL;
4126 const char *tpd_build_config = NULL;
4127 const char *tcov_file_name = NULL;
feade998 4128 size_t n_search_paths = 0;
4129 const char **search_paths = NULL;
3abe9331 4130 struct string_list* profiled_file_list = NULL;
4131 const char *profiled_file_list_zflag = NULL;
970ed795
EL
4132 const char *file_list_path = NULL;
4133 enum tpd_result tpd_processed = FALSE;
4134 struct string_list* sub_project_dirs = NULL;
4135 struct string2_list* create_symlink_list = NULL;
4136 struct string_list* ttcn3_prep_includes = NULL;
4137 struct string_list* ttcn3_prep_defines = NULL;
af710487 4138 struct string_list* ttcn3_prep_undefines = NULL;
970ed795
EL
4139 struct string_list* prep_includes = NULL;
4140 struct string_list* prep_defines = NULL;
af710487 4141 struct string_list* prep_undefines = NULL;
970ed795
EL
4142 char *cxxcompiler = NULL;
4143 char *optlevel = NULL;
4144 char *optflags = NULL;
4145 struct string_list* solspeclibraries = NULL;
4146 struct string_list* sol8speclibraries = NULL;
4147 struct string_list* linuxspeclibraries = NULL;
4148 struct string_list* freebsdspeclibraries = NULL;
4149 struct string_list* win32speclibraries = NULL;
4150 char *ttcn3prep = NULL;
4151 struct string_list* linkerlibraries = NULL;
4152 struct string_list* additionalObjects = NULL;
4153 struct string_list* linkerlibsearchpath = NULL;
4154 char* generatorCommandOutput = NULL;
4155 struct string2_list* target_placement_list = NULL;
4156 struct string2_list* run_command_list = NULL;
af710487 4157 struct string2_list* required_configs = NULL;
970ed795
EL
4158
4159#ifdef LICENSE
4160 license_struct lstr;
4161 int valid_license;
4162#endif
4163
4164 program_name = argv[0];
4165
4166 if (argc == 1) {
4167 fputs("Makefile Generator for the TTCN-3 Test Executor, version "
4168 PRODUCT_NUMBER "\n", stderr);
4169 usage();
4170 return EXIT_FAILURE;
4171 }
4172
4173 for ( ; ; ) {
f08ff9ca 4174 int c = getopt(argc, argv, "O:ab:c" C_flag "dDe:EfFgI:K:o:lLmMnpP:rRst:TU:vVwWXYz:ZH");
970ed795
EL
4175 if (c == -1) break;
4176 switch (c) {
4177 case 'O':
4178 n_other_files++;
4179 other_files = (const char**)
4180 Realloc(other_files, n_other_files * sizeof(*other_files));
4181 other_files[n_other_files - 1] = optarg;
4182 break;
feade998 4183 case 'I':
4184 n_search_paths++;
4185 search_paths = (const char**)
4186 Realloc(search_paths, n_search_paths * sizeof(*search_paths));
4187 search_paths[n_search_paths - 1] = optarg;
4188 break;
970ed795
EL
4189 case 'a':
4190 SET_FLAG(a);
4191 break;
4192 case 'b':
4193 SET_FLAG(b);
4194 tpd_build_config = optarg;
4195 break;
4196 case 'c':
4197 SET_FLAG(c);
4198 break;
4199 case 'K':
4200 SET_FLAG(K);
4201 tcov_file_name = optarg;
4202 break;
4203#ifdef COVERAGE_BUILD
4204 case 'C':
4205 SET_FLAG(C);
4206 break;
4207#endif
4208 case 'd':
4209 SET_FLAG(d);
4210 break;
4211 case 'D':
4212 SET_FLAG(D);
4213 break;
4214 case 'e':
4215 SET_FLAG(e);
4216 ets_name = optarg;
4217 break;
feade998 4218 case 'E':
4219 SET_FLAG(E);
4220 break;
970ed795
EL
4221 case 'f':
4222 SET_FLAG(f);
4223 break;
4224 case 'F':
4225 SET_FLAG(F);
4226 break;
4227 case 'g':
4228 SET_FLAG(g);
4229 break;
af710487 4230 case 'H':
4231 SET_FLAG(H);
4232 break;
970ed795
EL
4233 case 'o':
4234 SET_FLAG(o);
4235 output_file = optarg;
4236 break;
4237 case 'l':
4238 SET_FLAG(l);
4239 break;
4240 case 'L':
4241 SET_FLAG(L);
4242 break;
4243 case 'm':
4244 SET_FLAG(m);
4245 break;
3abe9331 4246 case 'M':
4247 SET_FLAG(M);
4248 break;
f08ff9ca
BB
4249 case 'n':
4250 SET_FLAG(n);
4251 break;
970ed795
EL
4252 case 'p':
4253 SET_FLAG(p);
4254 break;
4255 case 'P':
4256 SET_FLAG(P);
4257 /* Optional arguments with `::' are GNU specific... */
4258 if (get_path_status(optarg) == PS_DIRECTORY) {
af710487 4259 file_list_path = optarg;
970ed795 4260 } else {
af710487 4261 ERROR("The -P flag requires a valid directory as its argument "
4262 "instead of `%s'", optarg);
4263 error_flag = TRUE;
970ed795
EL
4264 }
4265 break;
4266 case 'r':
4267 SET_FLAG(r);
4268 break;
4269 case 'R':
4270 SET_FLAG(R);
4271 break;
4272 case 's':
4273 SET_FLAG(s);
4274 break;
4275 case 't':
4276 SET_FLAG(t);
4277 tpd_file_name = optarg;
4278 break;
4279 case 'T':
4280 SET_FLAG(T);
4281 break;
4282 case 'Y':
4283 SET_FLAG(Y);
4284 break;
4285 case 'U':
4286 SET_FLAG(U);
4287 code_splitting_mode = optarg;
4288 if (strcmp(optarg, "none") != 0 &&
4289 strcmp(optarg, "type") != 0)
4290 ERROR("Unrecognizable argument: '%s'. Valid options for -U switch are: "
4291 "'none', 'type'", optarg);
4292 break;
4293 case 'v':
4294 SET_FLAG(v);
4295 break;
4296 case 'V':
4297 SET_FLAG(V);
4298 break;
4299 case 'w':
4300 SET_FLAG(w);
4301 suppress_warnings = TRUE;
4302 break;
4303 case 'W':
4304 SET_FLAG(W);
4305 break;
4306 case 'X':
4307 SET_FLAG(X);
4308 break;
3abe9331 4309 case 'z':
4310 SET_FLAG(z);
4311 profiled_file_list_zflag = optarg;
4312 break;
af710487 4313 case 'Z':
4314 SET_FLAG(Z);
4315 break;
970ed795
EL
4316 default:
4317 error_flag = TRUE;
4318 break;
4319 }
4320 }
4321
4322 /* Checking incompatible options */
4323 if (vflag) {
4324 /* -v prints the version and exits, it's pointless to specify other flags */
4325 if ( aflag || bflag || cflag || Cflag || dflag || eflag || fflag || Fflag || gflag
4326 || mflag || oflag || lflag || pflag || Pflag || rflag || Rflag || sflag
4327 || tflag || Tflag || Vflag || wflag || Xflag || Kflag || Dflag || Wflag || Yflag
f08ff9ca 4328 || Zflag || Hflag || Mflag || zflag || Eflag || nflag || n_other_files > 0 || n_search_paths > 0)
af710487 4329 error_flag = TRUE;
4330 }
4331
4332 if (Zflag) {
4333 if (!gflag) gflag = TRUE; // GNU make
4334 if (!cflag) cflag = TRUE; // central sorage
970ed795
EL
4335 }
4336
af710487 4337 if ((bflag || Dflag || Pflag || Vflag || rflag || Wflag || Zflag) && !tflag) {
4338 ERROR("Using the '-b', '-D', '-P', '-V', '-r' 'Z' or '-W' option requires the use of the -t' option.");
970ed795
EL
4339 error_flag = TRUE;
4340 }
4341
4342 if (rflag && !cflag) {
4343 ERROR("Using the '-r' option requires use of the '-c' option. Recursive makefile hierarchy uses the central directory feature.");
4344 error_flag = TRUE;
4345 }
4346
4347 if (Fflag && !rflag) {
4348 ERROR("Using the '-F' option requires use of the '-r' option.");
4349 error_flag = TRUE;
4350 }
4351
4352 if (Xflag && !rflag) {
4353 ERROR("Using the '-X' option requires use of the '-r' option.");
4354 error_flag = TRUE;
4355 }
4356
4357 if (Tflag && !rflag) {
4358 ERROR("Using the '-T' option requires use of the '-r' option.");
4359 error_flag = TRUE;
4360 }
4361
af710487 4362 if (!Zflag && Hflag) {
4363 ERROR("Using the '-H' option requires use of the '-Z' option.");
4364 error_flag = TRUE;
4365 }
4366
4367 if (Zflag && !Fflag && !fflag) {
4368 ERROR("Using the '-Z' option requires use of the '-F' option.");
4369 error_flag = TRUE;
4370 }
4371
970ed795
EL
4372 if (lflag && !strncmp(get_platform_string(), "WIN32", 5)) {
4373 ERROR("Generating Makefile with dynamic linking enabled is not supported "
4374 "on Windows platform");
4375 error_flag = TRUE;
4376 }
4377
feade998 4378 if (n_search_paths > 0 && !tflag) {
4379 ERROR("Using the '-I' option requires use of the '-t' option.");
4380 error_flag = TRUE;
4381 }
d44e3c4f 4382
feade998 4383 for (size_t i = 0; i < n_search_paths; i++) {
d44e3c4f 4384 boolean is_abs_path =
feade998 4385#if defined WIN32 && defined MINGW
d44e3c4f 4386 /* On native Windows the absolute path name shall begin with
4387 * a drive letter, colon and backslash */
4388 (((search_paths[i][0] < 'A' || search_paths[i][0] > 'Z') &&
4389 (search_paths[i][0] < 'a' || search_paths[i][0] > 'z')) ||
4390 search_paths[i][1] != ':' || search_paths[i][2] != '\\');
feade998 4391#else
d44e3c4f 4392 /* On UNIX-like systems the absolute path name shall begin with
4393 * a slash */
4394 search_paths[i][0] != '/';
feade998 4395#endif
4396 if (is_abs_path) {
4397 ERROR("The path after the -I flag must be an absolute path.");
4398 error_flag = TRUE;
4399 }
4400 }
d44e3c4f 4401
970ed795
EL
4402 if (error_flag) {
4403 usage();
4404 return EXIT_FAILURE;
4405 }
4406
4407 if (vflag) {
4408 fputs("Makefile Generator for the TTCN-3 Test Executor\n"
4409 "Product number: " PRODUCT_NUMBER "\n"
4410 "Build date: " __DATE__ " " __TIME__ "\n"
4411 "Compiled with: " C_COMPILER_VERSION "\n\n"
4412 COPYRIGHT_STRING "\n\n", stderr);
4413#ifdef LICENSE
4414 print_license_info();
4415#endif
4416 return EXIT_SUCCESS;
4417 }
4418
4419#ifdef LICENSE
4420 init_openssl();
4421 load_license(&lstr);
4422 valid_license = verify_license(&lstr);
4423 free_openssl();
4424 if (!valid_license) {
4425 free_license(&lstr);
4426 exit(EXIT_FAILURE);
4427 }
4428 if (!check_feature(&lstr, FEATURE_TPGEN)) {
4429 ERROR("The license key does not allow the generation of "
4430 "Makefile skeletons.");
4431 return EXIT_FAILURE;
4432 }
4433 free_license(&lstr);
4434#endif
4435
4436 if (tflag) {
4437 char* abs_work_dir = NULL;
4438 FILE* prj_graph_fp = NULL;
4439 sub_project_dirs = (struct string_list*)Malloc(sizeof(struct string_list));
4440 sub_project_dirs->str = NULL;
4441 sub_project_dirs->next = NULL;
4442 ttcn3_prep_includes = (struct string_list*)Malloc(sizeof(struct string_list));
4443 ttcn3_prep_includes->str = NULL;
4444 ttcn3_prep_includes->next = NULL;
4445 ttcn3_prep_defines = (struct string_list*)Malloc(sizeof(struct string_list));
4446 ttcn3_prep_defines->str = NULL;
4447 ttcn3_prep_defines->next = NULL;
af710487 4448 ttcn3_prep_undefines = (struct string_list*)Malloc(sizeof(struct string_list));
4449 ttcn3_prep_undefines->str = NULL;
4450 ttcn3_prep_undefines->next = NULL;
970ed795
EL
4451 prep_includes = (struct string_list*)Malloc(sizeof(struct string_list));
4452 prep_includes->str = NULL;
4453 prep_includes->next = NULL;
4454 prep_defines = (struct string_list*)Malloc(sizeof(struct string_list));
4455 prep_defines->str = NULL;
4456 prep_defines->next = NULL;
af710487 4457 prep_undefines = (struct string_list*)Malloc(sizeof(struct string_list));
4458 prep_undefines->str = NULL;
4459 prep_undefines->next = NULL;
970ed795
EL
4460 solspeclibraries = (struct string_list*)Malloc(sizeof(struct string_list));
4461 solspeclibraries->str = NULL;
4462 solspeclibraries->next = NULL;
4463 sol8speclibraries = (struct string_list*)Malloc(sizeof(struct string_list));
4464 sol8speclibraries->str = NULL;
4465 sol8speclibraries->next = NULL;
4466 linuxspeclibraries = (struct string_list*)Malloc(sizeof(struct string_list));
4467 linuxspeclibraries->str = NULL;
4468 linuxspeclibraries->next = NULL;
4469 freebsdspeclibraries = (struct string_list*)Malloc(sizeof(struct string_list));
4470 freebsdspeclibraries->str = NULL;
4471 freebsdspeclibraries->next = NULL;
4472 win32speclibraries = (struct string_list*)Malloc(sizeof(struct string_list));
4473 win32speclibraries->str = NULL;
4474 win32speclibraries->next = NULL;
4475 linkerlibraries = (struct string_list*)Malloc(sizeof(struct string_list));
4476 linkerlibraries->str = NULL;
4477 linkerlibraries->next = NULL;
4478 additionalObjects = (struct string_list*)Malloc(sizeof(struct string_list));
4479 additionalObjects->str = NULL;
4480 additionalObjects->next = NULL;
4481 linkerlibsearchpath = (struct string_list*)Malloc(sizeof(struct string_list));
4482 linkerlibsearchpath->str = NULL;
4483 linkerlibsearchpath->next = NULL;
4484
4485 if (Xflag) {
4486 const char* prj_graph_filename = "project_hierarchy_graph.xml";
4487 prj_graph_fp = fopen(prj_graph_filename, "w");
4488 if (prj_graph_fp==NULL) WARNING("Cannot open output file `%s' for writing: %s", prj_graph_filename, strerror(errno));
4489 if (prj_graph_fp) fprintf(prj_graph_fp, "<project_hierarchy_graph top_level_tpd=\"%s\">\n", tpd_file_name);
4490 }
4491 create_symlink_list = (struct string2_list*)Malloc(sizeof(struct string2_list));
4492 create_symlink_list->str1 = NULL;
4493 create_symlink_list->str2 = NULL;
4494 create_symlink_list->next = NULL;
4495 target_placement_list = (struct string2_list*)Malloc(sizeof(struct string2_list));
4496 target_placement_list->str1 = NULL;
4497 target_placement_list->str2 = NULL;
4498 target_placement_list->next = NULL;
4499 run_command_list = (struct string2_list*)Malloc(sizeof(struct string2_list));
4500 run_command_list->str1 = NULL;
4501 run_command_list->str2 = NULL;
4502 run_command_list->next = NULL;
af710487 4503 required_configs = (struct string2_list*)Malloc(sizeof(struct string2_list));
4504 required_configs->str1 = NULL;
4505 required_configs->str2 = NULL;
4506 required_configs->next = NULL;
4507
970ed795 4508 tpd_processed = process_tpd(tpd_file_name, tpd_build_config, file_list_path,
af710487 4509 &argc, &argv, &optind, &ets_name, &project_name,
970ed795
EL
4510 &gflag, &sflag, &cflag, &aflag, &pflag,
4511 &Rflag, &lflag, &mflag, &Pflag, &Lflag, rflag, Fflag, Tflag, output_file, &abs_work_dir, sub_project_dirs, program_name, prj_graph_fp,
af710487 4512 create_symlink_list,ttcn3_prep_includes, ttcn3_prep_defines,ttcn3_prep_undefines, prep_includes, prep_defines, prep_undefines, &csflag,
4513 &quflag, &dsflag, &cxxcompiler, &optlevel, &optflags, &dbflag, &drflag, &dtflag, &dxflag, &djflag, &fxflag, &doflag, &gfflag, &lnflag, &isflag,
f08ff9ca 4514 &asflag, &swflag, &Yflag, &Mflag, &Eflag, &nflag, &diflag, solspeclibraries, sol8speclibraries, linuxspeclibraries, freebsdspeclibraries, win32speclibraries, &ttcn3prep,
af710487 4515 linkerlibraries, additionalObjects, linkerlibsearchpath, Vflag, Dflag, &Zflag, &Hflag,
feade998 4516 &generatorCommandOutput, target_placement_list, Wflag, run_command_list, required_configs, &profiled_file_list, search_paths, n_search_paths);
af710487 4517
970ed795
EL
4518 Free(abs_work_dir);
4519 if (prj_graph_fp) {
4520 fprintf(prj_graph_fp, "</project_hierarchy_graph>\n");
4521 fclose(prj_graph_fp);
4522 }
af710487 4523 if (tpd_processed == TPD_FAILED) {
4524 ERROR("Failed to process %s", tpd_file_name);
4525 exit(EXIT_FAILURE);
4526 }
3abe9331 4527 if (zflag) {
4528 WARNING("Compiler option '-z' and its argument will be overwritten by "
4529 "the settings in the TPD");
4530 }
4531 }
4532 else if (zflag) {
4533 // use the argument given in the command line if there is no TPD
4534 profiled_file_list = (struct string_list*)Malloc(sizeof(struct string_list));
4535 profiled_file_list->str = mcopystr(profiled_file_list_zflag);
4536 profiled_file_list->next = NULL;
970ed795
EL
4537 }
4538
4539 if (!Pflag) {
4540 run_makefilegen_commands(run_command_list);
4541 generate_symlinks(create_symlink_list);
af710487 4542 if (Zflag) {
4543 if (Fflag)
4544 NOTIFY("Makefile generation from top-level TPD: %s", tpd_file_name);
4545 if (!Fflag && fflag)
4546 NOTIFY("Makefile generation from lower level TPD: %s", tpd_file_name);
4547 }
970ed795 4548 generate_makefile(argc - optind, argv + optind, n_other_files, other_files,
af710487 4549 output_file, ets_name, project_name, gflag, sflag, cflag, aflag, pflag, dflag, fflag||Fflag,
3abe9331 4550 Rflag, lflag, mflag, Cflag, code_splitting_mode, tcov_file_name, profiled_file_list,
4551 Lflag, Zflag, Hflag, rflag ? sub_project_dirs : NULL, ttcn3_prep_includes,
af710487 4552 ttcn3_prep_defines, ttcn3_prep_undefines, prep_includes, prep_defines, prep_undefines, csflag, quflag, dsflag, cxxcompiler, optlevel, optflags, dbflag,
f08ff9ca 4553 drflag, dtflag, dxflag, djflag, fxflag, doflag, gfflag, lnflag, isflag, asflag, swflag, Yflag, Mflag, Eflag, nflag, diflag, solspeclibraries,
970ed795
EL
4554 sol8speclibraries, linuxspeclibraries, freebsdspeclibraries, win32speclibraries, ttcn3prep, linkerlibraries, additionalObjects,
4555 linkerlibsearchpath, generatorCommandOutput, target_placement_list);
4556 }
4557
4558 free_string_list(sub_project_dirs);
4559 free_string_list(ttcn3_prep_includes);
4560 free_string_list(ttcn3_prep_defines);
af710487 4561 free_string_list(ttcn3_prep_undefines);
970ed795
EL
4562 free_string_list(prep_includes);
4563 free_string_list(prep_defines);
af710487 4564 free_string_list(prep_undefines);
970ed795
EL
4565 free_string_list(solspeclibraries);
4566 free_string_list(sol8speclibraries);
4567 free_string_list(linuxspeclibraries);
4568 free_string_list(freebsdspeclibraries);
4569 free_string_list(win32speclibraries);
4570 free_string_list(linkerlibraries);
4571 free_string_list(additionalObjects);
4572 free_string_list(linkerlibsearchpath);
3abe9331 4573 free_string_list(profiled_file_list);
970ed795 4574
feade998 4575 Free(search_paths);
4576
970ed795
EL
4577 Free(generatorCommandOutput);
4578 free_string2_list(target_placement_list);
af710487 4579 free_string2_list(required_configs);
970ed795
EL
4580
4581 Free(other_files);
4582 if (tpd_processed == TPD_SUCCESS) {
4583 int E;
4584 if (!(eflag && ets_name))
4585 Free(ets_name);
4586 if (cxxcompiler)
4587 Free(cxxcompiler);
4588 if (optlevel)
4589 Free(optlevel);
4590 if (optflags)
4591 Free(optflags);
4592 if (ttcn3prep)
4593 Free(ttcn3prep);
4594 /* Free(output_file); */
4595 for (E = 0; E < argc; ++E) Free(argv[E]);
4596 Free(argv);
4597 }
af710487 4598 /* check_mem_leak(program_name); not needed when linked to new.cc */
970ed795
EL
4599 return error_count > 0 ? EXIT_FAILURE : EXIT_SUCCESS;
4600}
4601
This page took 0.220441 seconds and 5 git commands to generate.