/****************************************************************************** * Copyright (c) 2000-2016 Ericsson Telecom AB * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * * > * Baji, Laszlo * Balasko, Jeno * Baranyi, Botond * Beres, Szabolcs * Delic, Adam * Forstner, Matyas * Koppany, Csaba * Kovacs, Ferenc * Kremer, Peter * Lovassy, Arpad * Pandi, Krisztian * Raduly, Csaba * Szabados, Kristof * Szabo, Bence Janos * Szabo, Janos Zoltan – initial implementation * Szalay, Akos * Zalanyi, Balazs Andor * Pandi, Krisztian * ******************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdarg.h> #include <unistd.h> #include <errno.h> #include <ctype.h> #if defined SOLARIS || defined SOLARIS8 #include <sys/utsname.h> #endif #include "../common/memory.h" #include "../common/path.h" #include "../common/version_internal.h" #include "../common/userinfo.h" #include "ttcn3/ttcn3_preparser.h" #include "asn1/asn1_preparser.h" #ifdef LICENSE #include "../common/license.h" #endif #include "xpather.h" static const char *program_name = NULL; static unsigned int error_count = 0; static boolean suppress_warnings = FALSE; void free_string2_list(struct string2_list* act_elem); void free_string_list(struct string_list* act_elem); void ERROR(const char *fmt, ...) { va_list parameters; fprintf(stderr, "%s: error: ", program_name); va_start(parameters, fmt); vfprintf(stderr, fmt, parameters); va_end(parameters); fprintf(stderr, "\n"); fflush(stderr); error_count++; } void WARNING(const char *fmt, ...) { va_list parameters; if (suppress_warnings) return; fprintf(stderr, "%s: warning: ", program_name); va_start(parameters, fmt); vfprintf(stderr, fmt, parameters); va_end(parameters); putc('\n', stderr); fflush(stderr); } void NOTIFY(const char *fmt, ...) { va_list parameters; va_start(parameters, fmt); vfprintf(stderr, fmt, parameters); va_end(parameters); putc('\n', stderr); fflush(stderr); } void DEBUG(unsigned level, const char *fmt, ...) { va_list parameters; fprintf(stderr, "%*s", 2 * level, ""); va_start(parameters, fmt); vfprintf(stderr, fmt, parameters); va_end(parameters); putc('\n', stderr); fflush(stderr); } void path_error(const char *fmt, ...) { va_list ap; char *err_msg; va_start(ap, fmt); err_msg = mprintf_va_list(fmt, ap); va_end(ap); ERROR("%s", err_msg); Free(err_msg); } #if defined SOLARIS || defined SOLARIS8 /** Automatic detection of Solaris version based on uname() system call. * Distinguishing is needed because some socket functions use socklen_t * (which is an alias for unsigned int) as length arguments on Solaris 8. * On Solaris 2.6 the argument type is simply int and no socklen_t or other * alias exists. * Note: It was discovered later that Solaris 7 (which is used rarely within * Ericsson) already uses socklen_t thus the SOLARIS8 platform identifier is a * bit misleading. */ static const char *get_platform_string(void) { struct utsname name; int major, minor; if (uname(&name) < 0) { WARNING("System call uname() failed: %s", strerror(errno)); errno = 0; return "SOLARIS"; } if (sscanf(name.release, "%d.%d", &major, &minor) == 2 && major == 5) { if (minor <= 6) return "SOLARIS"; else return "SOLARIS8"; } else { ERROR("Invalid OS release: %s", name.release); return "SOLARIS"; } } #elif defined LINUX #define get_platform_string() "LINUX" #elif defined FREEBSD #define get_platform_string() "FREEBSD" #elif defined WIN32 #define get_platform_string() "WIN32" #elif defined INTERIX #define get_platform_string() "INTERIX" #else #error Platform was not set. #endif /** structure for describing TTCN-3 and ASN.1 modules */ struct module_struct { char *dir_name; /* directory of the TTCN-3 or ASN.1 file, it is NULL if the file is in the current working directory */ char *file_name; /* name of the TTCN-3 or ASN.1 file */ char *module_name; /* name of the TTCN-3 or ASN.1 module */ boolean is_regular; /* indicates whether the name of the source file follows the default naming convention */ }; /** structure for describing test ports and other C/C++ modules */ struct user_struct { char *dir_name; /* directory of the C/C++ source files, it is NULL if the files are in the current working directory */ char *file_prefix; /* the common prefix of the header and source file */ char *header_name; /* name of the C/C++ header file, which has .hh or .h or .hpp suffix, it is NULL if there is no header file */ char *source_name; /* name of the C/C++ source file, which has .cc or .c or .cpp suffix, it is NULL if there is no source file */ boolean has_hh_suffix; /* indicates whether the header file is present and has .hh or .hpp suffix */ boolean has_cc_suffix; /* indicates whether the source file is present and has .cc or .cpp suffix */ }; /** structure for directories that pre-compiled files are taken from */ struct base_dir_struct { const char *dir_name; /* name of the directory */ boolean has_modules; /* indicates whether there are TTCN-3/ASN.1 modules in the directory (it is set to FALSE if dir_name contains user C/C++ files only */ }; /** data structure that describes the information needed for the Makefile */ struct makefile_struct { char *project_name; size_t nTTCN3Modules; struct module_struct *TTCN3Modules; boolean preprocess; size_t nTTCN3PPModules; struct module_struct *TTCN3PPModules; boolean TTCN3ModulesRegular; boolean BaseTTCN3ModulesRegular; size_t nTTCN3IncludeFiles; char **TTCN3IncludeFiles; size_t nASN1Modules; struct module_struct *ASN1Modules; boolean ASN1ModulesRegular; boolean BaseASN1ModulesRegular; size_t nUserFiles; struct user_struct *UserFiles; boolean UserHeadersRegular; boolean UserSourcesRegular; boolean BaseUserHeadersRegular; boolean BaseUserSourcesRegular; size_t nOtherFiles; char **OtherFiles; boolean central_storage; size_t nBaseDirs; struct base_dir_struct *BaseDirs; char *working_dir; boolean gnu_make; boolean single_mode; char *output_file; char *ets_name; boolean force_overwrite; boolean use_runtime_2; boolean dynamic; boolean gcc_dep; char *code_splitting_mode; boolean coverage; char *tcov_file_name; struct string_list* profiled_file_list; /* not owned */ boolean library; boolean linkingStrategy; boolean hierarchical; struct string_list* sub_project_dirs; /* not owned */ struct string_list* ttcn3_prep_includes; /* not owned */ struct string_list* ttcn3_prep_defines; /* not owned */ struct string_list* ttcn3_prep_undefines; /* not owned */ struct string_list* prep_includes; /* not owned */ struct string_list* prep_defines; /* not owned */ struct string_list* prep_undefines; /* not owned */ boolean codesplittpd; boolean quietly; boolean disablesubtypecheck; const char *cxxcompiler; const char *optlevel; const char *optflags; boolean disableber; boolean disableraw; boolean disabletext; boolean disablexer; boolean disablejson; boolean forcexerinasn; boolean defaultasomit; boolean gccmsgformat; boolean linenumbersonlymsg; boolean includesourceinfo; boolean addsourcelineinfo; boolean suppresswarnings; boolean outparamboundness; boolean omit_in_value_list; boolean warnings_for_bad_variants; boolean activate_debugger; boolean disable_predef_ext_folder; struct string_list* solspeclibraries; /* not owned */ struct string_list* sol8speclibraries; /* not owned */ struct string_list* linuxspeclibraries; /* not owned */ struct string_list* freebsdspeclibraries; /* not owned */ struct string_list* win32speclibraries; /* not owned */ const char *ttcn3preprocessor; struct string_list* linkerlibraries; /* not owned */ struct string_list* additionalObjects; /* not owned */ struct string_list* linkerlibsearchpath; /* not owned */ char* generatorCommandOutput; /* not owned */ struct string2_list* target_placement_list; /* not owned */ }; /** Initializes structure \a makefile with empty lists and default settings. */ static void init_makefile_struct(struct makefile_struct *makefile) { makefile->project_name = NULL; makefile->nTTCN3Modules = 0; makefile->TTCN3Modules = NULL; makefile->preprocess = FALSE; makefile->nTTCN3PPModules = 0; makefile->TTCN3PPModules = NULL; makefile->TTCN3ModulesRegular = TRUE; makefile->BaseTTCN3ModulesRegular = TRUE; makefile->nTTCN3IncludeFiles = 0; makefile->TTCN3IncludeFiles = NULL; makefile->nASN1Modules = 0; makefile->ASN1Modules = NULL; makefile->ASN1ModulesRegular = TRUE; makefile->BaseASN1ModulesRegular = TRUE; makefile->nUserFiles = 0; makefile->UserFiles = NULL; makefile->UserHeadersRegular = TRUE; makefile->UserSourcesRegular = TRUE; makefile->BaseUserHeadersRegular = TRUE; makefile->BaseUserSourcesRegular = TRUE; makefile->nOtherFiles = 0; makefile->OtherFiles = NULL; makefile->central_storage = FALSE; makefile->nBaseDirs = 0; makefile->BaseDirs = NULL; makefile->working_dir = get_working_dir(); makefile->gnu_make = FALSE; makefile->single_mode = FALSE; makefile->ets_name = NULL; makefile->output_file = NULL; makefile->force_overwrite = FALSE; makefile->use_runtime_2 = FALSE; makefile->dynamic = FALSE; makefile->gcc_dep = FALSE; makefile->code_splitting_mode = NULL; makefile->coverage = FALSE; makefile->tcov_file_name = NULL; makefile->profiled_file_list = NULL; makefile->library = FALSE; makefile->linkingStrategy = FALSE; makefile->hierarchical = FALSE; makefile->sub_project_dirs = NULL; makefile->ttcn3_prep_includes = NULL; makefile->prep_includes = NULL; makefile->prep_defines = NULL; makefile->outparamboundness = FALSE; makefile->omit_in_value_list = FALSE; makefile->warnings_for_bad_variants = FALSE; makefile->activate_debugger = FALSE; makefile->solspeclibraries = NULL; makefile->sol8speclibraries = NULL; makefile->linuxspeclibraries = NULL; makefile->freebsdspeclibraries = NULL; makefile->win32speclibraries = NULL; makefile->linkerlibraries = NULL; makefile->additionalObjects = NULL; makefile->linkerlibsearchpath = NULL; makefile->generatorCommandOutput = NULL; makefile->target_placement_list = NULL; } /** Deallocates all memory associated with structure \a makefile. */ static void free_makefile_struct(const struct makefile_struct *makefile) { Free(makefile->project_name); size_t i; for (i = 0; i < makefile->nTTCN3Modules; i++) { Free(makefile->TTCN3Modules[i].dir_name); Free(makefile->TTCN3Modules[i].file_name); Free(makefile->TTCN3Modules[i].module_name); } Free(makefile->TTCN3Modules); for (i = 0; i < makefile->nTTCN3PPModules; i++) { Free(makefile->TTCN3PPModules[i].dir_name); Free(makefile->TTCN3PPModules[i].file_name); Free(makefile->TTCN3PPModules[i].module_name); } Free(makefile->TTCN3PPModules); for (i = 0; i < makefile->nTTCN3IncludeFiles; i++) Free(makefile->TTCN3IncludeFiles[i]); Free(makefile->TTCN3IncludeFiles); for (i = 0; i < makefile->nASN1Modules; i++) { Free(makefile->ASN1Modules[i].dir_name); Free(makefile->ASN1Modules[i].file_name); Free(makefile->ASN1Modules[i].module_name); } Free(makefile->ASN1Modules); for (i = 0; i < makefile->nUserFiles; i++) { Free(makefile->UserFiles[i].dir_name); Free(makefile->UserFiles[i].file_prefix); Free(makefile->UserFiles[i].header_name); Free(makefile->UserFiles[i].source_name); } Free(makefile->UserFiles); for (i = 0; i < makefile->nOtherFiles; i++) Free(makefile->OtherFiles[i]); Free(makefile->OtherFiles); Free(makefile->BaseDirs); Free(makefile->working_dir); Free(makefile->ets_name); Free(makefile->output_file); Free(makefile->code_splitting_mode); Free(makefile->tcov_file_name); } /** Displays the contents of structure \a makefile as debug messages. */ static void dump_makefile_struct(const struct makefile_struct *makefile, unsigned level) { size_t i; DEBUG(level, "Data used for Makefile generation:"); DEBUG(level + 1, "TTCN-3 project name: %s", makefile->project_name); DEBUG(level + 1, "TTCN-3 modules: (%u pcs.)", makefile->nTTCN3Modules); for (i = 0; i < makefile->nTTCN3Modules; i++) { const struct module_struct *module = makefile->TTCN3Modules + i; DEBUG(level + 2, "Module name: %s", module->module_name); if (module->dir_name != NULL) DEBUG(level + 3, "Directory: %s", module->dir_name); DEBUG(level + 3, "File name: %s", module->file_name); DEBUG(level + 3, "Follows the naming convention: %s", module->is_regular ? "yes" : "no"); } DEBUG(level + 1, "TTCN-3 preprocessing: %s", makefile->preprocess ? "yes" : "no"); if (makefile->preprocess) { DEBUG(level + 1, "TTCN-3 modules to be preprocessed: (%u pcs.)", makefile->nTTCN3PPModules); for (i = 0; i < makefile->nTTCN3PPModules; i++) { const struct module_struct *module = makefile->TTCN3PPModules + i; DEBUG(level + 2, "Module name: %s", module->module_name); if (module->dir_name != NULL) DEBUG(level + 3, "Directory: %s", module->dir_name); DEBUG(level + 3, "File name: %s", module->file_name); DEBUG(level + 3, "Follows the naming convention: %s", module->is_regular ? "yes" : "no"); } DEBUG(level + 1, "TTCN-3 include files: (%u pcs.)", makefile->nTTCN3IncludeFiles); for (i = 0; i < makefile->nTTCN3IncludeFiles; i++) DEBUG(level + 2, "File name: %s", makefile->TTCN3IncludeFiles[i]); } DEBUG(level + 1, "All local TTCN-3 modules follow the naming convention: %s", makefile->TTCN3ModulesRegular ? "yes" : "no"); if (makefile->central_storage) DEBUG(level + 1, "All TTCN-3 modules from other " "directories follow the naming convention: %s", makefile->BaseTTCN3ModulesRegular ? "yes" : "no"); DEBUG(level + 1, "ASN.1 modules: (%u pcs.)", makefile->nASN1Modules); for (i = 0; i < makefile->nASN1Modules; i++) { const struct module_struct *module = makefile->ASN1Modules + i; DEBUG(level + 2, "Module name: %s", module->module_name); if (module->dir_name != NULL) DEBUG(level + 3, "Directory: %s", module->dir_name); DEBUG(level + 3, "File name: %s", module->file_name); DEBUG(level + 3, "Follows the naming convention: %s", module->is_regular ? "yes" : "no"); } DEBUG(level + 1, "All local ASN.1 modules follow the naming convention: %s", makefile->ASN1ModulesRegular ? "yes" : "no"); if (makefile->central_storage) DEBUG(level + 1, "All ASN.1 modules from other " "directories follow the naming convention: %s", makefile->BaseASN1ModulesRegular ? "yes" : "no"); DEBUG(level + 1, "User C/C++ modules: (%u pcs.)", makefile->nUserFiles); for (i = 0; i < makefile->nUserFiles; i++) { const struct user_struct *user = makefile->UserFiles + i; DEBUG(level + 2, "File prefix: %s", user->file_prefix); if (user->dir_name != NULL) DEBUG(level + 3, "Directory: %s", user->dir_name); if (user->header_name != NULL) { DEBUG(level + 3, "Header file: %s", user->header_name); DEBUG(level + 3, "Header file has .hh or .hpp suffix: %s", user->has_hh_suffix ? "yes" : "no"); } if (user->source_name != NULL) { DEBUG(level + 3, "Source file: %s", user->source_name); DEBUG(level + 3, "Source file has .cc or .cpp suffix: %s", user->has_cc_suffix ? "yes" : "no"); DEBUG(level + 3, "Object file: %s.o", user->file_prefix); } } DEBUG(level + 1, "All local C/C++ header files follow the naming " "convention: %s", makefile->UserHeadersRegular ? "yes" : "no"); DEBUG(level + 1, "All local C/C++ source files follow the naming " "convention: %s", makefile->UserSourcesRegular ? "yes" : "no"); if (makefile->central_storage) { DEBUG(level + 1, "All C/C++ header files from other directories follow the " "naming convention: %s", makefile->BaseUserHeadersRegular ? "yes" : "no"); DEBUG(level + 1, "All C/C++ source files from other directories follow the " "naming convention: %s", makefile->BaseUserSourcesRegular ? "yes" : "no"); } DEBUG(level + 1, "Other files: (%u pcs.)", makefile->nOtherFiles); for (i = 0; i < makefile->nOtherFiles; i++) DEBUG(level + 2, "File name: %s", makefile->OtherFiles[i]); DEBUG(level + 1, "Use pre-compiled files from central storage: %s", makefile->central_storage ? "yes" : "no"); if (makefile->central_storage) { DEBUG(level + 1, "Directories of pre-compiled files: (%u pcs.)", makefile->nBaseDirs); for (i = 0; i < makefile->nBaseDirs; i++) { const struct base_dir_struct *base_dir = makefile->BaseDirs + i; DEBUG(level + 2, "Directory: %s", base_dir->dir_name); DEBUG(level + 3, "Has TTCN-3/ASN.1 modules: %s", base_dir->has_modules ? "yes" : "no"); } } DEBUG(level + 1, "Working directory: %s", makefile->working_dir != NULL ? makefile->working_dir : "<unknown>"); DEBUG(level + 1, "GNU make: %s", makefile->gnu_make ? "yes" : "no"); DEBUG(level + 1, "Execution mode: %s", makefile->single_mode ? "single" : "parallel"); DEBUG(level + 1, "Name of executable: %s", makefile->ets_name != NULL ? makefile->ets_name : "<unknown>"); DEBUG(level + 1, "Output file: %s", makefile->output_file != NULL ? makefile->output_file : "<unknown>"); DEBUG(level + 1, "Force overwrite: %s", makefile->force_overwrite ? "yes" : "no"); DEBUG(level + 1, "Use function test runtime: %s", makefile->use_runtime_2 ? "yes" : "no"); DEBUG(level + 1, "Use dynamic linking: %s", makefile->dynamic ? "yes" : "no"); DEBUG(level + 1, "Code splitting mode: %s", makefile->code_splitting_mode != NULL ? makefile->code_splitting_mode : "<unknown>"); DEBUG(level + 1, "Code coverage file: %s", makefile->tcov_file_name != NULL ? makefile->tcov_file_name : "<unknown>"); if (makefile->profiled_file_list) { char* lists = mcopystr(makefile->profiled_file_list->str); struct string_list* iter = makefile->profiled_file_list->next; while(iter != NULL) { lists = mputprintf(lists, " %s", iter->str); iter = iter->next; } DEBUG(level + 1, "Profiled file list(s): %s", lists); Free(lists); } #ifdef COVERAGE_BUILD DEBUG(level + 1, "Enable coverage: %s", makefile->coverage ? "yes" : "no"); #endif } /** Returns the name of an existing file that is related to command line * argument \a argument. Tries the given list of suffixes. NULL pointer is * returned if no file was found. The returned string shall be deallocated * by the caller. */ static char *get_file_name_for_argument(const char *argument) { static const char * const suffix_list[] = { "", ".ttcnpp", ".ttcnin", ".ttcn", ".ttcn3", ".3mp", ".asn", ".asn1", ".cc", ".c", ".cpp", ".hh", ".h",".hpp", ".cfg", ".prj", NULL }; const char * const *suffix_ptr; for (suffix_ptr = suffix_list; *suffix_ptr != NULL; suffix_ptr++) { char *file_name = mputstr(mcopystr(argument), *suffix_ptr); if (get_path_status(file_name) == PS_FILE) return file_name; Free(file_name); } return NULL; } /** Converts \a path_name to an absolute directory using \a working_dir. * NULL pointer is returned if \a path_name does not contain a directory or * the resulting absolute directory is identical to \a working_dir. * The returned string shall be deallocated by the caller. */ static char *get_dir_name(const char *path_name, const char *working_dir) { char *dir_name = get_dir_from_path(path_name); if (dir_name != NULL) { char *absolute_dir = get_absolute_dir(dir_name, working_dir, TRUE); Free(dir_name); if (absolute_dir == NULL || working_dir == NULL) { /* an error occurred */ return NULL; } else if (!strcmp(absolute_dir, working_dir)) { /* the directory is identical to the working dir */ Free(absolute_dir); return NULL; } else return absolute_dir; } else return NULL; } /** Returns whether \a dirname1 and \a dirname2 contain the same (canonized * absolute) directories. NULL pointer is handled in a special way: it is * identical only to itself. */ static boolean is_same_directory(const char *dirname1, const char *dirname2) { if (dirname1 == NULL) { if (dirname2 == NULL) return TRUE; else return FALSE; } else { if (dirname2 == NULL) return FALSE; else if (strcmp(dirname1, dirname2)) return FALSE; else return TRUE; } } /** Returns whether the file \a filename1 in directory \a dirname1 is identical * to file \a filename2 in directory \a dirname2. Only the directory names can * be NULL. */ static boolean is_same_file(const char *dirname1, const char *filename1, const char *dirname2, const char *filename2) { /* first examine the file names for efficiency reasons */ if (strcmp(filename1, filename2)) return FALSE; else return is_same_directory(dirname1, dirname2); } /** Determines whether the TTCN-3 or ASN.1 module identifiers \a module1 and * \a module2 are the same. Characters '-' and '_' in module names are not * distinguished. */ static boolean is_same_module(const char *module1, const char *module2) { size_t i; for (i = 0; ; i++) { switch (module1[i]) { case '\0': if (module2[i] == '\0') return TRUE; else return FALSE; case '-': case '_': if (module2[i] != '-' && module2[i] != '_') return FALSE; break; default: if (module1[i] != module2[i]) return FALSE; break; } } return FALSE; /* to avoid warnings */ } /** Determines the suffix (i.e. the character sequence following the last dot) * of file or path name \a file_name. NULL pointer is returned if \a file_name * does not contain any dot character or the last character of it is a dot. * The suffix is not copied, the returned pointer points to the tail of * \a file_name. */ static const char *get_suffix(const char *file_name) { size_t last_dot = (size_t)-1; size_t i; for (i = 0; file_name[i] != '\0'; i++) if (file_name[i] == '.') last_dot = i; if (last_dot == (size_t)-1 || file_name[last_dot + 1] == '\0') return NULL; else return file_name + last_dot + 1; } /** Truncates the suffix (i.e. the last dot and the characters following it) * from \a file_name and returns a copy of the prefix of \a file_name. * If \a file_name does not have a suffix an exact copy of it is returned. * The returned string shall be deallocated by the caller. */ static char *cut_suffix(const char *file_name) { char *ret_val; size_t last_dot = (size_t)-1; size_t i; for (i = 0; file_name[i] != '\0'; i++) if (file_name[i] == '.') last_dot = i; ret_val = mcopystr(file_name); if (last_dot != (size_t)-1) ret_val = mtruncstr(ret_val, last_dot); return ret_val; } /** Determines the name of the preprocessed file from \a file_name. * It is assumed that \a file_name has ttcnpp suffix. * The returned string shall be deallocated by the caller. */ static char *get_preprocessed_file_name(const char *file_name) { char *ret_val = cut_suffix(file_name); ret_val = mputstr(ret_val, ".ttcn"); return ret_val; } /** Check if any of the preprocessed ttcn file names with the preprocessed * (TTCN-3) suffix is equal to any other file given in the \a makefile */ static void check_preprocessed_filename_collision( struct makefile_struct *makefile) { size_t i; if (makefile->nTTCN3PPModules == 0) { WARNING("TTCN-3 preprocessing (option `-p') is enabled, but no TTCN-3 " "files to be preprocessed were given for the Makefile."); } for (i = 0; i < makefile->nTTCN3PPModules; i++) { const struct module_struct *pp_module = makefile->TTCN3PPModules + i; /* name of the intermediate preprocessed file */ char *preprocessed_name = get_preprocessed_file_name(pp_module->file_name); size_t j; for (j = 0; j < makefile->nTTCN3Modules; j++) { struct module_struct *module = makefile->TTCN3Modules + j; if (is_same_file(pp_module->dir_name, preprocessed_name, module->dir_name, module->file_name)) { if (is_same_module(pp_module->module_name, module->module_name)) { /* same file with the same module */ char *pp_pathname = compose_path_name(pp_module->dir_name, pp_module->file_name); char *m_pathname = compose_path_name(module->dir_name, module->file_name); WARNING("File `%s' containing TTCN-3 module `%s' is generated by " "the preprocessor from `%s'. Removing the file from the list of " "normal TTCN-3 modules.", m_pathname, module->module_name, pp_pathname); Free(pp_pathname); Free(m_pathname); Free(module->dir_name); Free(module->file_name); Free(module->module_name); makefile->nTTCN3Modules--; memmove(module, module + 1, (makefile->nTTCN3Modules - j) * sizeof(*makefile->TTCN3Modules)); makefile->TTCN3Modules = (struct module_struct*)Realloc(makefile->TTCN3Modules, makefile->nTTCN3Modules * sizeof(*makefile->TTCN3Modules)); } else { /* same file with different module */ char *pp_pathname = compose_path_name(pp_module->dir_name, pp_module->file_name); char *m_pathname = compose_path_name(module->dir_name, module->file_name); ERROR("Preprocessed intermediate file of `%s' (module `%s') clashes " "with file `%s' containing TTCN-3 module `%s'.", pp_pathname, pp_module->module_name, m_pathname, module->module_name); Free(pp_pathname); Free(m_pathname); } } else if (is_same_module(pp_module->module_name, module->module_name)) { /* different file with the same module */ char *pp_pathname = compose_path_name(pp_module->dir_name, pp_module->file_name); char *m_pathname = compose_path_name(module->dir_name, module->file_name); ERROR("Both files `%s' and `%s' contain TTCN-3 module `%s'.", pp_pathname, m_pathname, pp_module->module_name); Free(pp_pathname); Free(m_pathname); } } for (j = 0; j < makefile->nASN1Modules; j++) { struct module_struct *module = makefile->ASN1Modules + j; if (is_same_file(pp_module->dir_name, preprocessed_name, module->dir_name, module->file_name)) { char *pp_pathname = compose_path_name(pp_module->dir_name, pp_module->file_name); char *m_pathname = compose_path_name(module->dir_name, module->file_name); ERROR("Preprocessed intermediate file of `%s' (module `%s') clashes " "with file `%s' containing ASN.1 module `%s'.", pp_pathname, pp_module->module_name, m_pathname, module->module_name); Free(pp_pathname); Free(m_pathname); } } for (j = 0; j < makefile->nOtherFiles; j++) { char *dir_name = get_dir_name(makefile->OtherFiles[j], makefile->working_dir); char *file_name = get_file_from_path(makefile->OtherFiles[j]); if (is_same_file(pp_module->dir_name, preprocessed_name, dir_name, file_name)) { char *pp_pathname = compose_path_name(pp_module->dir_name, pp_module->file_name); ERROR("Preprocessed intermediate file of `%s' (module `%s') clashes " "with other file `%s'.", pp_pathname, pp_module->module_name, makefile->OtherFiles[j]); Free(pp_pathname); } Free(dir_name); Free(file_name); } Free(preprocessed_name); } } /** Checks the name clash between existing module \a module and newly added * module with parameters \a path_name, \a dir_name, \a file_name, * \a module_name. Both the existing and the new module shall be of the same * kind, parameter \a kind shall contain the respective string (either "ASN.1" * or "TTCN-3"). If a clash is found the parameters of the new module except * \a path_name are deallocated and TRUE is returned. Otherwise FALSE is * returned. */ static boolean check_module_clash_same(const struct module_struct *module, const char *kind, const char *path_name, char *dir_name, char *file_name, char *module_name) { if (is_same_module(module_name, module->module_name)) { if (is_same_file(dir_name, file_name, module->dir_name, module->file_name)) { /* the same file was given twice: just issue a warning */ WARNING("File `%s' was given more than once for the Makefile.", path_name); } else { /* two different files contain the same module: this cannot be * resolved as the generated C++ files will clash */ char *path_name1 = compose_path_name(module->dir_name, module->file_name); char *path_name2 = compose_path_name(dir_name, file_name); ERROR("Both files `%s' and `%s' contain %s module `%s'.", path_name1, path_name2, kind, module_name); Free(path_name1); Free(path_name2); } Free(file_name); Free(dir_name); Free(module_name); return TRUE; } else return FALSE; } /** Checks the name clash between existing module \a module and newly added * module with parameters \a dir_name, \a file_name, \a module_name. The two * modules shall be of different kinds (one is ASN.1, the other is TTCN-3). * Parameters \a kind1 and \a kind2 shall contain the respective strings. If a * clash is found the parameters of the new module are deallocated and TRUE is * returned. Otherwise FALSE is returned. */ static boolean check_module_clash_different(const struct module_struct *module, const char *kind1, char *dir_name, char *file_name, char *module_name, const char *kind2) { if (is_same_module(module_name, module->module_name)) { /* two different files contain the same module: this cannot be resolved * as the generated C++ files will clash */ char *path_name1 = compose_path_name(module->dir_name, module->file_name); char *path_name2 = compose_path_name(dir_name, file_name); ERROR("File `%s' containing %s module `%s' and file `%s' containing " "%s module `%s' cannot be used together in the same Makefile.", path_name1, kind1, module->module_name, path_name2, kind2, module_name); Free(path_name1); Free(path_name2); Free(file_name); Free(dir_name); Free(module_name); return TRUE; } else return FALSE; } /** Adds a TTCN-3 module to Makefile descriptor structure \a makefile. * The name of the TTCN-3 source file is \a path_name, the module identifier * is \a module_name. It is checked whether a file or module with the same name * already exists in \a makefile and an appropriate warning or error is * reported. */ static void add_ttcn3_module(struct makefile_struct *makefile, const char *path_name, char *module_name) { struct module_struct *module; char *dir_name = get_dir_name(path_name, makefile->working_dir); char *file_name = get_file_from_path(path_name); const char *suffix = get_suffix(file_name); size_t i; boolean is_preprocessed = FALSE; if (suffix != NULL) { if (!strcmp(suffix, "ttcnpp")) { if (makefile->preprocess) is_preprocessed = TRUE; else WARNING("The suffix of TTCN-3 file `%s' indicates that it should be " "preprocessed, but TTCN-3 preprocessing is not enabled. The file " "will be added to the list of normal TTCN-3 modules in the Makefile.", path_name); } else if (!strcmp(suffix, "ttcnin")) { WARNING("The suffix of file `%s' indicates that it should be a " "preprocessor include file, but it contains a TTCN-3 module named `%s'. " "The file will be added to the list of normal TTCN-3 modules in the " "Makefile.", path_name, module_name); } } for (i = 0; i < makefile->nASN1Modules; i++) { if (check_module_clash_different(makefile->ASN1Modules + i, "ASN.1", dir_name, file_name, module_name, "TTCN-3")) return; } /* never entered if suffix is NULL */ if (is_preprocessed) { char *file_prefix; for (i = 0; i < makefile->nTTCN3PPModules; i++) { if (check_module_clash_same(makefile->TTCN3PPModules + i, "TTCN-3", path_name, dir_name, file_name, module_name)) return; } /* clashes with normal TTCN-3 modules will be checked (and maybe resolved) * in \a check_preprocessed_filename_collision() */ /* add it to the list of TTCN-3 modules to be preprocessed */ makefile->TTCN3PPModules = (struct module_struct*) Realloc(makefile->TTCN3PPModules, (makefile->nTTCN3PPModules + 1) * sizeof(*makefile->TTCN3PPModules)); module = makefile->TTCN3PPModules + makefile->nTTCN3PPModules; makefile->nTTCN3PPModules++; module->dir_name = dir_name; module->file_name = file_name; module->module_name = module_name; file_prefix = cut_suffix(file_name); if (!strcmp(file_prefix, module_name)) module->is_regular = TRUE; else module->is_regular = FALSE; Free(file_prefix); } else { /* the file is not preprocessed */ for (i = 0; i < makefile->nTTCN3Modules; i++) { if (check_module_clash_same(makefile->TTCN3Modules + i, "TTCN-3", path_name, dir_name, file_name, module_name)) return; } /* clashes with preprocessed TTCN-3 modules will be checked (and maybe * resolved) in \a check_preprocessed_filename_collision() */ /* add it to the list of normal TTCN-3 modules */ makefile->TTCN3Modules = (struct module_struct*) Realloc(makefile->TTCN3Modules, (makefile->nTTCN3Modules + 1) * sizeof(*makefile->TTCN3Modules)); module = makefile->TTCN3Modules + makefile->nTTCN3Modules; makefile->nTTCN3Modules++; module->dir_name = dir_name; module->file_name = file_name; module->module_name = module_name; if (suffix != NULL && !strcmp(suffix, "ttcn")) { char *file_prefix = cut_suffix(file_name); if (!strcmp(file_prefix, module_name)) module->is_regular = TRUE; else module->is_regular = FALSE; Free(file_prefix); } else { module->is_regular = FALSE; } } } /** ASN.1 filename shall contain no hyphen */ static boolean is_valid_asn1_filename(const char* file_name) { if (0 == strchr(file_name, '-')) { return TRUE; } return FALSE; } /** Adds an ASN.1 module to Makefile descriptor structure \a makefile. * The name of the ASN.1 source file is \a path_name, the module identifier * is \a module_name. It is checked whether a file or module with the same name * already exists in \a makefile and an appropriate warning or error is * reported. */ static void add_asn1_module(struct makefile_struct *makefile, const char *path_name, char *module_name) { struct module_struct *module; char *dir_name = get_dir_name(path_name, makefile->working_dir); char *file_name = get_file_from_path(path_name); const char *suffix = get_suffix(file_name); size_t i; for (i = 0; i < makefile->nASN1Modules; i++) { if (check_module_clash_same(makefile->ASN1Modules + i, "ASN.1", path_name, dir_name, file_name, module_name)) return; } for (i = 0; i < makefile->nTTCN3Modules; i++) { if (check_module_clash_different(makefile->TTCN3Modules + i, "TTCN-3", dir_name, file_name, module_name, "ASN.1")) return; } if (makefile->preprocess) { for (i = 0; i < makefile->nTTCN3PPModules; i++) { if (check_module_clash_different(makefile->TTCN3PPModules + i, "TTCN-3", dir_name, file_name, module_name, "ASN.1")) return; } } makefile->ASN1Modules = (struct module_struct*) Realloc(makefile->ASN1Modules, (makefile->nASN1Modules + 1) * sizeof(*makefile->ASN1Modules)); module = makefile->ASN1Modules + makefile->nASN1Modules; makefile->nASN1Modules++; module->dir_name = dir_name; module->file_name = file_name; module->module_name = module_name; if (suffix != NULL && !strcmp(suffix, "asn")) { char *file_prefix = cut_suffix(file_name); /* replace all '_' with '-' in file name prefix */ for (i = 0; file_prefix[i] != '\0'; i++) if (file_prefix[i] == '_') file_prefix[i] = '-'; if (!strcmp(file_prefix, module_name)) module->is_regular = TRUE; else module->is_regular = FALSE; Free(file_prefix); } else { module->is_regular = FALSE; } } /** Adds the file named \a path_name to the list of files pointed by \a list_ptr * and \a list_size. The suffix or contents of \a path_name are not examined, * only duplicate entries are checked. In case of duplicate entries warning is * reported only if argument \a report_warning is set to TRUE. */ static void add_path_to_list(size_t *list_size, char ***list_ptr, const char *path_name, const char *working_dir, boolean report_warning) { size_t i; char *dir_name = get_dir_name(path_name, working_dir); char *file_name = get_file_from_path(path_name); char *canonized_path_name = compose_path_name(dir_name, file_name); Free(dir_name); Free(file_name); for (i = 0; i < *list_size; i++) { if (!strcmp(canonized_path_name, (*list_ptr)[i])) { if (report_warning) WARNING("File `%s' was given more than once for the " "Makefile.", path_name); Free(canonized_path_name); return; } } *list_ptr = (char**)Realloc(*list_ptr, (*list_size + 1) * sizeof(**list_ptr)); (*list_ptr)[*list_size] = canonized_path_name; (*list_size)++; } /** Adds a C/C++ header or source file or an other file named \a path_name to * Makefile descriptor structure \a makefile. The file is classified based on * its suffix and not by content. If the file clashes with existing files or * modules the appropriate warning or error is generated. */ static void add_user_file(struct makefile_struct *makefile, const char *path_name) { const char *suffix = get_suffix(path_name); if (suffix != NULL) { if (!strcmp(suffix, "ttcn") || !strcmp(suffix, "ttcn3") || !strcmp(suffix, "3mp") || !strcmp(suffix, "ttcnpp")) { /* The file content was already checked. Since it doesn't look like * a valid TTCN-3 file, these suffixes are suspect */ WARNING("File `%s' does not contain a valid TTCN-3 module. " "It will be added to the Makefile as other file.", path_name); } else if (!strcmp(suffix, "ttcnin")) { /* this is a TTCN-3 include file */ if (makefile->preprocess) { add_path_to_list(&makefile->nTTCN3IncludeFiles, &makefile->TTCN3IncludeFiles, path_name, makefile->working_dir, TRUE); return; } else { WARNING("The suffix of file `%s' indicates that it is a TTCN-3 " "include file, but TTCN-3 preprocessing is not enabled. The file " "will be added to the Makefile as other file.", path_name); } } else if (!strcmp(suffix, "asn") || !strcmp(suffix, "asn1")) { /* The file content was already checked. Since it doesn't look like * a valid ASN.1 file, these suffixes are suspect */ WARNING("File `%s' does not contain a valid ASN.1 module. " "It will be added to the Makefile as other file.", path_name); } else if (!strcmp(suffix, "cc") || !strcmp(suffix, "c") || !strcmp(suffix, "cpp")) { /* this is a source file */ char *dir_name = get_dir_name(path_name, makefile->working_dir); char *file_name = get_file_from_path(path_name); char *file_prefix = cut_suffix(file_name); struct user_struct *user; size_t i; for (i = 0; i < makefile->nUserFiles; i++) { user = makefile->UserFiles + i; if (!strcmp(file_prefix, user->file_prefix)) { if (user->source_name != NULL) { /* the source file is already present */ if (is_same_file(dir_name, file_name, user->dir_name, user->source_name)) { WARNING("File `%s' was given more than once for the Makefile.", path_name); } else { char *path_name1 = compose_path_name(user->dir_name, user->source_name); char *path_name2 = compose_path_name(dir_name, file_name); ERROR("C/C++ source files `%s' and `%s' cannot be used together " "in the same Makefile.", path_name1, path_name2); Free(path_name1); Free(path_name2); } } else { /* a header file with the same prefix is already present */ if (is_same_directory(dir_name, user->dir_name)) { user->source_name = file_name; file_name = NULL; if (!strcmp(suffix, "cc") || !strcmp(suffix, "cpp")) user->has_cc_suffix = TRUE; } else { char *path_name1 = compose_path_name(dir_name, file_name); char *path_name2 = compose_path_name(user->dir_name, user->header_name); ERROR("C/C++ source file `%s' cannot be used together with " "header file `%s' in the same Makefile.", path_name1, path_name2); Free(path_name1); Free(path_name2); } } Free(dir_name); Free(file_name); Free(file_prefix); return; } } makefile->UserFiles = (struct user_struct*)Realloc(makefile->UserFiles, (makefile->nUserFiles + 1) * sizeof(*makefile->UserFiles)); user = makefile->UserFiles + makefile->nUserFiles; makefile->nUserFiles++; user->dir_name = dir_name; user->file_prefix = file_prefix; user->header_name = NULL; user->source_name = file_name; user->has_hh_suffix = FALSE; if (!strcmp(suffix, "cc") || !strcmp(suffix, "cpp")) user->has_cc_suffix = TRUE; else user->has_cc_suffix = FALSE; return; } else if (!strcmp(suffix, "hh") || !strcmp(suffix, "h")) { /* this is a header file */ char *dir_name = get_dir_name(path_name, makefile->working_dir); char *file_name = get_file_from_path(path_name); char *file_prefix = cut_suffix(file_name); struct user_struct *user; size_t i; for (i = 0; i < makefile->nUserFiles; i++) { user = makefile->UserFiles + i; if (!strcmp(file_prefix, user->file_prefix)) { if (user->header_name != NULL) { /* the header file is already present */ if (is_same_file(dir_name, file_name, user->dir_name, user->header_name)) { WARNING("File `%s' was given more than once for the Makefile.", path_name); } else { char *path_name1 = compose_path_name(user->dir_name, user->header_name); char *path_name2 = compose_path_name(dir_name, file_name); ERROR("C/C++ header files `%s' and `%s' cannot be used together " "in the same Makefile.", path_name1, path_name2); Free(path_name1); Free(path_name2); } } else { /* a source file with the same prefix is already present */ if (is_same_directory(dir_name, user->dir_name)) { user->header_name = file_name; file_name = NULL; if (!strcmp(suffix, "hh") || !strcmp(suffix, "hpp")) user->has_hh_suffix = TRUE; } else { char *path_name1 = compose_path_name(dir_name, file_name); char *path_name2 = compose_path_name(user->dir_name, user->source_name); ERROR("C/C++ header file `%s' cannot be used together with " "source file `%s' in the same Makefile.", path_name1, path_name2); Free(path_name1); Free(path_name2); } } Free(dir_name); Free(file_name); Free(file_prefix); return; } } makefile->UserFiles = (struct user_struct*)Realloc(makefile->UserFiles, (makefile->nUserFiles + 1) * sizeof(*makefile->UserFiles)); user = makefile->UserFiles + makefile->nUserFiles; makefile->nUserFiles++; user->dir_name = dir_name; user->file_prefix = file_prefix; user->header_name = file_name; user->source_name = NULL; if (!strcmp(suffix, "hh") || !strcmp(suffix, "hpp")) user->has_hh_suffix = TRUE; else user->has_hh_suffix = FALSE; user->has_cc_suffix = FALSE; return; } } /* end if (suffix != NULL) */ /* treat the file as other file if it was not handled yet */ add_path_to_list(&makefile->nOtherFiles, &makefile->OtherFiles, path_name, makefile->working_dir, TRUE); } /** Removes the generated C++ header and/or source files of module \a module * from Makefile descriptor structure \a makefile. A warning is displayed if * such file is found. */ static void drop_generated_files(struct makefile_struct *makefile, const struct module_struct *module) { char *module_name = mcopystr(module->module_name); size_t i; /* transform all '-' characters in ASN.1 module name to '_' */ for (i = 0; module_name[i] != '\0'; i++) if (module_name[i] == '-') module_name[i] = '_'; for (i = 0; i < makefile->nUserFiles; i++) { struct user_struct *user = makefile->UserFiles + i; if (!strcmp(module_name, user->file_prefix)) { char *m_pathname = compose_path_name(module->dir_name, module->file_name); /** Note: if central storage is used the generated C++ files are placed * into the same directory as the TTCN-3/ASN.1 modules, otherwise the * files are generated into the working directory. */ boolean is_same_dir = is_same_directory(user->dir_name, makefile->central_storage ? module->dir_name : NULL); if (user->header_name != NULL) { char *u_pathname = compose_path_name(user->dir_name, user->header_name); if (is_same_dir && user->has_hh_suffix) { WARNING("Header file `%s' is generated from module `%s' (file `%s'). " "Removing it from the list of user files.", u_pathname, module->module_name, m_pathname); } else { ERROR("Header file `%s' cannot be used together with module `%s' " "(file `%s') in the same Makefile.", u_pathname, module->module_name, m_pathname); } Free(u_pathname); } if (user->source_name != NULL) { char *u_pathname = compose_path_name(user->dir_name, user->source_name); if (is_same_dir && user->has_cc_suffix) { WARNING("Source file `%s' is generated from module `%s' (file " "`%s'). Removing it from the list of user files.", u_pathname, module->module_name, m_pathname); } else { ERROR("Source file `%s' cannot be used together with module " "`%s' (file `%s') in the same Makefile.", u_pathname, module->module_name, m_pathname); } Free(u_pathname); } Free(m_pathname); Free(user->dir_name); Free(user->file_prefix); Free(user->header_name); Free(user->source_name); makefile->nUserFiles--; memmove(user, user + 1, (makefile->nUserFiles - i) * sizeof(*makefile->UserFiles)); makefile->UserFiles = (struct user_struct*)Realloc(makefile->UserFiles, makefile->nUserFiles * sizeof(*makefile->UserFiles)); break; } } Free(module_name); } /** Drops all C++ header and source files of the Makefile descriptor structure * \a makefile that are generated from its TTCN-3 or ASN.1 modules. */ static void filter_out_generated_files(struct makefile_struct *makefile) { size_t i; for (i = 0; i < makefile->nTTCN3Modules; i++) { drop_generated_files(makefile, makefile->TTCN3Modules + i); } if (makefile->preprocess) { for (i = 0; i < makefile->nTTCN3PPModules; i++) { drop_generated_files(makefile, makefile->TTCN3PPModules + i); } } for (i = 0; i < makefile->nASN1Modules; i++) { drop_generated_files(makefile, makefile->ASN1Modules + i); } } /** Completes the list of user C/C++ header and source files in \a makefile. * If only the source file was given the function looks for the corresponding * header file or vice versa. */ static void complete_user_files(const struct makefile_struct *makefile) { size_t i; for (i = 0; i < makefile->nUserFiles; i++) { struct user_struct *user = makefile->UserFiles + i; if (user->header_name == NULL) { static const char * const suffix_list[] = { "hh", "h", "hpp", NULL }; const char * const *suffix_ptr; for (suffix_ptr = suffix_list; *suffix_ptr != NULL; suffix_ptr++) { char *file_name = mprintf("%s.%s", user->file_prefix, *suffix_ptr); char *path_name = compose_path_name(user->dir_name, file_name); if (get_path_status(path_name) == PS_FILE) { Free(path_name); user->header_name = file_name; if (!strcmp(*suffix_ptr, "hh") || !strcmp(*suffix_ptr, "hpp")) user->has_hh_suffix = TRUE; break; } Free(file_name); Free(path_name); } } else if (user->source_name == NULL) { static const char * const suffix_list[] = { "cc", "c", "cpp", NULL }; const char * const *suffix_ptr; for (suffix_ptr = suffix_list; *suffix_ptr != NULL; suffix_ptr++) { char *file_name = mprintf("%s.%s", user->file_prefix, *suffix_ptr); char *path_name = compose_path_name(user->dir_name, file_name); if (get_path_status(path_name) == PS_FILE) { Free(path_name); user->source_name = file_name; if (!strcmp(*suffix_ptr, "cc") || !strcmp(*suffix_ptr, "cpp")) user->has_cc_suffix = TRUE; break; } Free(file_name); Free(path_name); } } } } /** Converts the directory name pointed by \a dir_ptr to a relative pathname * based on \a working_dir. The original directory name is deallocated and * replaced with a new string. Nothing happens if \a dir_ptr points to NULL. */ static void replace_dir_with_relative(char **dir_ptr, const char *working_dir) { if (*dir_ptr != NULL) { char *rel_dir = get_relative_dir(*dir_ptr, working_dir); Free(*dir_ptr); *dir_ptr = rel_dir; } } /** Converts the directory part of path name pointed by \a path_ptr to a relative * pathname based on \a working_dir. The original path name is deallocated and * replaced with a new string. */ static void convert_path_to_relative(char **path_ptr, const char *working_dir) { char *dir_name = get_dir_name(*path_ptr, working_dir); if (dir_name != NULL) { char *file_name = get_file_from_path(*path_ptr); replace_dir_with_relative(&dir_name, working_dir); Free(*path_ptr); *path_ptr = compose_path_name(dir_name, file_name); Free(file_name); Free(dir_name); } } /** Converts all directories used by the Makefile descriptor structure * \a makefile to relative pathnames based on the working directory stored in * \a makefile. */ static void convert_dirs_to_relative(struct makefile_struct *makefile) { size_t i; for (i = 0; i < makefile->nTTCN3Modules; i++) { replace_dir_with_relative(&makefile->TTCN3Modules[i].dir_name, makefile->working_dir); } if (makefile->preprocess) { for (i = 0; i < makefile->nTTCN3PPModules; i++) { replace_dir_with_relative(&makefile->TTCN3PPModules[i].dir_name, makefile->working_dir); } for (i = 0; i < makefile->nTTCN3IncludeFiles; i++) { convert_path_to_relative(makefile->TTCN3IncludeFiles + i, makefile->working_dir); } } for (i = 0; i < makefile->nASN1Modules; i++) { replace_dir_with_relative(&makefile->ASN1Modules[i].dir_name, makefile->working_dir); } for (i = 0; i < makefile->nUserFiles; i++) { replace_dir_with_relative(&makefile->UserFiles[i].dir_name, makefile->working_dir); } for (i = 0; i < makefile->nOtherFiles; i++) { convert_path_to_relative(makefile->OtherFiles + i, makefile->working_dir); } if (makefile->ets_name != NULL) convert_path_to_relative(&makefile->ets_name, makefile->working_dir); } /* Returns whether the string \a file_name contains special characters. */ static boolean has_special_chars(const char *file_name) { if (file_name != NULL) { size_t i; for (i = 0; ; i++) { int c = (unsigned char)file_name[i]; switch (c) { case '\0': return FALSE; case ' ': case '*': case '?': case '[': case ']': case '<': case '=': case '>': case '|': case '&': case '$': case '%': case '{': case '}': case ';': case ':': case '(': case ')': case '#': case '!': case '\'': case '"': case '`': case '\\': return TRUE; default: if (!isascii(c) || !isprint(c)) return TRUE; break; } } } return FALSE; } /** Checks whether the path name composed of \a dir_name and \a file_name * contains special characters that are not allowed in the Makefile. Parameter * \a what contains the description of the corresponding file. */ static void check_special_chars_in_path(const char *dir_name, const char *file_name, const char *what) { if (has_special_chars(dir_name) || has_special_chars(file_name)) { char *path_name = compose_path_name(dir_name, file_name); ERROR("The name of %s `%s' contains special characters that cannot be " "handled properly by the `make' utility and/or the shell.", what, path_name); Free(path_name); } } /** Checks whether the directory names or file names that will be used in the * generated Makefile contain special characters that cannot be handled by the * "make" utility. */ static void check_special_chars(const struct makefile_struct *makefile) { size_t i; for (i = 0; i < makefile->nTTCN3Modules; i++) { check_special_chars_in_path(makefile->TTCN3Modules[i].dir_name, makefile->TTCN3Modules[i].file_name, "TTCN-3 file"); } if (makefile->preprocess) { for (i = 0; i < makefile->nTTCN3PPModules; i++) { check_special_chars_in_path(makefile->TTCN3PPModules[i].dir_name, makefile->TTCN3PPModules[i].file_name, "TTCN-3 file to be preprocessed"); } } for (i = 0; i < makefile->nASN1Modules; i++) { check_special_chars_in_path(makefile->ASN1Modules[i].dir_name, makefile->ASN1Modules[i].file_name, "ASN.1 file"); } for (i = 0; i < makefile->nUserFiles; i++) { const struct user_struct *user = makefile->UserFiles + i; if (user->source_name != NULL) check_special_chars_in_path(user->dir_name, user->source_name, "C/C++ source file"); else check_special_chars_in_path(user->dir_name, user->header_name, "C/C++ header file"); } for (i = 0; i < makefile->nOtherFiles; i++) { check_special_chars_in_path(NULL, makefile->OtherFiles[i], "other file"); } } /** Adds base directory \a dir_name to Makefile descriptor structure * \a makefile. Flag \a has_modules indicates whether \a dir_name contains * TTCN-3 and/or ASN.1 modules. The new directory is ignored if it is already * added to \a makefile. */ static void add_base_dir(struct makefile_struct *makefile, const char *dir_name, boolean has_modules) { struct base_dir_struct *base_dir; if (dir_name != NULL) { size_t i; for (i = 0; i < makefile->nBaseDirs; i++) { base_dir = makefile->BaseDirs + i; if (!strcmp(dir_name, base_dir->dir_name)) { if (has_modules) base_dir->has_modules = TRUE; return; } } makefile->BaseDirs = (struct base_dir_struct*)Realloc(makefile->BaseDirs, (makefile->nBaseDirs + 1) * sizeof(*makefile->BaseDirs)); base_dir = makefile->BaseDirs + makefile->nBaseDirs; makefile->nBaseDirs++; base_dir->dir_name = dir_name; base_dir->has_modules = has_modules; } } /** Collects all directories that are used in the Makefile descriptor structure * \a makefile in order to use pre-compiled files from them. */ static void collect_base_dirs(struct makefile_struct *makefile) { size_t i; for (i = 0; i < makefile->nTTCN3Modules; i++) { add_base_dir(makefile, makefile->TTCN3Modules[i].dir_name, TRUE); } if (makefile->preprocess) { for (i = 0; i < makefile->nTTCN3PPModules; i++) { add_base_dir(makefile, makefile->TTCN3PPModules[i].dir_name, TRUE); } } for (i = 0; i < makefile->nASN1Modules; i++) { add_base_dir(makefile, makefile->ASN1Modules[i].dir_name, TRUE); } for (i = 0; i < makefile->nUserFiles; i++) { add_base_dir(makefile, makefile->UserFiles[i].dir_name, FALSE); } if (makefile->nBaseDirs == 0) { WARNING("Usage of pre-compiled files from central storage (option `-c') " "is enabled, but all given files are located in the current working " "directory."); } } /** Checks whether the TTCN-3, ASN.1 and C++ files follow the default naming * convention and sets the appropriate flags accordingly. */ static void check_naming_convention(struct makefile_struct *makefile) { /* initially set all flags to true */ makefile->TTCN3ModulesRegular = TRUE; makefile->BaseTTCN3ModulesRegular = TRUE; makefile->ASN1ModulesRegular = TRUE; makefile->BaseASN1ModulesRegular = TRUE; makefile->UserHeadersRegular = TRUE; makefile->UserSourcesRegular = TRUE; makefile->BaseUserHeadersRegular = TRUE; makefile->BaseUserSourcesRegular = TRUE; if (makefile->central_storage) { /* this project (Makefile) will use pre-compiled files from other directories */ size_t i; for (i = 0; i < makefile->nTTCN3Modules; i++) { const struct module_struct *module = makefile->TTCN3Modules + i; if (module->dir_name != NULL) { if (!module->is_regular) makefile->BaseTTCN3ModulesRegular = FALSE; } else { if (!module->is_regular) makefile->TTCN3ModulesRegular = FALSE; } if (!makefile->TTCN3ModulesRegular && !makefile->BaseTTCN3ModulesRegular) break; } /* ttcnpp files are ttcn files */ if ((makefile->TTCN3ModulesRegular || makefile->BaseTTCN3ModulesRegular) && makefile->preprocess) { for (i = 0; i < makefile->nTTCN3PPModules; i++) { const struct module_struct *module = makefile->TTCN3PPModules + i; if (module->dir_name != NULL) { if (!module->is_regular) makefile->BaseTTCN3ModulesRegular = FALSE; } else { if (!module->is_regular) makefile->TTCN3ModulesRegular = FALSE; } if (!makefile->TTCN3ModulesRegular && !makefile->BaseTTCN3ModulesRegular) break; } } for (i = 0; i < makefile->nASN1Modules; i++) { const struct module_struct *module = makefile->ASN1Modules + i; if (module->dir_name != NULL) { if (!module->is_regular) makefile->BaseASN1ModulesRegular = FALSE; } else { if (!module->is_regular) makefile->ASN1ModulesRegular = FALSE; } if (!makefile->ASN1ModulesRegular && !makefile->BaseASN1ModulesRegular) break; } for (i = 0; i < makefile->nUserFiles; i++) { const struct user_struct *user = makefile->UserFiles + i; if (user->dir_name != NULL) { if (!user->has_cc_suffix) makefile->BaseUserSourcesRegular = FALSE; if (!user->has_cc_suffix || !user->has_hh_suffix) makefile->BaseUserHeadersRegular = FALSE; } else { if (!user->has_cc_suffix) makefile->UserSourcesRegular = FALSE; if (!user->has_cc_suffix || !user->has_hh_suffix) makefile->UserHeadersRegular = FALSE; } if (!makefile->UserHeadersRegular && !makefile->UserSourcesRegular && !makefile->BaseUserHeadersRegular && !makefile->BaseUserSourcesRegular) break; } } else { /* this project (Makefile) will-be stand-alone */ size_t i; for (i = 0; i < makefile->nTTCN3Modules; i++) { const struct module_struct *module = makefile->TTCN3Modules + i; if (!module->is_regular || module->dir_name != NULL) { makefile->TTCN3ModulesRegular = FALSE; break; } } if (makefile->TTCN3ModulesRegular && makefile->preprocess) { for (i = 0; i < makefile->nTTCN3PPModules; i++) { const struct module_struct *module = makefile->TTCN3PPModules + i; if (!module->is_regular || module->dir_name != NULL) { makefile->TTCN3ModulesRegular = FALSE; break; } } } for (i = 0; i < makefile->nASN1Modules; i++) { const struct module_struct *module = makefile->ASN1Modules + i; if (!module->is_regular || module->dir_name != NULL) { makefile->ASN1ModulesRegular = FALSE; break; } } for (i = 0; i < makefile->nUserFiles; i++) { const struct user_struct *user = makefile->UserFiles + i; if (!user->has_cc_suffix) makefile->UserSourcesRegular = FALSE; if (!user->has_cc_suffix || !user->has_hh_suffix) makefile->UserHeadersRegular = FALSE; if (!makefile->UserHeadersRegular && !makefile->UserSourcesRegular) break; } } } /** Prints the name of the TTCN-3 or ASN.1 source file that belongs to module * \a module to file \a fp. */ static void print_file_name(FILE *fp, const struct module_struct *module) { char *path_name = compose_path_name(module->dir_name, module->file_name); fprintf(fp, " %s", path_name); Free(path_name); } /** Prints the name of the preprocessed TTCN-3 source file that belongs to * module \a module to file \a fp. */ static void print_preprocessed_file_name(FILE *fp, const struct module_struct *module) { char *preprocessed_name = get_preprocessed_file_name(module->file_name); char *path_name = compose_path_name(module->dir_name, preprocessed_name); fprintf(fp, " %s", path_name); Free(path_name); Free(preprocessed_name); } /** Prints the name of the generated header, source or object file of module * \a module to file \a fp. The name of the directory is added only if * \a add_directory is TRUE. Parameter \a suffix shall be "hh", "cc", "hpp", "cpp" or "o". */ static void print_generated_file_name(FILE *fp, const struct module_struct *module, boolean add_directory, const char *suffix) { char *file_name = mcopystr(module->module_name); /* replace '-' with '_' */ size_t i; for (i = 0; file_name[i] != '\0'; i++) if (file_name[i] == '-') file_name[i] = '_'; /* append the suffix */ file_name = mputprintf(file_name, "%s", suffix); /* add the directory name if necessary */ if (add_directory) { char *path_name = compose_path_name(module->dir_name, file_name); Free(file_name); file_name = path_name; } fprintf(fp, " %s", file_name); Free(file_name); } /** Prints the name of the user C/C++ header file of user module \a user if the * above file exists. */ static void print_header_name(FILE *fp, const struct user_struct *user) { if (user->header_name != NULL) { char *path_name = compose_path_name(user->dir_name, user->header_name); fprintf(fp, " %s", path_name); Free(path_name); } } /** Prints the name of the user C/C++ source file of user module \a user if the * above file exists. */ static void print_source_name(FILE *fp, const struct user_struct *user) { if (user->source_name != NULL) { char *path_name = compose_path_name(user->dir_name, user->source_name); fprintf(fp, " %s", path_name); Free(path_name); } } /** Prints the name of the user C/C++ object file of user module \a user if the * above file exists (i.e. the respective source file is present). */ static void print_object_name(FILE *fp, const struct user_struct *user) { if (user->source_name != NULL) { char *file_name = mprintf("%s.o", user->file_prefix); char *path_name = compose_path_name(user->dir_name, file_name); Free(file_name); fprintf(fp, " %s", path_name); Free(path_name); } } static void print_shared_object_name(FILE *fp, const struct user_struct *user) { if (user->source_name != NULL) { char *file_name = mprintf("%s.so", user->file_prefix); char *path_name = compose_path_name(user->dir_name, file_name); Free(file_name); fprintf(fp, " %s", path_name); Free(path_name); } } /** Prints the splitted files' names for a given module. */ static void print_splitted_file_names(FILE *fp, const struct makefile_struct *makefile, const struct module_struct *module) { if (strcmp(makefile->code_splitting_mode, "-U type") == 0) { print_generated_file_name(fp, module, FALSE, "_seq.cc"); print_generated_file_name(fp, module, FALSE, "_set.cc"); print_generated_file_name(fp, module, FALSE, "_seqof.cc"); print_generated_file_name(fp, module, FALSE, "_setof.cc"); print_generated_file_name(fp, module, FALSE, "_union.cc"); } } static void fprint_extra_targets(FILE* fp, struct string2_list* target_placement_list, const char* placement) { struct string2_list* act_elem = target_placement_list; while (act_elem) { if (act_elem->str1 && act_elem->str2 && (strcmp(act_elem->str2,placement)==0)) { fprintf(fp, " %s", act_elem->str1); } act_elem = act_elem->next; } } #undef COMMENT_PREFIX #define COMMENT_PREFIX "# " /** Prints the Makefile based on structure \a makefile. */ static void print_makefile(struct makefile_struct *makefile) { boolean add_refd_prjs = FALSE; if (makefile->linkingStrategy && makefile->hierarchical) { add_refd_prjs = hasSubProject(makefile->project_name); } else { add_refd_prjs = makefile->sub_project_dirs && makefile->sub_project_dirs->str; } NOTIFY("Generating Makefile skeleton..."); if (makefile->force_overwrite || get_path_status(makefile->output_file) == PS_NONEXISTENT) { size_t i; char *user_info; const char* cxx; const char* cpp; const char *rm_command = makefile->gnu_make ? "$(RM)" : "rm -f"; FILE *fp; boolean run_compiler = (makefile->nASN1Modules > 0) || (makefile->nTTCN3Modules) || (makefile->nTTCN3PPModules > 0); expstring_t titan_dir = 0; const char * last_slash = strrchr(program_name, '/'); if (last_slash != NULL) { size_t path_len = last_slash - program_name; titan_dir = mcopystr(program_name); /* Chop off the program name, and the /bin before it (if any) */ if (path_len >= 4 && memcmp(titan_dir + path_len - 4, "/bin", 4) == 0) { titan_dir = mtruncstr(titan_dir, path_len - 4); } else { titan_dir = mtruncstr(titan_dir, path_len); } } fp = fopen(makefile->output_file, "w"); if (fp == NULL){ ERROR("Cannot open output file `%s' for writing: %s", makefile->output_file, strerror(errno)); return; } user_info = get_user_info(); fprintf(fp, "# This Makefile was generated by the Makefile Generator\n" "# of the TTCN-3 Test Executor version " PRODUCT_NUMBER "\n" "# for %s\n" COPYRIGHT_STRING "\n\n" "# The following make commands are available:\n" "# - make, make all Builds the %s.\n" "# - make archive Archives all source files.\n" "# - make check Checks the semantics of TTCN-3 and ASN.1" "modules.\n" "# - make port Generates port skeletons.\n" "%s" // clean: "%s" //clean-all "# - make compile Translates TTCN-3 and ASN.1 modules to C++.\n" "# - make dep Creates/updates dependency list.\n" "# - make executable Builds the executable test suite.\n" "# - make library Builds the library archive.\n" "# - make objects Builds the object files without linking the " "executable.\n", user_info, makefile->library ? "library archive." : "executable test suite", (makefile->linkingStrategy && makefile->hierarchical) ? "# - make clean Removes generated files from project.\n" : "# - make clean Removes all generated files.\n", (makefile->linkingStrategy && makefile->hierarchical) ? "# - make clean-all Removes all generated files from the project hierarchy.\n" : ""); Free(user_info); if (makefile->dynamic) fprintf(fp, "# - make shared_objects Builds the shared object files " "without linking the executable.\n"); if (makefile->preprocess) fputs("# - make preprocess Preprocess TTCN-3 files.\n", fp); if (makefile->central_storage) { fputs("# WARNING! This Makefile uses pre-compiled files from the " "following directories:\n", fp); for (i = 0; i < makefile->nBaseDirs; i++) fprintf(fp, "# %s\n", makefile->BaseDirs[i].dir_name); fputs("# The executable tests will be consistent only if all directories " "use\n" "# the same platform and the same version of TTCN-3 Test Executor " "and\n" "# C++ compiler with the same command line switches.\n\n", fp); } if (makefile->gnu_make) { fputs("# WARNING! This Makefile can be used with GNU make only.\n" "# Other versions of make may report syntax errors in it.\n\n" "#\n" "# Do NOT touch this line...\n" "#\n" ".PHONY: all shared_objects executable library objects check port clean dep archive", fp); if (makefile->preprocess) fputs(" preprocess", fp); if (add_refd_prjs) { fprintf(fp, "\\\n referenced-all referenced-shared_objects referenced-executable referenced-library referenced-objects referenced-check" "\\\n referenced-clean%s", (makefile->linkingStrategy && makefile->hierarchical) ? "-all" : ""); } fprint_extra_targets(fp, makefile->target_placement_list, "PHONY"); if (makefile->gcc_dep) { fputs("\n\n.SUFFIXES: .d", fp); } fputs("\n\n", fp); } if (makefile->linkingStrategy) { const char* tpd_name = getTPDFileName(makefile->project_name); if (tpd_name) { fputs("# Titan Project Descriptor file what this Makefile is generated from.\n", fp); fprintf(fp, "TPD = %s\n\n", tpd_name); } const char* root_dir = getPathToRootDir(makefile->project_name); if (root_dir) { fputs("# Relative path to top directory at OS level.\n", fp); fprintf(fp, "ROOT_DIR = %s\n\n", root_dir); } } if (add_refd_prjs) { struct string_list* act_elem = NULL; struct string_list* head = NULL; if (makefile->linkingStrategy && makefile->hierarchical) {// pair with free_string_list head = act_elem = getRefWorkingDirs(makefile->project_name); } else { act_elem = makefile->sub_project_dirs; } if (!makefile->linkingStrategy) fputs("# This is the top level makefile of a Makefile hierarchy generated from\n", fp); fputs("# Titan Project Descriptor hierarchy. List of referenced project\n" "# working directories (ordered by dependencies):\n", fp); while (act_elem) { if (act_elem->str) { fprintf(fp, "# %s\n", act_elem->str); } act_elem = act_elem->next; } if (makefile->linkingStrategy && makefile->hierarchical) { // pair with getRefWorkingDirs free_string_list(head); } fputs("REFERENCED_PROJECT_DIRS = ", fp); if (makefile->linkingStrategy && makefile->hierarchical) { head = act_elem = getRefWorkingDirs(makefile->project_name); // pair with free_string_list } else { act_elem = makefile->sub_project_dirs; } while (act_elem) { if (act_elem->str) { fprintf(fp, "%s ", act_elem->str); } act_elem = act_elem->next; } fputs("\n\n", fp); if (makefile->linkingStrategy && makefile->hierarchical) {// pair with getRefWorkingDirs free_string_list(head); } } fprintf(fp, "#\n" "# Set these variables...\n" "#\n\n" "# The path of your TTCN-3 Test Executor installation:\n" "# Uncomment this line to override the environment variable.\n" "%s" "# TTCN3_DIR = %s\n" , titan_dir ? "# The value below points to the location of the TITAN version\n" "# that generated this makefile.\n" : "" , titan_dir ? titan_dir : ""); if (titan_dir) Free(titan_dir); boolean cxx_free = FALSE; if (makefile->cxxcompiler) { cxx = makefile->cxxcompiler; } else { #ifdef __clang__ unsigned int compiler_major = __clang_major__, compiler_minor = __clang_minor__; cxx = mprintf("clang++-%u.%u", compiler_major, compiler_minor); cxx_free = TRUE; #else cxx = "g++"; #endif } fprintf(fp, "\n# Your platform: (SOLARIS, SOLARIS8, LINUX, FREEBSD or " "WIN32)\n" "PLATFORM = %s\n\n" "# Your C++ compiler:\n" "# (if you change the platform, you may need to change the compiler)\n" "CXX = %s \n\n", get_platform_string(), cxx); if (makefile->preprocess || makefile->ttcn3preprocessor) { if (makefile->ttcn3preprocessor) { cpp = makefile->ttcn3preprocessor; } else { cpp = "cpp"; } fprintf(fp,"# C preprocessor used for TTCN-3 files:\n" "CPP = %s\n\n", cpp); } fputs("# Flags for the C++ preprocessor (and makedepend as well):\n" "CPPFLAGS = -D$(PLATFORM) -I$(TTCN3_DIR)/include", fp); if (makefile->use_runtime_2) fputs(" -DTITAN_RUNTIME_2", fp); for (i = 0; i < makefile->nBaseDirs; i++) { fprintf(fp, " -I%s", makefile->BaseDirs[i].dir_name); } if (makefile->prep_includes) { struct string_list* act_elem = makefile->prep_includes; while (act_elem) { if (act_elem->str) { fprintf(fp, " -I%s", act_elem->str); } act_elem = act_elem->next; } } if (makefile->prep_defines) { struct string_list* act_elem = makefile->prep_defines; while (act_elem) { if (act_elem->str) { fprintf(fp, " -D%s", act_elem->str); } act_elem = act_elem->next; } } if (makefile->prep_undefines) { struct string_list* act_elem = makefile->prep_undefines; while (act_elem) { if (act_elem->str) { fprintf(fp, " -U%s", act_elem->str); } act_elem = act_elem->next; } } fputs("\n\n", fp); if (makefile->gcc_dep) { fprintf(fp, "# Flags for dependency generation\n" "CXXDEPFLAGS = -%s\n\n", strstr(cxx, "g++") ? "MM" : "xM1"); } if (cxx_free) { Free((char*)cxx); cxx = NULL; } if (makefile->preprocess || makefile->ttcn3_prep_includes || makefile->ttcn3_prep_defines) { fputs("# Flags for preprocessing TTCN-3 files:\n" "CPPFLAGS_TTCN3 =", fp); if (makefile->preprocess) { for (i = 0; i < makefile->nBaseDirs; i++) { fprintf(fp, " -I%s", makefile->BaseDirs[i].dir_name); } } if (makefile->ttcn3_prep_includes) { struct string_list* act_elem = makefile->ttcn3_prep_includes; while (act_elem) { if (act_elem->str) { fprintf(fp, " -I%s", act_elem->str); } act_elem = act_elem->next; } } if (makefile->ttcn3_prep_defines) { struct string_list* act_elem = makefile->ttcn3_prep_defines; while (act_elem) { if (act_elem->str) { fprintf(fp, " -D%s", act_elem->str); } act_elem = act_elem->next; } } if (makefile->ttcn3_prep_undefines) { struct string_list* act_elem = makefile->ttcn3_prep_undefines; while (act_elem) { if (act_elem->str) { fprintf(fp, " -U%s", act_elem->str); } act_elem = act_elem->next; } } fputs("\n\n", fp); } /* code splitting: command line argument wins */ if (makefile->code_splitting_mode == NULL) { if (makefile->codesplittpd) { makefile->code_splitting_mode = mcopystr("-U type"); } } fprintf(fp, "# Flags for the C++ compiler:\n" "CXXFLAGS = %s%s %s %s\n\n" "# Flags for the linker:\n" "LDFLAGS = %s%s\n\n" "ifeq ($(PLATFORM), WIN32)\n" "# Silence linker warnings.\n" "LDFLAGS += -Wl,--enable-auto-import,--enable-runtime-pseudo-reloc\n" "endif\n\n" "# Utility to create library files\n" "AR = ar\n" "ARFLAGS = \n\n" "# Flags for the TTCN-3 and ASN.1 compiler:\n" "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" "# Execution mode: (either ttcn3 or ttcn3-parallel)\n" "TTCN3_LIB = ttcn3%s%s%s\n\n" #ifdef LICENSE "# The path of your OpenSSL installation:\n" "# If you do not have your own one, leave it unchanged.\n" "%sOPENSSL_DIR = $(TTCN3_DIR)\n\n" #endif "# The path of your libxml2 installation:\n" "# If you do not have your own one, leave it unchanged.\n" "XMLDIR = $(TTCN3_DIR)\n\n" "# Directory to store the archived source files:\n", makefile->dynamic ? "-Wall -fPIC" : "-Wall", /* CXXFLAGS */ makefile->coverage ? " -fprofile-arcs -ftest-coverage -g" : "", /* CXXFLAGS COVERAGE */ makefile->optlevel ? makefile->optlevel : "", /* CXXFLAGS optimization level */ makefile->optflags ? makefile->optflags : "", /* CXXFLAGS optimization level */ makefile->dynamic ? "-fPIC" : "", /* LDFLAGS */ makefile->coverage ? " -fprofile-arcs -ftest-coverage -g -lgcov" : "", /* LDFLAGS COVERAGE */ /* COMPILER_FLAGS */ makefile->use_runtime_2 ? " -L -R " : " -L ", (makefile->code_splitting_mode ? makefile->code_splitting_mode : ""), (makefile->quietly ? " -q" : ""), (makefile->disablesubtypecheck ? " -y" : ""), (makefile->disableber ? " -b" : ""), (makefile->disableraw ? " -r" : ""), (makefile->disabletext ? " -x" : ""), (makefile->disablexer ? " -X" : ""), (makefile->disablejson ? " -j" : ""), (makefile->forcexerinasn ? " -a" : ""), (makefile->defaultasomit ? " -d" : ""), (makefile->gccmsgformat ? " -g" : ""), (makefile->linenumbersonlymsg ? " -i" : ""), (makefile->includesourceinfo ? " -l" : ""), /*(makefile->addsourcelineinfo ? " -L" : ""),*/ (makefile->suppresswarnings ? " -w" : ""), (makefile->outparamboundness ? " -Y" : ""), (makefile->omit_in_value_list ? " -M" : ""), (makefile->warnings_for_bad_variants ? " -E" : ""), (makefile->activate_debugger ? " -n" : ""), (makefile->tcov_file_name ? makefile->tcov_file_name : ""), (makefile->profiled_file_list ? " -z $(PROFILED_FILE_LIST)" : ""), /* end of COMPILER FLAGS */ (makefile->use_runtime_2 ? "-rt2" : ""), /* TTCN3_LIB */ (makefile->single_mode ? "" : "-parallel"), (makefile->dynamic ? "-dynamic": "") #ifdef LICENSE ,(makefile->disable_predef_ext_folder ? "# " : "") #endif ); if (!makefile->gnu_make) { fputs("# Note: you can set any directory except ./archive\n", fp); } fputs("ARCHIVE_DIR = backup\n\n" "#\n" "# You may change these variables. Add your files if necessary...\n" "#\n\n" "# TTCN-3 modules of this project:\n" "TTCN3_MODULES =", fp); for (i = 0; i < makefile->nTTCN3Modules; i++) { const struct module_struct *module = makefile->TTCN3Modules + i; if (module->dir_name == NULL || !makefile->central_storage) /* If the file is in the current directory or * is not in the current directory but central directory is not used, * it goes into TTCN3_MODULES */ print_file_name(fp, module); } fprint_extra_targets(fp, makefile->target_placement_list, "TTCN3_MODULES"); if (makefile->preprocess) { fputs("\n\n" "# TTCN-3 modules to preprocess:\n" "TTCN3_PP_MODULES =", fp); for (i = 0; i < makefile->nTTCN3PPModules; i++) { const struct module_struct *module = makefile->TTCN3PPModules + i; if (module->dir_name == NULL || !makefile->central_storage) print_file_name(fp, module); } fprint_extra_targets(fp, makefile->target_placement_list, "TTCN3_PP_MODULES"); } if (makefile->central_storage) { fputs("\n\n" "# TTCN-3 modules used from central project(s):\n" "BASE_TTCN3_MODULES =", fp); if (!makefile->linkingStrategy) { for (i = 0; i < makefile->nTTCN3Modules; i++) { const struct module_struct *module = makefile->TTCN3Modules + i; /* Central storage used AND file is not in the current directory => it goes into BASE_TTCN3_MODULES */ if (module->dir_name != NULL) print_file_name(fp, module); } if (makefile->preprocess) { fputs("\n\n" "# TTCN-3 modules to preprocess used from central project(s):\n" "BASE_TTCN3_PP_MODULES =", fp); for (i = 0; i < makefile->nTTCN3PPModules; i++) { const struct module_struct *module = makefile->TTCN3PPModules + i; if (module->dir_name != NULL && !isTtcnPPFileInLibrary(module->file_name)) print_file_name(fp, module); } } } else { // new linking strategy for (i = 0; i < makefile->nTTCN3Modules; i++) { const struct module_struct *module = makefile->TTCN3Modules + i; /* Central storage used AND file is not in the current directory => it goes into BASE_TTCN3_MODULES */ if (module->dir_name != NULL && !isTtcn3ModuleInLibrary(module->module_name)) print_file_name(fp, module); } fputs("\n\n" "# TTCN-3 library linked modules used from central project(s):\n" "BASE2_TTCN3_MODULES =", fp); for (i = 0; i < makefile->nTTCN3Modules; i++) { const struct module_struct *module = makefile->TTCN3Modules + i; /* Central storage used AND file is not in the current directory => it goes into BASE_TTCN3_MODULES */ if (module->dir_name != NULL && isTtcn3ModuleInLibrary(module->module_name)) print_file_name(fp, module); } if (makefile->preprocess) { fputs("\n\n" "# TTCN-3 modules to preprocess used from central project(s):\n" "BASE_TTCN3_PP_MODULES =", fp); for (i = 0; i < makefile->nTTCN3PPModules; i++) { const struct module_struct *module = makefile->TTCN3PPModules + i; if (module->dir_name != NULL && !isTtcnPPFileInLibrary(module->file_name)) print_file_name(fp, module); } fputs("\n\n" "# TTCN-3 library linked modules to preprocess used from central project(s):\n" "BASE2_TTCN3_PP_MODULES =", fp); for (i = 0; i < makefile->nTTCN3PPModules; i++) { const struct module_struct *module = makefile->TTCN3PPModules + i; if (module->dir_name != NULL && isTtcnPPFileInLibrary(module->file_name)) print_file_name(fp, module); } } } } if (makefile->preprocess) { fputs("\n\n" "# Files to include in TTCN-3 preprocessed modules:\n" "TTCN3_INCLUDES =", fp); for (i = 0; i < makefile->nTTCN3IncludeFiles; i++) fprintf(fp, " %s", makefile->TTCN3IncludeFiles[i]); fprint_extra_targets(fp, makefile->target_placement_list, "TTCN3_INCLUDES"); } fputs("\n\n" "# ASN.1 modules of this project:\n" "ASN1_MODULES =", fp); for (i = 0; i < makefile->nASN1Modules; i++) { const struct module_struct *module = makefile->ASN1Modules + i; if (module->dir_name == NULL || !makefile->central_storage) print_file_name(fp, module); } fprint_extra_targets(fp, makefile->target_placement_list, "ASN1_MODULES"); if (makefile->central_storage) { fputs("\n\n" "# ASN.1 modules used from central project(s):\n" "BASE_ASN1_MODULES =", fp); if (!makefile->linkingStrategy) { for (i = 0; i < makefile->nASN1Modules; i++) { const struct module_struct *module = makefile->ASN1Modules + i; if (module->dir_name != NULL) print_file_name(fp, module); } } else { for (i = 0; i < makefile->nASN1Modules; i++) { const struct module_struct *module = makefile->ASN1Modules + i; if (module->dir_name != NULL && !isAsn1ModuleInLibrary(module->module_name)) print_file_name(fp, module); } fputs("\n\n" "# ASN.1 library linked modules used from central project(s):\n" "BASE2_ASN1_MODULES =", fp); for (i = 0; i < makefile->nASN1Modules; i++) { const struct module_struct *module = makefile->ASN1Modules + i; if (module->dir_name != NULL && isAsn1ModuleInLibrary(module->module_name)) print_file_name(fp, module); } } } if (makefile->preprocess) { fputs("\n\n" "# TTCN-3 source files generated by the C preprocessor:\n" "PREPROCESSED_TTCN3_MODULES =", fp); for (i = 0; i < makefile->nTTCN3PPModules; i++) { const struct module_struct *module = makefile->TTCN3PPModules + i; if (module->dir_name == NULL || !makefile->central_storage) print_preprocessed_file_name(fp, module); } if (makefile->central_storage) { fputs("\n\n" "# TTCN-3 files generated by the CPP used from central project(s):\n" "BASE_PREPROCESSED_TTCN3_MODULES =", fp); if (!makefile->linkingStrategy) { for (i = 0; i < makefile->nTTCN3PPModules; i++) { const struct module_struct *module = makefile->TTCN3PPModules + i; if (module->dir_name != NULL) print_preprocessed_file_name(fp, module); } } else { // new linking strategy for (i = 0; i < makefile->nTTCN3PPModules; i++) { const struct module_struct *module = makefile->TTCN3PPModules + i; if (module->dir_name != NULL && !isTtcnPPFileInLibrary(module->file_name)) print_preprocessed_file_name(fp, module); } fputs("\n\n" "# TTCN-3 library linked files generated by the CPP used from central project(s):\n" "BASE2_PREPROCESSED_TTCN3_MODULES =", fp); for (i = 0; i < makefile->nTTCN3PPModules; i++) { const struct module_struct *module = makefile->TTCN3PPModules + i; if (module->dir_name != NULL && isTtcnPPFileInLibrary(module->file_name)) print_preprocessed_file_name(fp, module); } } } } if (makefile->profiled_file_list) { if (makefile->profiled_file_list->next && !makefile->central_storage) { // merge all profiled file lists into one list fprintf(fp, "\n\n" "# Text file containing the list of profiled TTCN-3 files of " "this project:\n" "PROFILED_FILE_LIST = %s.merged\n" "PROFILED_FILE_LIST_SEGMENTS =", makefile->profiled_file_list->str); struct string_list* iter = makefile->profiled_file_list; while(iter != NULL) { fprintf(fp, " %s", iter->str); iter = iter->next; } } else { // only one profiled file list is needed fprintf(fp, "\n\n" "# Text file containing the list of profiled TTCN-3 files of " "this project:\n" "PROFILED_FILE_LIST = %s", makefile->profiled_file_list->str); } } fputs("\n\n" "# C++ source & header files generated from the TTCN-3 & ASN.1 " "modules of\n" "# this project:\n" "GENERATED_SOURCES =", fp); if (makefile->gnu_make && makefile->TTCN3ModulesRegular) { fputs(" $(TTCN3_MODULES:.ttcn=.cc)", fp); if (makefile->code_splitting_mode) { for (i = 0; i < makefile->nTTCN3Modules; i++) { const struct module_struct *module = makefile->TTCN3Modules + i; if (module->dir_name == NULL || !makefile->central_storage) print_splitted_file_names(fp, makefile, module); } } if (makefile->preprocess) { fputs(" $(TTCN3_PP_MODULES:.ttcnpp=.cc)", fp); if (makefile->code_splitting_mode) { for (i = 0; i < makefile->nTTCN3PPModules; i++) { const struct module_struct *module = makefile->TTCN3PPModules + i; if (module->dir_name == NULL || !makefile->central_storage) print_splitted_file_names(fp, makefile, module); } } } } else { for (i = 0; i < makefile->nTTCN3Modules; i++) { const struct module_struct *module = makefile->TTCN3Modules + i; if (module->dir_name == NULL || !makefile->central_storage) { print_generated_file_name(fp, module, FALSE, ".cc"); if (makefile->code_splitting_mode) print_splitted_file_names(fp, makefile, module); } } if (makefile->preprocess) { for (i = 0; i < makefile->nTTCN3PPModules; i++) { const struct module_struct *module = makefile->TTCN3PPModules + i; if (module->dir_name == NULL || !makefile->central_storage) { print_generated_file_name(fp, module, FALSE, ".cc"); if (makefile->code_splitting_mode) print_splitted_file_names(fp, makefile, module); } } } } if (makefile->gnu_make && makefile->ASN1ModulesRegular) { fputs(" $(ASN1_MODULES:.asn=.cc)", fp); if (makefile->code_splitting_mode) { for (i = 0; i < makefile->nASN1Modules; i++) { const struct module_struct *module = makefile->ASN1Modules + i; if (module->dir_name == NULL || !makefile->central_storage) { print_splitted_file_names(fp, makefile, module); } } } } else { for (i = 0; i < makefile->nASN1Modules; i++) { const struct module_struct *module = makefile->ASN1Modules + i; if (module->dir_name == NULL || !makefile->central_storage) { print_generated_file_name(fp, module, FALSE, ".cc"); if (makefile->code_splitting_mode) print_splitted_file_names(fp, makefile, module); } } } fputs("\nGENERATED_HEADERS =", fp); if (makefile->gnu_make) { fputs(" $(GENERATED_SOURCES:.cc=.hh)", fp); } else { for (i = 0; i < makefile->nTTCN3Modules; i++) { const struct module_struct *module = makefile->TTCN3Modules + i; if (module->dir_name == NULL || !makefile->central_storage) print_generated_file_name(fp, module, FALSE, ".hh"); } if (makefile->preprocess) { for (i = 0; i < makefile->nTTCN3PPModules; i++) { const struct module_struct *module = makefile->TTCN3PPModules + i; if (module->dir_name == NULL || !makefile->central_storage) print_generated_file_name(fp, module, FALSE, ".hh"); } } for (i = 0; i < makefile->nASN1Modules; i++) { const struct module_struct *module = makefile->ASN1Modules + i; if (module->dir_name == NULL || !makefile->central_storage) print_generated_file_name(fp, module, FALSE, ".hh"); } } if (makefile->central_storage) { fputs("\n\n" "# C++ source & header files generated from the TTCN-3 & ASN.1 " "modules of\n" "# central project(s):\n" "BASE_GENERATED_SOURCES =", fp); if (makefile->gnu_make && makefile->BaseTTCN3ModulesRegular) { fputs(" $(BASE_TTCN3_MODULES:.ttcn=.cc)", fp); if (makefile->code_splitting_mode) { for (i = 0; i < makefile->nTTCN3Modules; i++) { const struct module_struct *module = makefile->TTCN3Modules + i; if (module->dir_name != NULL) { print_splitted_file_names(fp, makefile, module); } } } if (makefile->preprocess) { fputs(" $(BASE_TTCN3_PP_MODULES:.ttcnpp=.cc)", fp); if (makefile->code_splitting_mode) { for (i = 0; i < makefile->nTTCN3PPModules; i++) { const struct module_struct *module = makefile->TTCN3PPModules + i; if (module->dir_name != NULL) { print_splitted_file_names(fp, makefile, module); } } } } } else { for (i = 0; i < makefile->nTTCN3Modules; i++) { const struct module_struct *module = makefile->TTCN3Modules + i; if (module->dir_name != NULL) { print_generated_file_name(fp, module, TRUE, ".cc"); if (makefile->code_splitting_mode) print_splitted_file_names(fp, makefile, module); } } if (makefile->preprocess) { for (i = 0; i < makefile->nTTCN3PPModules; i++) { const struct module_struct *module = makefile->TTCN3PPModules + i; if (module->dir_name != NULL) { print_generated_file_name(fp, module, TRUE, ".cc"); if (makefile->code_splitting_mode) print_splitted_file_names(fp, makefile, module); } } } } if (makefile->gnu_make && makefile->BaseASN1ModulesRegular) { fputs(" $(BASE_ASN1_MODULES:.asn=.cc)", fp); if (makefile->code_splitting_mode) { for (i = 0; i < makefile->nASN1Modules; i++) { const struct module_struct *module = makefile->ASN1Modules + i; if (module->dir_name != NULL) { print_splitted_file_names(fp, makefile, module); } } } } else { for (i = 0; i < makefile->nASN1Modules; i++) { const struct module_struct *module = makefile->ASN1Modules + i; if (module->dir_name != NULL) { print_generated_file_name(fp, module, TRUE, ".cc"); if (makefile->code_splitting_mode) print_splitted_file_names(fp, makefile, module); } } } fputs("\nBASE_GENERATED_HEADERS =", fp); if (makefile->gnu_make) { fputs(" $(BASE_GENERATED_SOURCES:.cc=.hh)", fp); } else { for (i = 0; i < makefile->nTTCN3Modules; i++) { const struct module_struct *module = makefile->TTCN3Modules + i; if (module->dir_name != NULL) print_generated_file_name(fp, module, TRUE, ".hh"); } if (makefile->preprocess) { for (i = 0; i < makefile->nTTCN3PPModules; i++) { const struct module_struct *module = makefile->TTCN3PPModules + i; if (module->dir_name != NULL) print_generated_file_name(fp, module, TRUE, ".hh"); } } for (i = 0; i < makefile->nASN1Modules; i++) { const struct module_struct *module = makefile->ASN1Modules + i; if (module->dir_name != NULL) print_generated_file_name(fp, module, TRUE, ".hh"); } } } if (makefile->linkingStrategy) { fputs("\n\n" "# C++ source & header files generated from the TTCN-3 " " library linked modules of\n" "# central project(s):\n" "BASE2_GENERATED_SOURCES =", fp); if (makefile->gnu_make && makefile->BaseTTCN3ModulesRegular) { fputs(" $(BASE2_TTCN3_MODULES:.ttcn=.cc)", fp); fputs(" $(BASE2_ASN1_MODULES:.asn=.cc)", fp); if (makefile->preprocess) fputs(" $(BASE2_TTCN3_PP_MODULES:.ttcnpp=.cc)", fp); } else { for (i = 0; i < makefile->nTTCN3Modules; i++) { const struct module_struct *module = makefile->TTCN3Modules + i; if (module->dir_name != NULL && isTtcn3ModuleInLibrary(module->module_name)) { print_generated_file_name(fp, module, TRUE, ".cc"); } } if (makefile->preprocess) { for (i = 0; i < makefile->nTTCN3PPModules; i++) { const struct module_struct *module = makefile->TTCN3PPModules + i; if (module->dir_name != NULL && isTtcnPPFileInLibrary(module->file_name)) { print_generated_file_name(fp, module, TRUE, ".cc"); } } } } fputs("\nBASE2_GENERATED_HEADERS =", fp); if (makefile->gnu_make) { fputs(" $(BASE2_GENERATED_SOURCES:.cc=.hh)", fp); } else ERROR("the usage of 'Z' flag requires GNU make"); } fputs("\n\n" "# C/C++ Source & header files of Test Ports, external functions " "and\n" "# other modules:\n" "USER_SOURCES =", fp); for (i = 0; i < makefile->nUserFiles; i++) { const struct user_struct *user = makefile->UserFiles + i; if (user->dir_name == NULL || !makefile->central_storage) print_source_name(fp, user); } fprint_extra_targets(fp, makefile->target_placement_list, "USER_SOURCES"); fputs("\nUSER_HEADERS =", fp); if (makefile->gnu_make && makefile->UserHeadersRegular) { fputs(" $(USER_SOURCES:.cc=.hh)", fp); } else { for (i = 0; i < makefile->nUserFiles; i++) { const struct user_struct *user = makefile->UserFiles + i; if (user->dir_name == NULL || !makefile->central_storage) print_header_name(fp, user); } } fprint_extra_targets(fp, makefile->target_placement_list, "USER_HEADERS"); if (makefile->central_storage) { fputs("\n\n" "# C/C++ Source & header files of Test Ports, external functions " "and\n" "# other modules used from central project(s):\n" "BASE_USER_SOURCES =", fp); if (!makefile->linkingStrategy) { for (i = 0; i < makefile->nUserFiles; i++) { const struct user_struct *user = makefile->UserFiles + i; if (user->dir_name != NULL) { print_source_name(fp, user); } } fputs("\nBASE_USER_HEADERS =", fp); if (makefile->gnu_make && makefile->BaseUserHeadersRegular) { fputs(" $(BASE_USER_SOURCES:.cc=.hh)", fp); } else { for (i = 0; i < makefile->nUserFiles; i++) { const struct user_struct *user = makefile->UserFiles + i; if (user->dir_name != NULL) print_header_name(fp, user); } } } else { for (i = 0; i < makefile->nUserFiles; i++) { const struct user_struct *user = makefile->UserFiles + i; if (user->dir_name != NULL && !isSourceFileInLibrary(user->source_name)) { print_source_name(fp, user); } } fputs("\nBASE_USER_HEADERS =", fp); if (makefile->gnu_make && makefile->BaseUserHeadersRegular) { fputs(" $(BASE_USER_SOURCES:.cc=.hh)", fp); } else { for (i = 0; i < makefile->nUserFiles; i++) { const struct user_struct *user = makefile->UserFiles + i; if (user->dir_name != NULL && !isHeaderFileInLibrary(user->header_name)) print_header_name(fp, user); } } fputs("\n\n" "# C/C++ Source & header files of Test Ports, external functions " "and\n" "# other modules used from library linked central project(s):\n" "BASE2_USER_SOURCES =", fp); for (i = 0; i < makefile->nUserFiles; i++) { const struct user_struct *user = makefile->UserFiles + i; if (user->dir_name != NULL && isSourceFileInLibrary(user->source_name)) { print_source_name(fp, user); } } fputs("\nBASE2_USER_HEADERS =", fp); if (makefile->gnu_make && makefile->BaseUserHeadersRegular) { fputs(" $(BASE2_USER_SOURCES:.cc=.hh)", fp); } else { for (i = 0; i < makefile->nUserFiles; i++) { const struct user_struct *user = makefile->UserFiles + i; if (user->dir_name != NULL && isHeaderFileInLibrary(user->header_name)) print_header_name(fp, user); } } } } if (makefile->dynamic) { fputs("\n\n" "# Shared object files of this project:\n" "SHARED_OBJECTS =", fp); if (makefile->gnu_make) { fputs(" $(GENERATED_SOURCES:.cc=.so)", fp); } else { for (i = 0; i < makefile->nTTCN3Modules; i++) { const struct module_struct *module = makefile->TTCN3Modules + i; if (module->dir_name == NULL || !makefile->central_storage) { print_generated_file_name(fp, module, FALSE, ".so"); if (makefile->code_splitting_mode != NULL) if (strcmp(makefile->code_splitting_mode, "-U type") == 0) { print_generated_file_name(fp, module, FALSE, "_seq.so"); print_generated_file_name(fp, module, FALSE, "_set.so"); print_generated_file_name(fp, module, FALSE, "_seqof.so"); print_generated_file_name(fp, module, FALSE, "_setof.so"); print_generated_file_name(fp, module, FALSE, "_union.so"); } } } if (makefile->preprocess) { for (i = 0; i < makefile->nTTCN3PPModules; i++) { const struct module_struct *module = makefile->TTCN3PPModules + i; if (module->dir_name == NULL || !makefile->central_storage) { print_generated_file_name(fp, module, FALSE, ".so"); if (makefile->code_splitting_mode != NULL) if (strcmp(makefile->code_splitting_mode, "-U type") == 0) { print_generated_file_name(fp, module, FALSE, "_seq.so"); print_generated_file_name(fp, module, FALSE, "_set.so"); print_generated_file_name(fp, module, FALSE, "_seqof.so"); print_generated_file_name(fp, module, FALSE, "_setof.so"); print_generated_file_name(fp, module, FALSE, "_union.so"); } } } } for (i = 0; i < makefile->nASN1Modules; i++) { const struct module_struct *module = makefile->ASN1Modules + i; if (module->dir_name == NULL || !makefile->central_storage) { print_generated_file_name(fp, module, FALSE, ".so"); if (makefile->code_splitting_mode != NULL) if (strcmp(makefile->code_splitting_mode, "-U type") == 0) { print_generated_file_name(fp, module, FALSE, "_seq.so"); print_generated_file_name(fp, module, FALSE, "_set.so"); print_generated_file_name(fp, module, FALSE, "_seqof.so"); print_generated_file_name(fp, module, FALSE, "_setof.so"); print_generated_file_name(fp, module, FALSE, "_union.so"); } } } } if (makefile->gnu_make && makefile->UserSourcesRegular) { fputs(" $(USER_SOURCES:.cc=.so)", fp); } else { for (i = 0; i < makefile->nUserFiles; i++) { const struct user_struct *user = makefile->UserFiles + i; if (user->dir_name == NULL || !makefile->central_storage) print_shared_object_name(fp, user); } } } fputs("\n\n" "# Object files of this project that are needed for the executable " "test suite:\n" "OBJECTS = $(GENERATED_OBJECTS) $(USER_OBJECTS)\n\n" /* never := */ "GENERATED_OBJECTS =", fp); if (makefile->gnu_make) { fputs(" $(GENERATED_SOURCES:.cc=.o)", fp); } else { for (i = 0; i < makefile->nTTCN3Modules; i++) { const struct module_struct *module = makefile->TTCN3Modules + i; if (module->dir_name == NULL || !makefile->central_storage) { print_generated_file_name(fp, module, FALSE, ".o"); if (makefile->code_splitting_mode != NULL) if (strcmp(makefile->code_splitting_mode, "-U type") == 0) { print_generated_file_name(fp, module, FALSE, "_seq.o"); print_generated_file_name(fp, module, FALSE, "_set.o"); print_generated_file_name(fp, module, FALSE, "_seqof.o"); print_generated_file_name(fp, module, FALSE, "_setof.o"); print_generated_file_name(fp, module, FALSE, "_union.o"); } } } if (makefile->preprocess) { for (i = 0; i < makefile->nTTCN3PPModules; i++) { const struct module_struct *module = makefile->TTCN3PPModules + i; if (module->dir_name == NULL || !makefile->central_storage) { print_generated_file_name(fp, module, FALSE, ".o"); if (makefile->code_splitting_mode != NULL) if (strcmp(makefile->code_splitting_mode, "-U type") == 0) { print_generated_file_name(fp, module, FALSE, "_seq.o"); print_generated_file_name(fp, module, FALSE, "_set.o"); print_generated_file_name(fp, module, FALSE, "_seqof.o"); print_generated_file_name(fp, module, FALSE, "_setof.o"); print_generated_file_name(fp, module, FALSE, "_union.o"); } } } } for (i = 0; i < makefile->nASN1Modules; i++) { const struct module_struct *module = makefile->ASN1Modules + i; if (module->dir_name == NULL || !makefile->central_storage) { print_generated_file_name(fp, module, FALSE, ".o"); if (makefile->code_splitting_mode != NULL) if (strcmp(makefile->code_splitting_mode, "-U type") == 0) { print_generated_file_name(fp, module, FALSE, "_seq.o"); print_generated_file_name(fp, module, FALSE, "_set.o"); print_generated_file_name(fp, module, FALSE, "_seqof.o"); print_generated_file_name(fp, module, FALSE, "_setof.o"); print_generated_file_name(fp, module, FALSE, "_union.o"); } } } } fputs("\n\nUSER_OBJECTS =", fp); if (makefile->gnu_make && makefile->UserSourcesRegular) { fputs(" $(USER_SOURCES:.cc=.o)", fp); } else { for (i = 0; i < makefile->nUserFiles; i++) { const struct user_struct *user = makefile->UserFiles + i; if (user->dir_name == NULL || !makefile->central_storage) print_object_name(fp, user); } } fprint_extra_targets(fp, makefile->target_placement_list, "USER_OBJECTS"); if (makefile->gcc_dep) { /* GNU Make processes included makefiles in reverse order. By putting * user sources first, their .d will be generated last, after the * GENERATED_SOURCES (and GENERATED_HEADERS) have been created. * This avoid spurious errors during incremental dependency generation */ fputs("\n\nDEPFILES = $(USER_OBJECTS:.o=.d) $(GENERATED_OBJECTS:.o=.d)", fp); } if (makefile->central_storage) { if (makefile->dynamic) { fputs("\n\n" "# Shared object files of central project(s):\n" "BASE_SHARED_OBJECTS =", fp); if (!makefile->linkingStrategy) { if (makefile->gnu_make) { fputs(" $(BASE_GENERATED_SOURCES:.cc=.so)", fp); } else { for (i = 0; i < makefile->nTTCN3Modules; i++) { const struct module_struct *module = makefile->TTCN3Modules + i; if (module->dir_name != NULL) print_generated_file_name(fp, module, TRUE, ".so"); } if (makefile->preprocess) { for (i = 0; i < makefile->nTTCN3PPModules; i++) { const struct module_struct *module = makefile->TTCN3PPModules + i; if (module->dir_name != NULL) print_generated_file_name(fp, module, TRUE, ".so"); } } for (i = 0; i < makefile->nASN1Modules; i++) { const struct module_struct *module = makefile->ASN1Modules + i; if (module->dir_name != NULL) print_generated_file_name(fp, module, TRUE, ".so"); } } if (makefile->gnu_make && makefile->BaseUserSourcesRegular) { fputs(" $(BASE_USER_SOURCES:.cc=.so)", fp); } else { for (i = 0; i < makefile->nUserFiles; i++) { const struct user_struct *user = makefile->UserFiles + i; if (user->dir_name != NULL) print_shared_object_name(fp, user); } } } else { // new linkingStrategy if (makefile->gnu_make) { fputs(" $(BASE_GENERATED_SOURCES:.cc=.so)", fp); } else ERROR("the usage of 'Z' flag requires GNU make"); if (makefile->gnu_make && makefile->BaseUserSourcesRegular) { fputs(" $(BASE_USER_SOURCES:.cc=.so)", fp); } else { for (i = 0; i < makefile->nUserFiles; i++) { const struct user_struct *user = makefile->UserFiles + i; if (user->dir_name != NULL && !isSourceFileInLibrary(user->source_name)) print_shared_object_name(fp, user); } } } } /* if dynamic */ fputs("\n\n" "# Object files of central project(s) that are needed for the " "executable test suite:\n" "BASE_OBJECTS =", fp); if (!makefile->linkingStrategy) { if (makefile->gnu_make) { fputs(" $(BASE_GENERATED_SOURCES:.cc=.o)", fp); } else { for (i = 0; i < makefile->nTTCN3Modules; i++) { const struct module_struct *module = makefile->TTCN3Modules + i; if (module->dir_name != NULL) print_generated_file_name(fp, module, TRUE, ".o"); } if (makefile->preprocess) { for (i = 0; i < makefile->nTTCN3PPModules; i++) { const struct module_struct *module = makefile->TTCN3PPModules + i; if (module->dir_name != NULL) print_generated_file_name(fp, module, TRUE, ".o"); } } for (i = 0; i < makefile->nASN1Modules; i++) { const struct module_struct *module = makefile->ASN1Modules + i; if (module->dir_name != NULL) print_generated_file_name(fp, module, TRUE, ".o"); } } if (makefile->gnu_make && makefile->BaseUserSourcesRegular) { fputs(" $(BASE_USER_SOURCES:.cc=.o)", fp); } else { for (i = 0; i < makefile->nUserFiles; i++) { const struct user_struct *user = makefile->UserFiles + i; if (user->dir_name != NULL) print_object_name(fp, user); } } } else { // new linkingStrategy if (makefile->gnu_make) { fputs(" $(BASE_GENERATED_SOURCES:.cc=.o)", fp); } else ERROR("the usage of 'Z' flag requires GNU make"); if (makefile->gnu_make && makefile->BaseUserSourcesRegular) { fputs(" $(BASE_USER_SOURCES:.cc=.o)", fp); } else { for (i = 0; i < makefile->nUserFiles; i++) { const struct user_struct *user = makefile->UserFiles + i; if (user->dir_name != NULL && !isSourceFileInLibrary(user->source_name)) print_object_name(fp, user); } } } } if (makefile->linkingStrategy) { fputs("\n\n" "# Object files of library linked central project(s) that are needed for the " "executable test suite:\n" "BASE2_OBJECTS =", fp); if (makefile->gnu_make) { if (makefile->dynamic) fputs(" $(BASE2_GENERATED_SOURCES:.cc=.so)", fp); else fputs(" $(BASE2_GENERATED_SOURCES:.cc=.o)", fp); } else ERROR("the usage of 'Z' flag requires GNU make"); if (makefile->gnu_make && makefile->BaseUserSourcesRegular) { if (makefile->dynamic) fputs(" $(BASE2_USER_SOURCES:.cc=.so)", fp); else fputs(" $(BASE2_USER_SOURCES:.cc=.o)", fp); } else { for (i = 0; i < makefile->nUserFiles; i++) { const struct user_struct *user = makefile->UserFiles + i; if (user->dir_name != NULL && isSourceFileInLibrary(user->source_name)) { if (makefile->dynamic) print_shared_object_name(fp, user); else print_object_name(fp, user); } } } if (makefile->hierarchical) { fputs("\n\n" "#Libraries of referenced project(s) that are needed for the " "executable or library target:\n" "BASE2_LIBRARY =", fp); struct string2_list* head = getLinkerLibs(makefile->project_name); struct string2_list* act_elem = head; while (act_elem) { if (act_elem->str2) { fputs(" ", fp); fprintf(fp, "%s/lib%s.%s", act_elem->str1, act_elem->str2, isDynamicLibrary(act_elem->str2) ? "so" : "a"); } act_elem = act_elem->next; } free_string2_list(head); } } fputs("\n\n" "# Other files of the project (Makefile, configuration files, etc.)\n" "# that will be added to the archived source files:\n" "OTHER_FILES =", fp); for (i = 0; i < makefile->nOtherFiles; i++) fprintf(fp, " %s", makefile->OtherFiles[i]); fprint_extra_targets(fp, makefile->target_placement_list, "OTHER_FILES"); if (makefile->ets_name) { const char *ets_suffix = NULL; /* EXECUTABLE variable */ fprintf(fp, "\n\n" "# The name of the executable test suite:\n" "EXECUTABLE = %s", makefile->ets_name); #ifdef WIN32 { /* add the .exe suffix unless it is already present */ ets_suffix = get_suffix(makefile->ets_name); if (ets_suffix == NULL || strcmp(ets_suffix, "exe")) fputs(".exe", fp); } #endif fputs("\n\n", fp); if (makefile->linkingStrategy) { #ifndef WIN32 fputs("DYNAMIC_LIBRARY = lib$(EXECUTABLE).so\n", fp); fputs("STATIC_LIBRARY = lib$(EXECUTABLE).a\n", fp); #else char* name_prefix = cut_suffix(makefile->ets_name); fprintf(fp, "DYNAMIC_LIBRARY = lib%s.so\n", name_prefix); fprintf(fp, "STATIC_LIBRARY = lib%s.a\n", name_prefix); Free(name_prefix); #endif } /* LIBRARY variable */ ets_suffix = get_suffix(makefile->ets_name); if (ets_suffix != NULL && !strcmp(ets_suffix, "exe")) { char* name_prefix = cut_suffix(makefile->ets_name); fprintf(fp, "\n\nLIBRARY = %s%s%s\n", "lib", name_prefix ? name_prefix : "library", makefile->dynamic ? ".so" : ".a"); Free(name_prefix); } else { #ifndef WIN32 fprintf(fp, "\n\nLIBRARY = lib$(EXECUTABLE)%s\n", makefile->dynamic ? ".so" : ".a"); #else fprintf(fp, "\n\nLIBRARY = lib%s%s\n", makefile->ets_name, makefile->dynamic ? ".so" : ".a"); #endif } } else { fputs("\n\n" "# The name of the executable test suite:\n" "EXECUTABLE =\n" "LIBRARY =\n", fp); } if (!makefile->linkingStrategy || !buildObjects(makefile->project_name, add_refd_prjs)) { fprintf(fp, "\n" "TARGET = $(%s)", makefile->library ? "LIBRARY" : "EXECUTABLE"); } else { if (makefile->dynamic) { fputs("\n" "TARGET = $(SHARED_OBJECTS)", fp); } else { fputs("\n" "TARGET = $(OBJECTS)", fp); } } fputs("\n\n" "#\n" "# Do not modify these unless you know what you are doing...\n" "# Platform specific additional libraries:\n" "#\n", fp); fputs("SOLARIS_LIBS = -lsocket -lnsl -lxml2", fp); #ifdef USAGE_STATS fputs(" -lresolv", fp); #endif #ifdef ADVANCED_DEBUGGER_UI fputs(" -lcurses", fp); #endif if (makefile->solspeclibraries) { struct string_list* act_elem = makefile->solspeclibraries; while (act_elem) { if (act_elem->str) { fprintf(fp, " -l%s", act_elem->str); } act_elem = act_elem->next; } } fputs("\n", fp); fputs("SOLARIS8_LIBS = -lsocket -lnsl -lxml2", fp); #ifdef USAGE_STATS fputs(" -lresolv", fp); #endif #ifdef ADVANCED_DEBUGGER_UI fputs(" -lcurses", fp); #endif if (makefile->sol8speclibraries) { struct string_list* act_elem = makefile->sol8speclibraries; while (act_elem) { if (act_elem->str) { fprintf(fp, " -l%s", act_elem->str); } act_elem = act_elem->next; } } fputs("\n", fp); fputs("LINUX_LIBS = -lxml2", fp); #ifdef USAGE_STATS fputs(" -lpthread -lrt", fp); #endif #ifdef ADVANCED_DEBUGGER_UI fputs(" -lncurses", fp); #endif if (makefile->linuxspeclibraries) { struct string_list* act_elem = makefile->linuxspeclibraries; while (act_elem) { if (act_elem->str) { fprintf(fp, " -l%s", act_elem->str); } act_elem = act_elem->next; } } fputs("\n", fp); fputs("FREEBSD_LIBS = -lxml2", fp); #ifdef ADVANCED_DEBUGGER_UI fputs(" -lncurses", fp); #endif if (makefile->freebsdspeclibraries) { struct string_list* act_elem = makefile->freebsdspeclibraries; while (act_elem) { if (act_elem->str) { fprintf(fp, " -l%s", act_elem->str); } act_elem = act_elem->next; } } fputs("\n", fp); fputs("WIN32_LIBS = -lxml2", fp); #ifdef ADVANCED_DEBUGGER_UI fputs(" -lncurses", fp); #endif if (makefile->win32speclibraries) { struct string_list* act_elem = makefile->win32speclibraries; while (act_elem) { if (act_elem->str) { fprintf(fp, " -l%s", act_elem->str); } act_elem = act_elem->next; } } fputs("\n\n", fp); fputs("#\n" "# Rules for building the executable...\n" "#\n\n", fp); fprintf(fp, "all:%s $(TARGET) ;\n\n", add_refd_prjs?" referenced-all":""); if (makefile->dynamic) { fprintf(fp, "shared_objects:%s $(SHARED_OBJECTS) ;\n\n", add_refd_prjs?" referenced-shared_objects":""); } fprintf(fp, "executable:%s $(EXECUTABLE) ;\n\n" "library:%s $(LIBRARY) ;\n\n" "objects:%s $(OBJECTS) compile;\n\n", add_refd_prjs?" referenced-executable":"", add_refd_prjs?" referenced-library":"", add_refd_prjs?" referenced-objects":""); /* target $(EXECUTABLE) */ if (makefile->dynamic && makefile->library) { /* There is no need to create the .so for all the source files */ fputs("$(EXECUTABLE): $(LIBRARY)\n" "\tif $(CXX) $(LDFLAGS) -o $@ $(LIBRARY)", fp); } else { fprintf(fp, "$(EXECUTABLE): %s", makefile->dynamic ? "$(SHARED_OBJECTS)" : "$(OBJECTS)"); if (!makefile->linkingStrategy) { // use the old linking method if (makefile->central_storage) { if (makefile->dynamic) { fputs(" $(BASE_SHARED_OBJECTS)", fp); } else { fputs(" $(BASE_OBJECTS)", fp); } } } else { if (!makefile->library) { if (makefile->dynamic) { fputs(" $(BASE_SHARED_OBJECTS)", fp); } else { fputs(" $(BASE_OBJECTS)", fp); } if (makefile->hierarchical) { fputs(" $(BASE2_LIBRARY)", fp); } } } fprintf(fp, "\n" "\tif $(CXX) $(LDFLAGS) -o $@ %s", #if defined (SOLARIS) || defined (SOLARIS8) ""); #else makefile->dynamic ? "-Wl,--no-as-needed " : ""); /* start writing the link step */ #endif if (makefile->gnu_make) fputs("$^", fp); else { if (makefile->dynamic) { fputs("$(SHARED_OBJECTS)", fp); if (makefile->central_storage) fputs(" $(BASE_SHARED_OBJECTS)", fp); } else { fputs("$(OBJECTS)", fp); if (makefile->central_storage) fputs(" $(BASE_OBJECTS)", fp); } } } if (makefile->additionalObjects) { struct string_list* act_elem = makefile->additionalObjects; while (act_elem) { if (act_elem->str) { fprintf(fp, " %s", act_elem->str); } act_elem = act_elem->next; } } fprintf(fp, " \\\n" "\t-L$(TTCN3_DIR)/lib -l$(TTCN3_LIB)" " \\\n" "\t-L$(OPENSSL_DIR)/lib -lcrypto"); if (!makefile->linkingStrategy) { if (makefile->linkerlibraries) { struct string_list* act_elem = makefile->linkerlibraries; while (act_elem) { if (act_elem->str) { fprintf(fp, " -l%s", act_elem->str); } act_elem = act_elem->next; } } if (makefile->linkerlibsearchpath) { struct string_list* act_elem = makefile->linkerlibsearchpath; while (act_elem) { if (act_elem->str) { fprintf(fp, " -L%s", act_elem->str); } act_elem = act_elem->next; } } fprintf(fp, " \\\n" "\t-L$(XMLDIR)/lib $($(PLATFORM)_LIBS); \\\n" "\tthen : ; else $(TTCN3_DIR)/bin/titanver $(OBJECTS); exit 1; fi\n"); } else { // new linking strategy fputs (" \\\n", fp); if (makefile->linkerlibraries && !makefile->library) { struct string2_list* head = getLinkerLibs(makefile->project_name); struct string2_list* act_elem = head; while (act_elem) { if (act_elem->str1 && act_elem->str2) { fprintf(fp, "\t-L%s -Wl,-rpath=%s -l%s \\\n", act_elem->str1, act_elem->str1, act_elem->str2); } act_elem = act_elem->next; } free_string2_list(head); struct string_list* act_head = getExternalLibPaths(makefile->project_name); struct string_list* act_ext_elem = act_head; while (act_ext_elem) { if (act_ext_elem->str) { fprintf(fp, "\t-L%s \\\n", act_ext_elem->str); } act_ext_elem = act_ext_elem->next; } free_string_list(act_head); act_head = getExternalLibs(makefile->project_name); act_ext_elem = act_head; while (act_ext_elem) { if (act_ext_elem->str) { fprintf(fp, "\t-l%s \\\n", act_ext_elem->str); } act_ext_elem = act_ext_elem->next; } free_string_list(act_head); } fprintf(fp, "\t-L$(XMLDIR)/lib $($(PLATFORM)_LIBS); \\\n" "\tthen : ; else $(TTCN3_DIR)/bin/titanver $(OBJECTS); exit 1; fi\n"); } /* If the compiler will not be run because there are no TTCN(PP) or ASN.1 * files, create the "compile" marker file which is checked by the * superior makefile if using this project as central storage */ if (!run_compiler) fputs("\ttouch compile\n", fp); /* End of target $(EXECUTABLE) */ /* target $(LIBRARY) */ if (makefile->dynamic) { fprintf(fp, "\n" "$(LIBRARY): $(OBJECTS)%s\n" "\t$(CXX) -shared -o $@ $(OBJECTS)", makefile->hierarchical ? " $(BASE2_LIBRARY)" : ""); if (makefile->central_storage && !makefile->linkingStrategy) { fputs(" $(BASE_SHARED_OBJECTS) ;\n" "\tln -s $@ $(subst lib, ,$@) > /dev/null 2>&1 ;", fp); } if (makefile->linkingStrategy) { struct string2_list* head = getLinkerLibs(makefile->project_name); struct string2_list* act_elem = head; // If the project is Executable on Top Level the linker can link the *.a and *.so together while (act_elem && !isTopLevelExecutable(makefile->project_name)) { if (act_elem->str1 && act_elem->str2 && isDynamicLibrary(act_elem->str2)) { fputs(" \\\n", fp); fprintf(fp, "\t-L%s -Wl,-rpath=%s -l%s", act_elem->str1, act_elem->str1, act_elem->str2); } else { const char* mainLibName = getLibFromProject(makefile->project_name); ERROR("Library archive 'lib%s.a' cannot be linked to dynamic library 'lib%s.so' " "in project '%s' ", act_elem->str2, mainLibName ? mainLibName : "", makefile->project_name); free_string2_list(head); exit(EXIT_FAILURE); } act_elem = act_elem->next; } free_string2_list(head); struct string_list* act_head = getExternalLibPaths(makefile->project_name); struct string_list* act_ext_elem = act_head; while (act_ext_elem) { if (act_ext_elem->str) { fputs(" \\\n", fp); fprintf(fp, "\t-L%s", act_ext_elem->str); } act_ext_elem = act_ext_elem->next; } free_string_list(act_head); act_head = getExternalLibs(makefile->project_name); act_ext_elem = act_head; while (act_ext_elem) { if (act_ext_elem->str) { fputs(" \\\n", fp); fprintf(fp, "\t-l%s", act_ext_elem->str); } act_ext_elem = act_ext_elem->next; } free_string_list(act_head); } } else { // static linking fprintf(fp, "\n" "$(LIBRARY): $(OBJECTS)%s\n" "\t$(AR) -r%s $(ARFLAGS) $(LIBRARY) $(OBJECTS)", makefile->hierarchical ? " $(BASE2_LIBRARY)" : "", makefile->linkingStrategy ? "cT" : ""); if (makefile->central_storage && !makefile->linkingStrategy) { fputs(" $(BASE_OBJECTS)", fp); } if (makefile->linkingStrategy) { if ( makefile->library) { struct string2_list* head = getLinkerLibs(makefile->project_name); struct string2_list* act_elem = head; while (act_elem) { if (act_elem->str2 && !isDynamicLibrary(act_elem->str2)) { fputs(" \\\n", fp); fprintf(fp, "\t%s/lib%s.a", act_elem->str1, act_elem->str2); } else { const char* mainLibName = getLibFromProject(makefile->project_name); if (act_elem->str2) { ERROR("Dynamic library 'lib%s.so' cannot be linked to static library 'lib%s.a' " "in project '%s' ", act_elem->str2, mainLibName ? mainLibName : "", makefile->project_name); exit(EXIT_FAILURE); } else { struct string_list* ext_libs = getExternalLibs(makefile->project_name); if (ext_libs && ext_libs->str) { ERROR("Third party dynamic library '%s' cannot be linked to static library 'lib%s.a' " "in project '%s' ", ext_libs->str, mainLibName ? mainLibName : "", makefile->project_name); free_string_list(ext_libs); exit(EXIT_FAILURE); } free_string_list(ext_libs); } } act_elem = act_elem->next; } free_string2_list(head); struct string_list* act_head = getExternalLibs(makefile->project_name); struct string_list* act_ext_elem = act_head; while (act_ext_elem) { if (act_ext_elem->str && hasExternalLibrary(act_ext_elem->str, makefile->project_name)) { fputs(" \\\n", fp); fprintf(fp, "\tlib%s.a", act_ext_elem->str); ERROR("linking static 3d party or system library 'lib%s.a' to " "project library 'lib%s.a' is not supported ", act_ext_elem->str, makefile->ets_name); exit(EXIT_FAILURE); } act_ext_elem = act_ext_elem->next; } free_string_list(act_head); } } } fputs("\n\n.cc.o .c.o:\n" "\t$(CXX) -c $(CPPFLAGS) $(CXXFLAGS) -o $@ $<\n\n", fp); if (makefile->gcc_dep) { fputs(".cc.d .c.d:\n" "\t@echo Creating dependency file for '$<'; set -e; \\\n" "\t$(CXX) $(CXXDEPFLAGS) $(CPPFLAGS) $(CXXFLAGS) $< \\\n" "\t| sed 's/\\($*\\)\\.o[ :]*/\\1.o $@ : /g' > $@; \\\n" "\t[ -s $@ ] || rm -f $@\n\n", fp); /* "set -e" causes bash to exit the script if any statement * returns nonzero (failure). * The sed line transforms the first line of the dependency from * "x.o: x.cc" to "x.o x.d: x.cc", making the dependency file depend * on the source and headers. * [ -s x.d ] checks that the generated dependency is not empty; * otherwise it gets deleted. */ } if (makefile->dynamic) { fputs("%.so: %.o\n" "\t$(CXX) -shared -o $@ $<\n\n", fp); } if (makefile->preprocess) { fputs("%.ttcn: %.ttcnpp $(TTCN3_INCLUDES)\n" "\t$(CPP) -x c -nostdinc $(CPPFLAGS_TTCN3) $< $@\n\n" "preprocess: $(PREPROCESSED_TTCN3_MODULES) ;\n\n", fp); } boolean merge_profiled_file_lists = makefile->profiled_file_list && makefile->profiled_file_list->next && !makefile->central_storage; if (makefile->central_storage) { boolean is_first = TRUE; fprintf(fp, "$(GENERATED_SOURCES) $(GENERATED_HEADERS):%s compile-all compile ", makefile->hierarchical ? " update" : ""); if (add_refd_prjs) fputs("referenced-dep", fp); /* These extra compile dependencies for the generated .cc are here to * check if all the referenced projects are up to date. * If the referenced projects are built too then they are not needed * (and cause problems as the included .d depends on the .cc). */ if (!add_refd_prjs) for (i = 0; i < makefile->nBaseDirs; i++) { const struct base_dir_struct *base_dir = makefile->BaseDirs + i; if (base_dir->has_modules) { if (is_first) { fputs(" \\\n", fp); is_first = FALSE; } else putc(' ', fp); fprintf(fp, "%s/compile", base_dir->dir_name); } } if (makefile->preprocess) { fprintf(fp, "\n" "\t@if [ ! -f $@ ]; then %s compile-all; $(MAKE) compile-all; fi\n" "\n" "check:%s $(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n" "\t$(PREPROCESSED_TTCN3_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) " "%s\\\n" "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\n" "\t$(TTCN3_DIR)/bin/compiler -s $(COMPILER_FLAGS) ", rm_command, add_refd_prjs?" referenced-check":"", makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"", makefile->linkingStrategy ? "$(BASE2_PREPROCESSED_TTCN3_MODULES) ":"", makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) ":""); if (makefile->gnu_make) { if (add_refd_prjs) // referenced-check cannot be compiled it is not a ttcn modul fprintf(fp, "$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n" "\t$(PREPROCESSED_TTCN3_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) " "%s\\\n" "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\n", makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"", makefile->linkingStrategy ? "$(BASE2_PREPROCESSED_TTCN3_MODULES) ":"", makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) ":""); else fputs("$^", fp); } else { fputs("\\\n" "\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) \\\n" "\t$(PREPROCESSED_TTCN3_MODULES) " "$(BASE_PREPROCESSED_TTCN3_MODULES) \\\n" "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES)", fp); } fprintf(fp, "\n\n" "port: $(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n" "\t$(PREPROCESSED_TTCN3_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) " "%s\n" "\t$(TTCN3_DIR)/bin/compiler -t $(COMPILER_FLAGS) ", makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"", makefile->linkingStrategy ? "$(BASE2_PREPROCESSED_TTCN3_MODULES) ":""); if (makefile->gnu_make) { if (add_refd_prjs) // referenced-check cannot be compiled it is not a ttcn modul fprintf(fp, "$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n" "\t$(PREPROCESSED_TTCN3_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) " "%s\n", makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"", makefile->linkingStrategy ? "$(BASE2_PREPROCESSED_TTCN3_MODULES) ":""); else fputs("$^", fp); } else { fputs("\\\n" "\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) \\\n" "\t$(PREPROCESSED_TTCN3_MODULES) " "$(BASE_PREPROCESSED_TTCN3_MODULES) \n", fp); } if (makefile->linkingStrategy && makefile->hierarchical) { fputs("\n\n" "update: $(BASE_TTCN3_MODULES) $(BASE_ASN1_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) \\\n" "\t$(BASE2_TTCN3_MODULES) $(BASE2_ASN1_MODULES) $(BASE2_PREPROCESSED_TTCN3_MODULES)\n" "ifneq ($(wildcard $(GENERATED_SOURCES)), ) \n" "ifeq ($(wildcard $?), ) \n" "\ttouch compile-all; \n" "\ttouch update; \n" "endif\n" "endif",fp); } if (makefile->profiled_file_list) { fputs("\n\n" "compile:: $(PROFILED_FILE_LIST)\n" "\ttouch $(TTCN3_MODULES) $(PREPROCESSED_TTCN3_MODULES) " "$(ASN1_MODULES)", fp); } fprintf(fp, "\n\n" "compile:%s $(TTCN3_MODULES) $(PREPROCESSED_TTCN3_MODULES) " "$(ASN1_MODULES)\n" "\t@echo \"compiling \"'$(patsubst %%.tpd, %%, $(TPD))';\n" "\t$(TTCN3_DIR)/bin/compiler $(COMPILER_FLAGS) \\\n" "\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n" "\t$(PREPROCESSED_TTCN3_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) %s\\\n" "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s - $?\n" "\ttouch $@\n\n", makefile->profiled_file_list ? ":" : "", makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"", makefile->linkingStrategy ? "$(BASE2_PREPROCESSED_TTCN3_MODULES) ":"", makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES)":""); fprintf (fp, "compile-all: $(BASE_TTCN3_MODULES) $(BASE_ASN1_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) " "%s" "\t$(MAKE) preprocess\n" "\t@echo \"compiling all \"'$(patsubst %%.tpd, %%, $(TPD))';\n" "\t$(TTCN3_DIR)/bin/compiler $(COMPILER_FLAGS) \\\n" "\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n" "\t$(PREPROCESSED_TTCN3_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) %s" "\\\n" "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\\\n" "\t- $(TTCN3_MODULES) $(PREPROCESSED_TTCN3_MODULES) $(ASN1_MODULES)\n" "\ttouch $@ compile\n\n", makefile->linkingStrategy ? "\\\n\t$(BASE2_TTCN3_MODULES) $(BASE2_ASN1_MODULES) " "$(BASE2_PREPROCESSED_TTCN3_MODULES) \n":"\n", makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"", makefile->linkingStrategy ? "$(BASE2_PREPROCESSED_TTCN3_MODULES) ":"", makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) ":""); } else { fprintf(fp, "\n" "\t@if [ ! -f $@ ]; then %s compile-all; $(MAKE) compile-all; fi\n", rm_command); fprintf(fp, "\n" "check:%s $(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n" "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\n" "\t$(TTCN3_DIR)/bin/compiler -s $(COMPILER_FLAGS) ", add_refd_prjs?" referenced-check":"", makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"", makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) ":""); if (makefile->gnu_make) { if (add_refd_prjs) // referenced-check cannot be compiled it is not a ttcn modul fprintf(fp, "$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n" "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\n", makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":"", makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) ":""); else fputs("$^", fp); } else { fputs("\\\n" "\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) \\\n" "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES)", fp); } fprintf(fp, "\n\n" "port: $(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\n" "\t$(TTCN3_DIR)/bin/compiler -t $(COMPILER_FLAGS) ", makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":""); if (makefile->gnu_make) { if (add_refd_prjs) // referenced-check cannot be compiled it is not a ttcn modul fprintf(fp, "$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\n", makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) ":""); else fputs("$^", fp); } else { fputs("\\\n" "\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) \n", fp); } if (makefile->linkingStrategy && makefile->hierarchical) { fputs("\n\n" "update: $(BASE_TTCN3_MODULES) $(BASE_ASN1_MODULES) $(BASE_PREPROCESSED_TTCN3_MODULES) \\\n" "\t$(BASE2_TTCN3_MODULES) $(BASE2_ASN1_MODULES) $(BASE2_PREPROCESSED_TTCN3_MODULES)\n" "ifneq ($(wildcard $(GENERATED_SOURCES)), ) \n" "ifeq ($(wildcard $?), ) \n" "\ttouch compile-all; \n" "\ttouch update; \n" "endif\n" "endif",fp); } if (makefile->profiled_file_list) { fputs("\n\n" "compile:: $(PROFILED_FILE_LIST)\n" "\ttouch $(TTCN3_MODULES) $(ASN1_MODULES)", fp); } fprintf(fp, "\n\n" "compile:%s $(TTCN3_MODULES) $(ASN1_MODULES)\n" "\t@echo \"compiling \"'$(patsubst %%.tpd, %%, $(TPD))';\n" "\t$(TTCN3_DIR)/bin/compiler $(COMPILER_FLAGS) \\\n" "\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n" "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\\\n" "\t- $?\n" "\ttouch $@\n\n", makefile->profiled_file_list ? ":" : "", makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) " : "", makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) " : ""); fprintf(fp, "compile-all: $(BASE_TTCN3_MODULES) $(BASE_ASN1_MODULES) %s\n", makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) $(BASE2_ASN1_MODULES)" : ""); fputs("\t@echo \"compiling all \"'$(patsubst %.tpd, %, $(TPD))';\n", fp); fprintf(fp,"\t$(TTCN3_DIR)/bin/compiler $(COMPILER_FLAGS) \\\n" "\t$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n" "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\\\n" "\t- $(TTCN3_MODULES) $(ASN1_MODULES)\n" "\ttouch $@ compile\n\n", makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) " : "", makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) " : ""); } if (!makefile->hierarchical) for (i = 0; i < makefile->nBaseDirs; i++) { const struct base_dir_struct *base_dir = makefile->BaseDirs + i; if (base_dir->has_modules) { size_t j; fprintf(fp, "%s/compile:", base_dir->dir_name); for (j = 0; j < makefile->nTTCN3Modules; j++) { const struct module_struct *module = makefile->TTCN3Modules + j; if (module->dir_name != NULL && !strcmp(base_dir->dir_name, module->dir_name)) print_file_name(fp, module); } for (j = 0; j < makefile->nTTCN3PPModules; j++) { const struct module_struct *module = makefile->TTCN3PPModules + j; if (module->dir_name != NULL && !strcmp(base_dir->dir_name, module->dir_name)) print_file_name(fp, module); } for (j = 0; j < makefile->nASN1Modules; j++) { const struct module_struct *module = makefile->ASN1Modules + j; if (module->dir_name != NULL && !strcmp(base_dir->dir_name, module->dir_name)) print_file_name(fp, module); } fprintf(fp, "\n" "\t@echo 'Central directory %s is not up-to-date!'\n" "\t@exit 2\n\n", base_dir->dir_name); } } } else { /* not central storage */ fprintf(fp, "$(GENERATED_SOURCES) $(GENERATED_HEADERS): compile\n" "\t@if [ ! -f $@ ]; then %s compile; $(MAKE) compile; fi\n\n" "%s" "check:%s $(TTCN3_MODULES) ", rm_command, merge_profiled_file_lists ? "check:: $(PROFILED_FILE_LIST)\n\n" : "", merge_profiled_file_lists ? ":" : ""); if (makefile->preprocess) fputs("$(PREPROCESSED_TTCN3_MODULES) ", fp); fputs("$(ASN1_MODULES)\n" "\t$(TTCN3_DIR)/bin/compiler -s $(COMPILER_FLAGS) ", fp); if (makefile->gnu_make) fputs("$^", fp); else { fputs("\\\n" "\t$(TTCN3_MODULES) $(PREPROCESSED_TTCN3_MODULES) $(ASN1_MODULES)", fp); } fputs("\n\n", fp); fprintf(fp, "port: $(TTCN3_MODULES) "); if (makefile->preprocess) fputs("$(PREPROCESSED_TTCN3_MODULES) ", fp); fputs("\n", fp); fputs("\t$(TTCN3_DIR)/bin/compiler -t $(COMPILER_FLAGS) ", fp); if (makefile->gnu_make) fputs("$^", fp); else { fputs("\\\n" "\t$(TTCN3_MODULES) $(PREPROCESSED_TTCN3_MODULES)", fp); } if (makefile->profiled_file_list) { fputs("\n\ncompile:: $(PROFILED_FILE_LIST)\n" "\ttouch $(TTCN3_MODULES) ", fp); if (makefile->preprocess) fputs("$(PREPROCESSED_TTCN3_MODULES) ", fp); fputs("$(ASN1_MODULES)", fp); } fprintf(fp, "\n\n" "compile:%s $(TTCN3_MODULES) ", makefile->profiled_file_list ? ":" : ""); if (makefile->preprocess) fputs("$(PREPROCESSED_TTCN3_MODULES) ", fp); fputs("$(ASN1_MODULES)\n" "\t$(TTCN3_DIR)/bin/compiler $(COMPILER_FLAGS) ", fp); if (makefile->gnu_make) fputs("$^", fp); else { fputs("\\\n" "\t$(TTCN3_MODULES) ", fp); if (makefile->preprocess) fputs("$(PREPROCESSED_TTCN3_MODULES) ", fp); fputs("$(ASN1_MODULES)", fp); } fputs(" - $?\n" "\ttouch $@\n" "\n", fp); if (merge_profiled_file_lists) { fputs("$(PROFILED_FILE_LIST): $(PROFILED_FILE_LIST_SEGMENTS)\n" "\tcat $(PROFILED_FILE_LIST_SEGMENTS) > $(PROFILED_FILE_LIST)\n\n", fp); } } // clean: if (makefile->linkingStrategy) { fprintf(fp, "clean:%s\n", (add_refd_prjs && !makefile->hierarchical) ? " referenced-clean" : ""); if (makefile->dynamic && (makefile->central_storage || makefile->linkingStrategy)) { fprintf(fp,"\tfind . -type l -name \"*.so\" -exec unlink {} \\;\n"); } fprintf(fp, "\t%s $(EXECUTABLE) $(DYNAMIC_LIBRARY) $(STATIC_LIBRARY) " "$(OBJECTS) $(GENERATED_HEADERS) \\\n" "\t$(GENERATED_SOURCES) ", rm_command); if (makefile->dynamic) fputs("$(SHARED_OBJECTS) ", fp); if (makefile->preprocess) fputs("$(PREPROCESSED_TTCN3_MODULES) ", fp); fputs("compile", fp); if (makefile->central_storage) fputs(" compile-all", fp); if (makefile->gcc_dep) fputs(" $(DEPFILES)", fp); if (merge_profiled_file_lists) { fputs(" $(PROFILED_FILE_LIST)", fp); } fprintf(fp, " \\\n" "\ttags *.log%s%s\n\n", add_refd_prjs?" referenced*":"", makefile->hierarchical ? " update":""); } else { fprintf(fp, "clean:%s\n" "\t-%s $(EXECUTABLE) $(LIBRARY) $(OBJECTS) $(GENERATED_HEADERS) \\\n" "\t$(GENERATED_SOURCES) ", add_refd_prjs?" referenced-clean":"", rm_command); if (makefile->dynamic) fputs("$(SHARED_OBJECTS) ", fp); if (makefile->preprocess) fputs("$(PREPROCESSED_TTCN3_MODULES) ", fp); fputs("compile", fp); if (makefile->central_storage) fputs(" compile-all", fp); if (makefile->gcc_dep) fputs(" $(DEPFILES)", fp); if (merge_profiled_file_lists) { fputs(" $(PROFILED_FILE_LIST)", fp); } fprintf(fp, " \\\n" "\ttags *.log%s", add_refd_prjs?" referenced*":""); } // clean-all: if (makefile->linkingStrategy && makefile->hierarchical) fprintf(fp, "clean-all: %s clean\n", add_refd_prjs ? "referenced-clean-all":""); // dep: fputs("\n\ndep: $(GENERATED_SOURCES) $(USER_SOURCES)",fp); if (add_refd_prjs) { fprintf(fp, "\n\t%s referenced-dep", rm_command); } else fputs(" ;",fp); if (makefile->gcc_dep) { fprintf(fp, " \n\n" "ifeq ($(findstring n,$(MAKEFLAGS)),)\n" "ifeq ($(filter clean%s check port compile archive diag%s,$(MAKECMDGOALS)),)\n" "-include $(DEPFILES)\n" "endif\n" "endif", (makefile->linkingStrategy && makefile->hierarchical) ? " clean-all" : "", (makefile->preprocess ? " preprocess" : "")); /* Don't include .d files when cleaning etc.; make will try to build them * and this involves running the Titan compiler. Same for preprocess. * The check target would be pointless if running the compiler * without generating code was always preceded by running the compiler * _and_ generating C++ code. */ } else { /* old-style dep with makedepend. Do not check compiler version. */ fputs("\n\tmakedepend $(CPPFLAGS) -DMAKEDEPEND_RUN ", fp); if (makefile->gnu_make) fputs("$^", fp); else fputs("$(GENERATED_SOURCES) $(USER_SOURCES)", fp); } if (makefile->linkingStrategy) { fputs("\n\n" "archive:\n" "\t@perl $(TTCN3_DIR)/bin/ttcn3_archive\n\n", fp); } else { fputs("\n\n" "archive:\n" "\tmkdir -p $(ARCHIVE_DIR)\n" "\ttar -cvhf - ", fp); if (makefile->central_storage) { fprintf(fp, "$(TTCN3_MODULES) $(BASE_TTCN3_MODULES) %s\\\n", makefile->linkingStrategy ? "$(BASE2_TTCN3_MODULES) " : ""); if (makefile->preprocess) { fprintf(fp, "\t$(TTCN3_PP_MODULES) $(BASE_TTCN3_PP_MODULES) " "%s $(TTCN3_INCLUDES) \\\n", makefile->linkingStrategy ? "$(BASE2_TTCN3_PP_MODULES)" : ""); } fprintf(fp, "\t$(ASN1_MODULES) $(BASE_ASN1_MODULES) %s\\\n" "\t$(USER_HEADERS) $(BASE_USER_HEADERS) %s\\\n" "\t$(USER_SOURCES) $(BASE_USER_SOURCES) %s", makefile->linkingStrategy ? "$(BASE2_ASN1_MODULES) " : "", makefile->linkingStrategy ? "$(BASE2_USER_HEADERS) " : "", makefile->linkingStrategy ? "$(BASE2_USER_SOURCES)" : ""); } else { fputs("$(TTCN3_MODULES) ", fp); if (makefile->preprocess) { fputs("$(TTCN3_PP_MODULES) \\\n" "\t$(TTCN3_INCLUDES) ", fp); } fputs("$(ASN1_MODULES) \\\n" "\t$(USER_HEADERS) $(USER_SOURCES)", fp); } fputs(" $(OTHER_FILES) \\\n" "\t| gzip >$(ARCHIVE_DIR)/`basename $(TARGET) .exe`-" "`date '+%y%m%d-%H%M'`.tgz\n\n", fp); } fprintf(fp, "diag:\n" "\t$(TTCN3_DIR)/bin/compiler -v 2>&1\n" "\t$(TTCN3_DIR)/bin/mctr_cli -v 2>&1\n" "\t$(CXX) -v 2>&1\n" "%s" "\t@echo TTCN3_DIR=$(TTCN3_DIR)\n" "\t@echo OPENSSL_DIR=$(OPENSSL_DIR)\n" "\t@echo XMLDIR=$(XMLDIR)\n" "\t@echo PLATFORM=$(PLATFORM)\n\n", makefile->dynamic ? "" : "\t$(AR) -V 2>&1\n"); if (add_refd_prjs) { fprintf(fp, "referenced-all referenced-shared_objects referenced-executable referenced-library \\\n" "referenced-objects referenced-check \\\n" "referenced-clean%s:\n" "\t@for dir in $(REFERENCED_PROJECT_DIRS); do \\\n" "\t $(MAKE) -C $$dir $(subst referenced-,,$@) || exit; \\\n" "\tdone; \n\n", (makefile->linkingStrategy && makefile->hierarchical) ? "-all" : ""); fputs("referenced-dep:\n" "\t@for dir in $(REFERENCED_PROJECT_DIRS); do \\\n" "\t $(MAKE) -C $$dir $(subst referenced-,,$@) || exit; \\\n" "\tdone; \n" "\ttouch $@\n\n", fp); } if (makefile->generatorCommandOutput) { fputs("### Project specific rules generated by user written script:\n\n", fp); fputs(makefile->generatorCommandOutput, fp); fputs("\n### End of project specific rules.\n\n", fp); } fputs("#\n" "# Add your rules here if necessary...\n" "#\n\n", fp); fclose(fp); if (strcmp(makefile->output_file, "Makefile")) { NOTIFY("Makefile skeleton was written to `%s'.", makefile->output_file); } else { NOTIFY("Makefile skeleton was generated."); } } else { ERROR("Output file `%s' already exists. Use switch `%s' to force " "overwrite.", makefile->output_file, makefile->linkingStrategy ? "-F" : "-f"); } } #undef COMMENT_PREFIX #define COMMENT_PREFIX /** run makefilegen commans for sub-projects */ static void run_makefilegen_commands(struct string2_list* run_command_list) { struct string2_list* act_elem = run_command_list; while (act_elem) { struct string2_list* next_elem = act_elem->next; /* run commands if there were no ERRORs */ if ((error_count == 0) && act_elem->str1 && act_elem->str2) { int rv; char* sub_proj_effective_work_dir = act_elem->str1; char* command = act_elem->str2; char* orig_dir = get_working_dir(); rv = set_working_dir(sub_proj_effective_work_dir); if (rv) ERROR("Could not set working dir to `%s'", sub_proj_effective_work_dir); else { fprintf(stderr, "Executing `%s' in working directory `%s'...\n", command, sub_proj_effective_work_dir); rv = system(command); 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 } rv = set_working_dir(orig_dir); if (rv) ERROR("Could not restore working dir to `%s'", orig_dir); Free(orig_dir); } Free(act_elem->str1); Free(act_elem->str2); Free(act_elem); act_elem = next_elem; } } /** create symlinks and delete list */ static void generate_symlinks(struct string2_list* create_symlink_list) { struct string2_list* act_elem = create_symlink_list; while (act_elem) { struct string2_list* next_elem = act_elem->next; /* create symlinks if there were no ERRORs */ if ((error_count == 0) && act_elem->str1 && act_elem->str2) { int fail = symlink(act_elem->str1, act_elem->str2); if (fail) perror(act_elem->str2); /* complain but do not call ERROR() */ } Free(act_elem->str1); Free(act_elem->str2); Free(act_elem); act_elem = next_elem; } } /** Performs all tasks of Makefile generation based on the given list of * modules/files (taken from the command line) and options that represent * command line switches. */ static void generate_makefile(size_t n_arguments, char *arguments[], size_t n_other_files, const char *other_files[], const char *output_file, const char *ets_name, char *project_name, boolean gnu_make, boolean single_mode, boolean central_storage, boolean absolute_paths, boolean preprocess, boolean dump_makefile_data, boolean force_overwrite, boolean use_runtime_2, boolean dynamic, boolean makedepend, boolean coverage, const char *code_splitting_mode, const char *tcov_file_name, struct string_list* profiled_file_list, boolean Lflag, boolean Zflag, boolean Hflag, struct string_list* sub_project_dirs, struct string_list* ttcn3_prep_includes, struct string_list* ttcn3_prep_defines, struct string_list* ttcn3_prep_undefines, struct string_list* prep_includes, struct string_list* prep_defines, struct string_list* prep_undefines, boolean codesplittpd, boolean quietly, boolean disablesubtypecheck, const char* cxxcompiler, const char* optlevel, const char* optflags, boolean disableber, boolean disableraw, boolean disabletext, boolean disablexer, boolean disablejson, boolean forcexerinasn, boolean defaultasomit, boolean gccmsgformat, boolean linenumbersonlymsg, boolean includesourceinfo, boolean addsourcelineinfo, boolean suppresswarnings, boolean outparamboundness, boolean omit_in_value_list, boolean warnings_for_bad_variants, boolean activate_debugger, boolean disable_predef_ext_folder, struct string_list* solspeclibraries, struct string_list* sol8speclibraries, struct string_list* linuxspeclibraries, struct string_list* freebsdspeclibraries, struct string_list* win32speclibraries, const char* ttcn3preprocessor, struct string_list* linkerlibraries, struct string_list* additionalObjects, struct string_list* linkerlibsearchpath, char* generatorCommandOutput, struct string2_list* target_placement_list) { size_t i; struct makefile_struct makefile; init_makefile_struct(&makefile); makefile.project_name = project_name; makefile.central_storage = central_storage; makefile.gnu_make = gnu_make; makefile.preprocess = preprocess; makefile.single_mode = single_mode; makefile.force_overwrite = force_overwrite; makefile.use_runtime_2 = use_runtime_2; makefile.dynamic = dynamic; makefile.gcc_dep = gnu_make && !makedepend; makefile.coverage = coverage; makefile.library = Lflag; makefile.linkingStrategy = Zflag; makefile.hierarchical = Hflag; makefile.sub_project_dirs = sub_project_dirs; makefile.ttcn3_prep_includes = ttcn3_prep_includes; makefile.ttcn3_prep_defines = ttcn3_prep_defines; makefile.ttcn3_prep_undefines = ttcn3_prep_undefines; makefile.prep_includes = prep_includes; makefile.prep_defines = prep_defines; makefile.prep_undefines = prep_undefines; makefile.codesplittpd = codesplittpd; makefile.quietly = quietly; makefile.disablesubtypecheck = disablesubtypecheck; makefile.cxxcompiler = cxxcompiler; makefile.optlevel = optlevel; makefile.optflags = optflags; makefile.disableber = disableber; makefile.disableraw = disableraw; makefile.disabletext = disabletext; makefile.disablexer = disablexer; makefile.disablejson = disablejson; makefile.forcexerinasn = forcexerinasn; makefile.defaultasomit = defaultasomit; makefile.gccmsgformat = gccmsgformat; makefile.linenumbersonlymsg = linenumbersonlymsg; makefile.includesourceinfo = includesourceinfo; makefile.addsourcelineinfo = addsourcelineinfo; makefile.suppresswarnings = suppresswarnings; makefile.outparamboundness = outparamboundness; makefile.omit_in_value_list = omit_in_value_list; makefile.warnings_for_bad_variants = warnings_for_bad_variants; makefile.activate_debugger = activate_debugger; makefile.disable_predef_ext_folder = disable_predef_ext_folder; makefile.solspeclibraries = solspeclibraries; makefile.sol8speclibraries = sol8speclibraries; makefile.linuxspeclibraries = linuxspeclibraries; makefile.freebsdspeclibraries = freebsdspeclibraries; makefile.win32speclibraries = win32speclibraries; makefile.ttcn3preprocessor = ttcn3preprocessor; makefile.linkerlibraries = linkerlibraries; makefile.additionalObjects = additionalObjects; makefile.linkerlibsearchpath = linkerlibsearchpath; makefile.generatorCommandOutput = generatorCommandOutput; makefile.target_placement_list = target_placement_list; for (i = 0; i < n_arguments; i++) { char *file_name = get_file_name_for_argument(arguments[i]); if (file_name != NULL) { FILE *fp = fopen(file_name, "r"); if (fp != NULL) { char *module_name; if (is_ttcn3_module(file_name, fp, &module_name)) { if (is_asn1_module(file_name, fp, NULL)) { ERROR("File `%s' looks so strange that it can be both ASN.1 and " "TTCN-3 module. Add it to the Makefile manually.", file_name); Free(module_name); } else { add_ttcn3_module(&makefile, file_name, module_name); } } else if (is_asn1_module(file_name, fp, &module_name)) { if (is_valid_asn1_filename(file_name)) { add_asn1_module(&makefile, file_name, module_name); } else { ERROR("The file name (without suffix) shall be identical to the module name.\n" "If the name of the ASN.1 module contains a hyphen, the corresponding " "file name shall contain an underscore character instead."); } } else { add_user_file(&makefile, file_name); } fclose(fp); } else { ERROR("Cannot open file `%s' for reading: %s", file_name, strerror(errno)); errno = 0; } Free(file_name); } else if (get_path_status(arguments[i]) == PS_DIRECTORY) { ERROR("Argument `%s' is a directory.", arguments[i]); } else { ERROR("Cannot find any source file for argument `%s'.", arguments[i]); } } for (i = 0; i < n_other_files; i++) { char *file_name = get_file_name_for_argument(other_files[i]); if (file_name != NULL) { add_path_to_list(&makefile.nOtherFiles, &makefile.OtherFiles, file_name, makefile.working_dir, TRUE); Free(file_name); } else if (get_path_status(other_files[i]) == PS_DIRECTORY) { ERROR("Argument `%s' given as other file is a directory.", other_files[i]); } else { ERROR("Cannot find any other file for argument `%s'.", other_files[i]); } } if (ets_name != NULL) { char *dir_name = get_dir_name(ets_name, makefile.working_dir); char *file_name = get_file_from_path(ets_name); makefile.ets_name = compose_path_name(dir_name, file_name); Free(dir_name); Free(file_name); } if (code_splitting_mode != NULL) { makefile.code_splitting_mode = mputprintf(makefile.code_splitting_mode, "-U %s", code_splitting_mode); } if (tcov_file_name != NULL) { makefile.tcov_file_name = mprintf(" -K %s", tcov_file_name); } if (profiled_file_list != NULL) { makefile.profiled_file_list = profiled_file_list; } if (makefile.nTTCN3Modules >= 1) { if (makefile.ets_name == NULL) makefile.ets_name = mcopystr(makefile.TTCN3Modules[0].module_name); } else if (preprocess && (makefile.nTTCN3PPModules >= 1)) { if (makefile.ets_name == NULL) makefile.ets_name = mcopystr(makefile.TTCN3PPModules[0].module_name); } else if (makefile.nASN1Modules >= 1) { WARNING("No TTCN-3 module was given for the Makefile."); if (makefile.ets_name == NULL) makefile.ets_name = mcopystr(makefile.ASN1Modules[0].module_name); } else if (makefile.nUserFiles > 0) { WARNING("No TTCN-3 or ASN.1 module was given for the Makefile."); if (makefile.ets_name == NULL) makefile.ets_name = mcopystr(makefile.UserFiles[0].file_prefix); } else { WARNING("No source files were given for the Makefile"); } if (output_file != NULL) { if (get_path_status(output_file) == PS_DIRECTORY) makefile.output_file = mprintf("%s/Makefile", output_file); else makefile.output_file = mcopystr(output_file); } else makefile.output_file = mcopystr("Makefile"); add_path_to_list(&makefile.nOtherFiles, &makefile.OtherFiles, makefile.output_file, makefile.working_dir, FALSE); if (preprocess) check_preprocessed_filename_collision(&makefile); filter_out_generated_files(&makefile); complete_user_files(&makefile); if (!absolute_paths) convert_dirs_to_relative(&makefile); check_special_chars(&makefile); if (central_storage) collect_base_dirs(&makefile); check_naming_convention(&makefile); if (dump_makefile_data) dump_makefile_struct(&makefile, 0); if (error_count == 0) print_makefile(&makefile); free_makefile_struct(&makefile); } #ifdef COVERAGE_BUILD #define C_flag "C" #else #define C_flag #endif static void usage(void) { fprintf(stderr, "\n" "usage: %s [-abc" C_flag "dDEfFglLmMnprRstTVwWXZ] [-K file] [-z file ] [-P dir]" " [-U none|type] [-e ets_name] [-o dir|file]\n" " [-t project_descriptor.tpd [-b buildconfig]]\n" " [-O file] ... module_name ... testport_name ...\n" " or %s -v\n" "\n" "OPTIONS:\n" " -a: use absolute pathnames in the generated Makefile\n" " -c: use the pre-compiled files from central directories\n" #ifdef COVERAGE_BUILD " -C: enable coverage of generated C++ code\n" #endif " -d: dump the data used for Makefile generation\n" " -e ets_name: name of the target executable\n" " -E: display only warnings for unrecognized encoding variants\n" " -f: force overwriting of the output Makefile\n" " -g: generate Makefile for use with GNU make\n" " -I path: Add path to the search paths when using TPD files\n" " -K file: enable selective code coverage\n" " -l: use dynamic linking\n" " -L: create makefile with library archive as the default target\n" " -m: always use makedepend for dependencies\n" " -M: allow 'omit' in template value lists (legacy behavior)\n" " -n: activate debugger (generates extra code for debugging)\n" " -o dir|file: write the Makefile to the given directory or file\n" " -O file: add the given file to the Makefile as other file\n" " -p: generate Makefile with TTCN-3 preprocessing\n" " -R: use function test runtime (TITAN_RUNTIME_2)\n" " -s: generate Makefile for single mode\n" " -U none|type: split generated code\n" " -v: show version\n" " -w: suppress warnings\n" " -Y: Enforces legacy behaviour of the \"out\" function parameters (see refguide)\n" " -z file: enable profiling and code coverage for the TTCN-3 files in the argument\n" "Options for processing the Titan Project Descriptor file(s):\n" " -t tpd: read project descriptor file\n" " -b buildconfig: use the specified build config instead of the default\n" " -D: use current directory as working directory\n" " -V: disable validation of TPD file with schema\n" " -r: generate Makefile hierarchy for TPD hierarchy (recursive)\n" " -F: force overwriting of all generated Makefiles, use with -r\n" " -T: generate only top-level Makefile of the hierarchy, use with -r\n" " -P dir: prints out a file list found in a given TPD relative to the given directory\n" " -X: generate XML file that describes the TPD hierarchy, use with -r\n" " -W: prefix working directories with project name\n" " -Z: recursive Makefile generation from TPD using object files and dynamic libraries too\n" " -H: hierachical Makefile generation from TPD use with -Z\n" , program_name, program_name); } #define SET_FLAG(x) if (x##flag) {\ ERROR("Flag -" #x " was specified more than once.");\ error_flag = TRUE;\ } else x##flag = TRUE void free_string_list(struct string_list* act_elem) { while (act_elem) { struct string_list* next_elem = act_elem->next; Free(act_elem->str); Free(act_elem); act_elem = next_elem; } } void free_string2_list(struct string2_list* act_elem) { while (act_elem) { struct string2_list* next_elem = act_elem->next; Free(act_elem->str1); Free(act_elem->str2); Free(act_elem); act_elem = next_elem; } } int main(int argc, char *argv[]) { boolean aflag = FALSE, bflag = FALSE, cflag = FALSE, Cflag = FALSE, dflag = FALSE, eflag = FALSE, fflag = FALSE, gflag = FALSE, oflag = FALSE, Kflag = FALSE, lflag = FALSE, pflag = FALSE, Pflag = FALSE, Rflag = FALSE, sflag = FALSE, tflag = FALSE, wflag = FALSE, vflag = FALSE, mflag = FALSE, Uflag = FALSE, Lflag = FALSE, rflag = FALSE, Fflag = FALSE, Xflag = FALSE, Tflag = FALSE, Yflag = FALSE, csflag = FALSE, quflag = FALSE, dsflag = FALSE, dbflag = FALSE, drflag = FALSE, dtflag = FALSE, dxflag = FALSE, fxflag = FALSE, doflag = FALSE, gfflag = FALSE, lnflag = FALSE, isflag = FALSE, asflag = FALSE, swflag = FALSE, Vflag = FALSE, Dflag = FALSE, Wflag = FALSE, djflag = FALSE, Zflag = FALSE, Hflag = FALSE, Mflag = FALSE, diflag = FALSE, zflag = FALSE, Eflag = FALSE, nflag = FALSE; boolean error_flag = FALSE; char *output_file = NULL; char *ets_name = NULL; char *project_name = NULL; size_t n_other_files = 0; const char **other_files = NULL; const char *code_splitting_mode = NULL; const char *tpd_file_name = NULL; const char *tpd_build_config = NULL; const char *tcov_file_name = NULL; size_t n_search_paths = 0; const char **search_paths = NULL; struct string_list* profiled_file_list = NULL; const char *profiled_file_list_zflag = NULL; const char *file_list_path = NULL; enum tpd_result tpd_processed = FALSE; struct string_list* sub_project_dirs = NULL; struct string2_list* create_symlink_list = NULL; struct string_list* ttcn3_prep_includes = NULL; struct string_list* ttcn3_prep_defines = NULL; struct string_list* ttcn3_prep_undefines = NULL; struct string_list* prep_includes = NULL; struct string_list* prep_defines = NULL; struct string_list* prep_undefines = NULL; char *cxxcompiler = NULL; char *optlevel = NULL; char *optflags = NULL; struct string_list* solspeclibraries = NULL; struct string_list* sol8speclibraries = NULL; struct string_list* linuxspeclibraries = NULL; struct string_list* freebsdspeclibraries = NULL; struct string_list* win32speclibraries = NULL; char *ttcn3prep = NULL; struct string_list* linkerlibraries = NULL; struct string_list* additionalObjects = NULL; struct string_list* linkerlibsearchpath = NULL; char* generatorCommandOutput = NULL; struct string2_list* target_placement_list = NULL; struct string2_list* run_command_list = NULL; struct string2_list* required_configs = NULL; #ifdef LICENSE license_struct lstr; int valid_license; #endif program_name = argv[0]; if (argc == 1) { fputs("Makefile Generator for the TTCN-3 Test Executor, version " PRODUCT_NUMBER "\n", stderr); usage(); return EXIT_FAILURE; } for ( ; ; ) { int c = getopt(argc, argv, "O:ab:c" C_flag "dDe:EfFgI:K:o:lLmMnpP:rRst:TU:vVwWXYz:ZH"); if (c == -1) break; switch (c) { case 'O': n_other_files++; other_files = (const char**) Realloc(other_files, n_other_files * sizeof(*other_files)); other_files[n_other_files - 1] = optarg; break; case 'I': n_search_paths++; search_paths = (const char**) Realloc(search_paths, n_search_paths * sizeof(*search_paths)); search_paths[n_search_paths - 1] = optarg; break; case 'a': SET_FLAG(a); break; case 'b': SET_FLAG(b); tpd_build_config = optarg; break; case 'c': SET_FLAG(c); break; case 'K': SET_FLAG(K); tcov_file_name = optarg; break; #ifdef COVERAGE_BUILD case 'C': SET_FLAG(C); break; #endif case 'd': SET_FLAG(d); break; case 'D': SET_FLAG(D); break; case 'e': SET_FLAG(e); ets_name = optarg; break; case 'E': SET_FLAG(E); break; case 'f': SET_FLAG(f); break; case 'F': SET_FLAG(F); break; case 'g': SET_FLAG(g); break; case 'H': SET_FLAG(H); break; case 'o': SET_FLAG(o); output_file = optarg; break; case 'l': SET_FLAG(l); break; case 'L': SET_FLAG(L); break; case 'm': SET_FLAG(m); break; case 'M': SET_FLAG(M); break; case 'n': SET_FLAG(n); break; case 'p': SET_FLAG(p); break; case 'P': SET_FLAG(P); /* Optional arguments with `::' are GNU specific... */ if (get_path_status(optarg) == PS_DIRECTORY) { file_list_path = optarg; } else { ERROR("The -P flag requires a valid directory as its argument " "instead of `%s'", optarg); error_flag = TRUE; } break; case 'r': SET_FLAG(r); break; case 'R': SET_FLAG(R); break; case 's': SET_FLAG(s); break; case 't': SET_FLAG(t); tpd_file_name = optarg; break; case 'T': SET_FLAG(T); break; case 'Y': SET_FLAG(Y); break; case 'U': SET_FLAG(U); code_splitting_mode = optarg; if (strcmp(optarg, "none") != 0 && strcmp(optarg, "type") != 0) ERROR("Unrecognizable argument: '%s'. Valid options for -U switch are: " "'none', 'type'", optarg); break; case 'v': SET_FLAG(v); break; case 'V': SET_FLAG(V); break; case 'w': SET_FLAG(w); suppress_warnings = TRUE; break; case 'W': SET_FLAG(W); break; case 'X': SET_FLAG(X); break; case 'z': SET_FLAG(z); profiled_file_list_zflag = optarg; break; case 'Z': SET_FLAG(Z); break; default: error_flag = TRUE; break; } } /* Checking incompatible options */ if (vflag) { /* -v prints the version and exits, it's pointless to specify other flags */ if ( aflag || bflag || cflag || Cflag || dflag || eflag || fflag || Fflag || gflag || mflag || oflag || lflag || pflag || Pflag || rflag || Rflag || sflag || tflag || Tflag || Vflag || wflag || Xflag || Kflag || Dflag || Wflag || Yflag || Zflag || Hflag || Mflag || zflag || Eflag || nflag || n_other_files > 0 || n_search_paths > 0) error_flag = TRUE; } if (Zflag) { if (!gflag) gflag = TRUE; // GNU make if (!cflag) cflag = TRUE; // central sorage } if ((bflag || Dflag || Pflag || Vflag || rflag || Wflag || Zflag) && !tflag) { ERROR("Using the '-b', '-D', '-P', '-V', '-r' 'Z' or '-W' option requires the use of the -t' option."); error_flag = TRUE; } if (rflag && !cflag) { ERROR("Using the '-r' option requires use of the '-c' option. Recursive makefile hierarchy uses the central directory feature."); error_flag = TRUE; } if (Fflag && !rflag) { ERROR("Using the '-F' option requires use of the '-r' option."); error_flag = TRUE; } if (Xflag && !rflag) { ERROR("Using the '-X' option requires use of the '-r' option."); error_flag = TRUE; } if (Tflag && !rflag) { ERROR("Using the '-T' option requires use of the '-r' option."); error_flag = TRUE; } if (!Zflag && Hflag) { ERROR("Using the '-H' option requires use of the '-Z' option."); error_flag = TRUE; } if (Zflag && !Fflag && !fflag) { ERROR("Using the '-Z' option requires use of the '-F' option."); error_flag = TRUE; } if (lflag && !strncmp(get_platform_string(), "WIN32", 5)) { ERROR("Generating Makefile with dynamic linking enabled is not supported " "on Windows platform"); error_flag = TRUE; } if (n_search_paths > 0 && !tflag) { ERROR("Using the '-I' option requires use of the '-t' option."); error_flag = TRUE; } for (size_t i = 0; i < n_search_paths; i++) { boolean is_abs_path = #if defined WIN32 && defined MINGW /* On native Windows the absolute path name shall begin with * a drive letter, colon and backslash */ (((search_paths[i][0] < 'A' || search_paths[i][0] > 'Z') && (search_paths[i][0] < 'a' || search_paths[i][0] > 'z')) || search_paths[i][1] != ':' || search_paths[i][2] != '\\'); #else /* On UNIX-like systems the absolute path name shall begin with * a slash */ search_paths[i][0] != '/'; #endif if (is_abs_path) { ERROR("The path after the -I flag must be an absolute path."); error_flag = TRUE; } } if (error_flag) { usage(); return EXIT_FAILURE; } if (vflag) { fputs("Makefile Generator for the TTCN-3 Test Executor\n" "Product number: " PRODUCT_NUMBER "\n" "Build date: " __DATE__ " " __TIME__ "\n" "Compiled with: " C_COMPILER_VERSION "\n\n" COPYRIGHT_STRING "\n\n", stderr); #ifdef LICENSE print_license_info(); #endif return EXIT_SUCCESS; } #ifdef LICENSE init_openssl(); load_license(&lstr); valid_license = verify_license(&lstr); free_openssl(); if (!valid_license) { free_license(&lstr); exit(EXIT_FAILURE); } if (!check_feature(&lstr, FEATURE_TPGEN)) { ERROR("The license key does not allow the generation of " "Makefile skeletons."); return EXIT_FAILURE; } free_license(&lstr); #endif if (tflag) { char* abs_work_dir = NULL; FILE* prj_graph_fp = NULL; sub_project_dirs = (struct string_list*)Malloc(sizeof(struct string_list)); sub_project_dirs->str = NULL; sub_project_dirs->next = NULL; ttcn3_prep_includes = (struct string_list*)Malloc(sizeof(struct string_list)); ttcn3_prep_includes->str = NULL; ttcn3_prep_includes->next = NULL; ttcn3_prep_defines = (struct string_list*)Malloc(sizeof(struct string_list)); ttcn3_prep_defines->str = NULL; ttcn3_prep_defines->next = NULL; ttcn3_prep_undefines = (struct string_list*)Malloc(sizeof(struct string_list)); ttcn3_prep_undefines->str = NULL; ttcn3_prep_undefines->next = NULL; prep_includes = (struct string_list*)Malloc(sizeof(struct string_list)); prep_includes->str = NULL; prep_includes->next = NULL; prep_defines = (struct string_list*)Malloc(sizeof(struct string_list)); prep_defines->str = NULL; prep_defines->next = NULL; prep_undefines = (struct string_list*)Malloc(sizeof(struct string_list)); prep_undefines->str = NULL; prep_undefines->next = NULL; solspeclibraries = (struct string_list*)Malloc(sizeof(struct string_list)); solspeclibraries->str = NULL; solspeclibraries->next = NULL; sol8speclibraries = (struct string_list*)Malloc(sizeof(struct string_list)); sol8speclibraries->str = NULL; sol8speclibraries->next = NULL; linuxspeclibraries = (struct string_list*)Malloc(sizeof(struct string_list)); linuxspeclibraries->str = NULL; linuxspeclibraries->next = NULL; freebsdspeclibraries = (struct string_list*)Malloc(sizeof(struct string_list)); freebsdspeclibraries->str = NULL; freebsdspeclibraries->next = NULL; win32speclibraries = (struct string_list*)Malloc(sizeof(struct string_list)); win32speclibraries->str = NULL; win32speclibraries->next = NULL; linkerlibraries = (struct string_list*)Malloc(sizeof(struct string_list)); linkerlibraries->str = NULL; linkerlibraries->next = NULL; additionalObjects = (struct string_list*)Malloc(sizeof(struct string_list)); additionalObjects->str = NULL; additionalObjects->next = NULL; linkerlibsearchpath = (struct string_list*)Malloc(sizeof(struct string_list)); linkerlibsearchpath->str = NULL; linkerlibsearchpath->next = NULL; if (Xflag) { const char* prj_graph_filename = "project_hierarchy_graph.xml"; prj_graph_fp = fopen(prj_graph_filename, "w"); if (prj_graph_fp==NULL) WARNING("Cannot open output file `%s' for writing: %s", prj_graph_filename, strerror(errno)); if (prj_graph_fp) fprintf(prj_graph_fp, "<project_hierarchy_graph top_level_tpd=\"%s\">\n", tpd_file_name); } create_symlink_list = (struct string2_list*)Malloc(sizeof(struct string2_list)); create_symlink_list->str1 = NULL; create_symlink_list->str2 = NULL; create_symlink_list->next = NULL; target_placement_list = (struct string2_list*)Malloc(sizeof(struct string2_list)); target_placement_list->str1 = NULL; target_placement_list->str2 = NULL; target_placement_list->next = NULL; run_command_list = (struct string2_list*)Malloc(sizeof(struct string2_list)); run_command_list->str1 = NULL; run_command_list->str2 = NULL; run_command_list->next = NULL; required_configs = (struct string2_list*)Malloc(sizeof(struct string2_list)); required_configs->str1 = NULL; required_configs->str2 = NULL; required_configs->next = NULL; tpd_processed = process_tpd(tpd_file_name, tpd_build_config, file_list_path, &argc, &argv, &optind, &ets_name, &project_name, &gflag, &sflag, &cflag, &aflag, &pflag, &Rflag, &lflag, &mflag, &Pflag, &Lflag, rflag, Fflag, Tflag, output_file, &abs_work_dir, sub_project_dirs, program_name, prj_graph_fp, create_symlink_list,ttcn3_prep_includes, ttcn3_prep_defines,ttcn3_prep_undefines, prep_includes, prep_defines, prep_undefines, &csflag, &quflag, &dsflag, &cxxcompiler, &optlevel, &optflags, &dbflag, &drflag, &dtflag, &dxflag, &djflag, &fxflag, &doflag, &gfflag, &lnflag, &isflag, &asflag, &swflag, &Yflag, &Mflag, &Eflag, &nflag, &diflag, solspeclibraries, sol8speclibraries, linuxspeclibraries, freebsdspeclibraries, win32speclibraries, &ttcn3prep, linkerlibraries, additionalObjects, linkerlibsearchpath, Vflag, Dflag, &Zflag, &Hflag, &generatorCommandOutput, target_placement_list, Wflag, run_command_list, required_configs, &profiled_file_list, search_paths, n_search_paths); Free(abs_work_dir); if (prj_graph_fp) { fprintf(prj_graph_fp, "</project_hierarchy_graph>\n"); fclose(prj_graph_fp); } if (tpd_processed == TPD_FAILED) { ERROR("Failed to process %s", tpd_file_name); exit(EXIT_FAILURE); } if (zflag) { WARNING("Compiler option '-z' and its argument will be overwritten by " "the settings in the TPD"); } } else if (zflag) { // use the argument given in the command line if there is no TPD profiled_file_list = (struct string_list*)Malloc(sizeof(struct string_list)); profiled_file_list->str = mcopystr(profiled_file_list_zflag); profiled_file_list->next = NULL; } if (!Pflag) { run_makefilegen_commands(run_command_list); generate_symlinks(create_symlink_list); if (Zflag) { if (Fflag) NOTIFY("Makefile generation from top-level TPD: %s", tpd_file_name); if (!Fflag && fflag) NOTIFY("Makefile generation from lower level TPD: %s", tpd_file_name); } generate_makefile(argc - optind, argv + optind, n_other_files, other_files, output_file, ets_name, project_name, gflag, sflag, cflag, aflag, pflag, dflag, fflag||Fflag, Rflag, lflag, mflag, Cflag, code_splitting_mode, tcov_file_name, profiled_file_list, Lflag, Zflag, Hflag, rflag ? sub_project_dirs : NULL, ttcn3_prep_includes, ttcn3_prep_defines, ttcn3_prep_undefines, prep_includes, prep_defines, prep_undefines, csflag, quflag, dsflag, cxxcompiler, optlevel, optflags, dbflag, drflag, dtflag, dxflag, djflag, fxflag, doflag, gfflag, lnflag, isflag, asflag, swflag, Yflag, Mflag, Eflag, nflag, diflag, solspeclibraries, sol8speclibraries, linuxspeclibraries, freebsdspeclibraries, win32speclibraries, ttcn3prep, linkerlibraries, additionalObjects, linkerlibsearchpath, generatorCommandOutput, target_placement_list); } free_string_list(sub_project_dirs); free_string_list(ttcn3_prep_includes); free_string_list(ttcn3_prep_defines); free_string_list(ttcn3_prep_undefines); free_string_list(prep_includes); free_string_list(prep_defines); free_string_list(prep_undefines); free_string_list(solspeclibraries); free_string_list(sol8speclibraries); free_string_list(linuxspeclibraries); free_string_list(freebsdspeclibraries); free_string_list(win32speclibraries); free_string_list(linkerlibraries); free_string_list(additionalObjects); free_string_list(linkerlibsearchpath); free_string_list(profiled_file_list); Free(search_paths); Free(generatorCommandOutput); free_string2_list(target_placement_list); free_string2_list(required_configs); Free(other_files); if (tpd_processed == TPD_SUCCESS) { int E; if (!(eflag && ets_name)) Free(ets_name); if (cxxcompiler) Free(cxxcompiler); if (optlevel) Free(optlevel); if (optflags) Free(optflags); if (ttcn3prep) Free(ttcn3prep); /* Free(output_file); */ for (E = 0; E < argc; ++E) Free(argv[E]); Free(argv); } /* check_mem_leak(program_name); not needed when linked to new.cc */ return error_count > 0 ? EXIT_FAILURE : EXIT_SUCCESS; }