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