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