1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2015 Ericsson Telecom AB
3 // All rights reserved. This program and the accompanying materials
4 // are made available under the terms of the Eclipse Public License v1.0
5 // which accompanies this distribution, and is available at
6 // http://www.eclipse.org/legal/epl-v10.html
7 ///////////////////////////////////////////////////////////////////////////////
16 #include <sys/types.h>
20 #include <libxml/parser.h>
21 #include <libxml/tree.h>
22 #include <libxml/xpath.h>
24 #define LIBXML_SCHEMAS_ENABLED
25 #include <libxml/xmlschemastypes.h>
27 #include "../common/memory.h"
29 // Do _NOT_ #include "string.hh", it drags in ustring.o, common/Quadruple.o,
30 // Int.o, ttcn3/PatternString.o, and then the entire AST :(
32 #include "ProjectGenHelper.hh"
33 #include "../common/path.h"
34 #include "ttcn3/ttcn3_preparser.h"
35 #include "asn1/asn1_preparser.h"
38 void ERROR (const char *fmt
, ...);
39 void WARNING(const char *fmt
, ...);
40 void NOTIFY (const char *fmt
, ...);
41 void DEBUG (const char *fmt
, ...);
44 void fatal_error(const char * filename
, int lineno
, const char * fmt
, ...)
45 __attribute__ ((__format__ (__printf__
, 3, 4), __noreturn__
));
47 void fatal_error(const char * filename
, int lineno
, const char * fmt
, ...)
49 fputs(filename
, stderr
);
50 fprintf(stderr
, ":%d: ", lineno
);
53 vfprintf(stderr
, fmt
, va
);
58 ProjectGenHelper
& projGenHelper
= ProjectGenHelper::Instance();
60 /// Run an XPath query and return an xmlXPathObjectPtr, which must be freed
61 xmlXPathObjectPtr
run_xpath(xmlXPathContextPtr xpathCtx
, const char *xpathExpr
)
63 xmlXPathObjectPtr xpathObj
= xmlXPathEvalExpression(
64 (const xmlChar
*)xpathExpr
, xpathCtx
);
65 if(xpathObj
== NULL
) {
66 fprintf(stderr
,"Error: unable to evaluate xpath expression \"%s\"\n", xpathExpr
);
77 explicit XmlDoc(xmlDocPtr p
) : doc_(p
) {}
79 if (doc_
!= NULL
) xmlFreeDoc(doc_
);
81 operator xmlDocPtr() const { return doc_
; }
88 explicit XPathContext(xmlXPathContextPtr c
) : ctx_(c
) {}
90 if (ctx_
!= NULL
) xmlXPathFreeContext(ctx_
);
92 operator xmlXPathContextPtr() const { return ctx_
; }
94 xmlXPathContextPtr ctx_
;
99 explicit XPathObject(xmlXPathObjectPtr o
) : xpo_(o
) {}
101 if (xpo_
!= NULL
) xmlXPathFreeObject(xpo_
);
103 operator xmlXPathObjectPtr() const { return xpo_
; }
104 xmlXPathObjectPtr
operator->() const { return xpo_
; }
106 xmlXPathObjectPtr xpo_
;
109 //------------------------------------------------------------------
110 /// compare-by-content wrapper of a plain C string
112 explicit cstring(const char *s
) : str(s
) {}
113 void destroy() const;
114 operator const char*() const { return str
; }
117 friend boolean
operator<(const cstring
& l
, const cstring
& r
);
118 friend boolean
operator==(const cstring
& l
, const cstring
& r
);
121 void cstring::destroy() const {
122 Free(const_cast<char*>(str
)); // assumes valid pointer or NULL
125 boolean
operator<(const cstring
& l
, const cstring
& r
) {
126 return strcmp(l
.str
, r
.str
) < 0;
129 boolean
operator==(const cstring
& l
, const cstring
& r
) {
130 return strcmp(l
.str
, r
.str
) == 0;
133 /// RAII for C string
134 struct autostring
: public cstring
{
135 /// Constructor; takes over ownership
136 explicit autostring(const char *s
= 0) : cstring(s
) {}
138 // He who can destroy a thing, controls that thing -- Paul Muad'Dib
139 Free(const_cast<char*>(str
)); // assumes valid pointer or NULL
141 /// %Assignment; takes over ownership
142 const autostring
& operator=(const char *s
) {
143 Free(const_cast<char*>(str
)); // assumes valid pointer or NULL
147 /// Relinquish ownership
148 const char *extract() {
149 const char *retval
= str
;
154 autostring(const autostring
&);
155 autostring
& operator=(const autostring
&);
159 bool validate_tpd(const XmlDoc
& xml_doc
, const char* tpd_file_name
, const char* xsd_file_name
)
161 xmlLineNumbersDefault(1);
163 xmlSchemaParserCtxtPtr ctxt
= xmlSchemaNewParserCtxt(xsd_file_name
);
165 ERROR("Unable to create xsd context for xsd file `%s'", xsd_file_name
);
168 xmlSchemaSetParserErrors(ctxt
, (xmlSchemaValidityErrorFunc
)fprintf
, (xmlSchemaValidityWarningFunc
)fprintf
, stderr
);
170 xmlSchemaPtr schema
= xmlSchemaParse(ctxt
);
172 ERROR("Unable to parse xsd file `%s'", xsd_file_name
);
173 xmlSchemaFreeParserCtxt(ctxt
);
177 xmlSchemaValidCtxtPtr xsd
= xmlSchemaNewValidCtxt(schema
);
179 ERROR("Schema validation error for xsd file `%s'", xsd_file_name
);
180 xmlSchemaFree(schema
);
181 xmlSchemaFreeParserCtxt(ctxt
);
184 xmlSchemaSetValidErrors(xsd
, (xmlSchemaValidityErrorFunc
) fprintf
, (xmlSchemaValidityWarningFunc
) fprintf
, stderr
);
186 int ret
= xmlSchemaValidateDoc(xsd
, xml_doc
);
188 xmlSchemaFreeValidCtxt(xsd
);
189 xmlSchemaFree(schema
);
190 xmlSchemaFreeParserCtxt(ctxt
);
191 xmlSchemaCleanupTypes();
194 return true; // successful validation
196 ERROR("TPD file `%s' is invalid according to schema `%s'", tpd_file_name
, xsd_file_name
);
199 ERROR("TPD validation of `%s' generated an internal error in libxml2", tpd_file_name
);
204 /** Extract a boolean value from the XML, if it exists otherwise flag is unchanged
206 * @param xpathCtx XPath context object
207 * @param actcfg name of the active configuration
208 * @param option name of the value
209 * @param flag pointer to the variable to receive the value
211 void xsdbool2boolean(const XPathContext
& xpathCtx
, const char *actcfg
,
212 const char *option
, boolean
* flag
)
214 char *xpath
= mprintf(
215 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
216 "/ProjectProperties/MakefileSettings/%s[text()='true']",
218 XPathObject
xpathObj(run_xpath(xpathCtx
, xpath
));
221 if (xpathObj
->nodesetval
&& xpathObj
->nodesetval
->nodeNr
> 0) {
226 extern "C" string_list
* getExternalLibs(const char* projName
)
228 if (!projGenHelper
.getZflag()) return NULL
;
229 ProjectDescriptor
* proj
= projGenHelper
.getTargetOfProject(projName
);
230 if (!proj
) return NULL
;
232 std::vector
<const char*> externalLibs
;
233 projGenHelper
.getExternalLibs(externalLibs
);
235 if (0 == externalLibs
.size()) return NULL
;
237 struct string_list
* head
= (struct string_list
*)Malloc(sizeof(struct string_list
));
238 struct string_list
* last_elem
= head
;
239 struct string_list
* tail
= head
;
241 for (size_t i
= 0; i
< externalLibs
.size(); ++i
) {
243 last_elem
->str
= mcopystr(externalLibs
[i
]);
244 last_elem
->next
= (struct string_list
*)Malloc(sizeof(struct string_list
));
245 last_elem
= last_elem
->next
;
252 extern "C" string_list
* getExternalLibPaths(const char* projName
)
254 if (!projGenHelper
.getZflag()) return NULL
;
255 ProjectDescriptor
* proj
= projGenHelper
.getTargetOfProject(projName
);
256 if (!proj
) return NULL
;
258 std::vector
<const char*> externalLibs
;
259 projGenHelper
.getExternalLibSearchPaths(externalLibs
);
261 if (0 == externalLibs
.size()) return NULL
;
263 struct string_list
* head
= (struct string_list
*)Malloc(sizeof(struct string_list
));
264 struct string_list
* last_elem
= head
;
265 struct string_list
* tail
= head
;
267 for (size_t i
= 0; i
< externalLibs
.size(); ++i
) {
269 last_elem
->str
= mcopystr(externalLibs
[i
]);
270 last_elem
->next
= (struct string_list
*)Malloc(sizeof(struct string_list
));
271 last_elem
= last_elem
->next
;
278 extern "C" string_list
* getRefWorkingDirs(const char* projName
)
280 if (!projGenHelper
.getZflag()) return NULL
;
281 ProjectDescriptor
* proj
= projGenHelper
.getTargetOfProject(projName
);
282 if (!proj
) FATAL_ERROR("Project \"%s\" was not found in the project list", projName
);
284 struct string_list
* head
= (struct string_list
*)Malloc(sizeof(struct string_list
));
285 struct string_list
* last_elem
= head
;
286 struct string_list
* tail
= head
;
287 last_elem
->str
= NULL
;
288 last_elem
->next
= NULL
;
289 for (size_t i
= 0; i
< proj
->numOfRefProjWorkingDirs(); ++i
) {
291 last_elem
->str
= mcopystr(proj
->getRefProjWorkingDir(i
).c_str());
292 last_elem
->next
= (struct string_list
*)Malloc(sizeof(struct string_list
));
293 last_elem
= last_elem
->next
;
300 extern "C" string2_list
* getLinkerLibs(const char* projName
)
303 if (!projGenHelper
.getZflag()) return NULL
;
304 if (1 == projGenHelper
.numOfProjects() || 0 == projGenHelper
.numOfLibs()){
305 return NULL
; //no library
307 ProjectDescriptor
* projLib
= projGenHelper
.getTargetOfProject(projName
);
308 if (!projLib
) FATAL_ERROR("Project \"%s\" was not found in the project list", projName
);
310 struct string2_list
* head
= (struct string2_list
*)Malloc(sizeof(struct string2_list
));
311 struct string2_list
* last_elem
= head
;
312 struct string2_list
* tail
= head
;
313 last_elem
->next
= NULL
;
314 last_elem
->str1
= NULL
;
315 last_elem
->str2
= NULL
;
316 for (std::map
<std::string
, ProjectDescriptor
>::const_iterator it
= projGenHelper
.getHead();
317 it
!= projGenHelper
.getEnd(); ++it
) {
318 if ((it
->second
).isLibrary()) {
319 if (!(it
->second
).getLinkingStrategy() &&
320 !projLib
->hasLinkerLibTo((it
->second
).getProjectName())) { // static linked library
323 std::string relPath
= projLib
->setRelativePathTo((it
->second
).getProjectAbsWorkingDir());
324 if (relPath
== std::string(".")) {
325 continue; // the relpath shows to itself
328 last_elem
->str1
= mcopystr(relPath
.c_str());
329 last_elem
->str2
= mcopystr((it
->second
).getTargetExecName().c_str());
330 last_elem
->next
= (struct string2_list
*)Malloc(sizeof(struct string2_list
));
331 last_elem
= last_elem
->next
;
337 if (head
->str1
&& head
->str2
)
343 extern "C" const char* getLibFromProject(const char* projName
)
345 if (!projGenHelper
.getZflag()) return NULL
;
346 ProjectDescriptor
* lib
= projGenHelper
.getTargetOfProject(projName
);
347 if (lib
) return lib
->getTargetExecName().c_str();
351 extern "C" void erase_libs() {
352 projGenHelper
.cleanUp();
355 extern "C" void print_libs() {
356 projGenHelper
.print();
360 extern "C" boolean
hasSubProject(const char* projName
) {
361 if (!projGenHelper
.getZflag()) return FALSE
;
362 if (projGenHelper
.getHflag())
363 return static_cast<boolean
>(projGenHelper
.hasReferencedProject());
364 else if(std::string(projName
) == projGenHelper
.getToplevelProjectName())
365 return static_cast<boolean
>(projGenHelper
.hasReferencedProject());
370 extern "C" boolean
hasExternalLibrary(const char* libName
, const char* projName
) {
371 if (!projGenHelper
.getZflag()) return FALSE
;
372 ProjectDescriptor
* projLib
= projGenHelper
.getTargetOfProject(projName
);
373 if (projLib
&& projLib
->hasLinkerLib(libName
))
379 extern "C" boolean
isTopLevelExecutable(const char* projName
) {
380 if (!projGenHelper
.getZflag()) return false;
381 ProjectDescriptor
* proj
= projGenHelper
.getTargetOfProject(projName
);
382 if (projGenHelper
.getToplevelProjectName() != std::string(projName
)) return FALSE
;
383 if (proj
&& proj
->isLibrary())
389 extern "C" boolean
isDynamicLibrary(const char* key
) {
390 if (!projGenHelper
.getZflag()) return false;
391 ProjectDescriptor
* proj
= projGenHelper
.getProjectDescriptor(key
);
392 if (proj
) return proj
->getLinkingStrategy();
393 FATAL_ERROR("Library \"%s\" was not found", key
);
397 extern "C" const char* getTPDFileName(const char* projName
) {
398 if (!projGenHelper
.getZflag()) return NULL
;
399 ProjectDescriptor
* proj
= projGenHelper
.getTargetOfProject(projName
);
400 if (proj
) return proj
->getTPDFileName().c_str();
401 FATAL_ERROR("TPD file name to project \"%s\" was not found", projName
);
404 extern "C" const char* getPathToRootDir(const char* projName
) {
405 if (!projGenHelper
.getZflag()) return NULL
;
406 ProjectDescriptor
* proj
= projGenHelper
.getTargetOfProject(projName
);
407 const char* rootDir
= projGenHelper
.getRootDirOS(projName
).c_str();
408 if (proj
&& rootDir
) {
411 FATAL_ERROR("Project \"%s\": no relative path was found to top directory at OS level.", projName
);
414 extern "C" const char* findLibraryPath(const char* libraryName
, const char* projName
)
416 if (!projGenHelper
.getZflag()) return NULL
;
417 ProjectDescriptor
* projLib
= projGenHelper
.getTargetOfProject(projName
);
418 if (!projLib
) FATAL_ERROR("Project \"%s\" was not found in the project list", projName
);
419 ProjectDescriptor
* libLib
= projGenHelper
.getProjectDescriptor(libraryName
);
420 if (!libLib
) return NULL
;
421 std::string str
= projLib
->setRelativePathTo(libLib
->getProjectAbsWorkingDir());
422 size_t refIndex
= projLib
->getLibSearchPathIndex(libLib
->getProjectName());
423 if (refIndex
> projLib
->numOfLibSearchPaths()) return NULL
;
424 projLib
->setLibSearchPath(refIndex
, str
);
425 return projLib
->getLibSearchPath(libLib
->getProjectName());
428 extern "C" const char* findLibraryName(const char* libraryName
, const char* projName
)
430 if (!projGenHelper
.getZflag()) return NULL
;
431 ProjectDescriptor
* projLib
= projGenHelper
.getTargetOfProject(projName
);
432 if (!projLib
) FATAL_ERROR("Project \"%s\" was not found in the project list", projName
);
433 ProjectDescriptor
* libLib
= projGenHelper
.getProjectDescriptor(libraryName
);
434 if (!libLib
) return NULL
;
435 for (size_t i
= 0; i
< projLib
->numOfReferencedProjects(); ++i
) {
436 const std:: string refProjName
= projLib
->getReferencedProject(i
);
437 ProjectDescriptor
* refLib
= projGenHelper
.getTargetOfProject(refProjName
.c_str());
438 if (refLib
->getTargetExecName() == std::string(libraryName
))
444 extern "C" boolean
isTtcn3ModuleInLibrary(const char* moduleName
)
446 if (!projGenHelper
.getZflag()) return FALSE
;
447 return (boolean
)projGenHelper
.isTtcn3ModuleInLibrary(moduleName
);
450 extern "C" boolean
isAsn1ModuleInLibrary(const char* moduleName
)
452 if (!projGenHelper
.getZflag()) return FALSE
;
453 return (boolean
)projGenHelper
.isAsn1ModuleInLibrary(moduleName
);
456 extern "C" boolean
isSourceFileInLibrary(const char* fileName
)
458 if (!projGenHelper
.getZflag()) return FALSE
;
459 return (boolean
)projGenHelper
.isSourceFileInLibrary(fileName
);
462 extern "C" boolean
isHeaderFileInLibrary(const char* fileName
)
464 if (!projGenHelper
.getZflag()) return FALSE
;
465 return (boolean
)projGenHelper
.isHeaderFileInLibrary(fileName
);
468 extern "C" boolean
isTtcnPPFileInLibrary(const char* fileName
)
470 if (!projGenHelper
.getZflag()) return FALSE
;
471 return (boolean
)projGenHelper
.isTtcnPPFileInLibrary(fileName
);
475 extern "C" boolean
buildObjects(const char* projName
, boolean add_referenced
)
477 if (!projGenHelper
.getZflag()) return FALSE
;
478 if (projGenHelper
.getHflag()) return FALSE
;
479 if (add_referenced
) return FALSE
;
480 ProjectDescriptor
* desc
=projGenHelper
.getTargetOfProject(projName
);
481 if (desc
&& desc
->isLibrary()) return FALSE
;
485 void append_to_library_list (const char* prjName
,
486 const XPathContext
& xpathCtx
,
489 if (!projGenHelper
.getZflag()) return;
491 char *exeXpath
= mprintf(
492 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
493 "/ProjectProperties/MakefileSettings/targetExecutable/text()",
495 XPathObject
exeObj(run_xpath(xpathCtx
, exeXpath
));
497 std::string lib_name
;
498 if (exeObj
->nodesetval
&& exeObj
->nodesetval
->nodeNr
> 0) {
499 const char* target_executable
= (const char*)exeObj
->nodesetval
->nodeTab
[0]->content
;
500 autostring
target_exe_dir(get_dir_from_path(target_executable
));
501 autostring
target_exe_file(get_file_from_path(target_executable
));
502 lib_name
= target_exe_file
;
503 ProjectDescriptor
* projDesc
= projGenHelper
.getTargetOfProject(prjName
);
505 projDesc
->setTargetExecName(lib_name
.c_str());
510 // data structures and functions to manage excluded folders/files
512 map
<cstring
, const char> excluded_files
;
514 boolean
is_excluded_file(const cstring
& path
, const char* project
) {
515 if (!excluded_files
.has_key(path
)) return false;
516 const char* proj
= excluded_files
[path
];
517 if (0 == strcmp(project
, proj
)) return true;
521 vector
<const char> excluded_folders
;
523 // Unfortunately, when "docs" is excluded, we need to drop
524 // files in "docs/", "docs/pdf/", "docs/txt/", "docs/txt/old/" etc;
525 // so it's not as simple as using a map :(
527 /** Checks whether a file is under an excluded folder
529 * @param path (relative) path of the file
530 * @return true if file is excluded, false otherwise
532 boolean
is_excluded_folder(const char *path
) {
533 boolean answer
= FALSE
;
534 size_t pathlen
= strlen(path
);
536 for (size_t i
= 0, end
= excluded_folders
.size(); i
< end
; ++i
) {
537 const char *xdir
= excluded_folders
[i
];
538 size_t xdlen
= strlen(xdir
);
539 if (pathlen
> xdlen
&& path
[xdlen
] == '/') {
540 // we may have a winner
541 if ((answer
= !strncmp(path
, xdir
, xdlen
))) break;
547 // How do you treat a raw info? You cook it, of course!
548 // Returns a newly allocated string.
549 char *cook(const char *raw
, const map
<cstring
, const char>& path_vars
)
551 const char *slash
= strchr(raw
, '/');
552 if (!slash
) { // Pretend that the slash is at the end of the string.
553 slash
= raw
+ strlen(raw
);
556 // Assume that a path variable reference is the first (or only) component
557 // of the path: ROOT in "ROOT/etc/issue".
558 autostring
prefix(mcopystrn(raw
, slash
- raw
));
559 if (path_vars
.has_key(prefix
)) {
560 char *cooked
= mcopystr(path_vars
[prefix
]);
561 bool ends_with_slash
= cooked
[strlen(cooked
)-1] == '/';
562 if (ends_with_slash
&& *slash
== '/') {
563 // Avoid paths with two slashes at the start; Cygwin thinks it's UNC
566 // If there was no '/' (only the path variable reference e.g "ROOT")
567 // then slash points to a null byte and the mputstr is a no-op.
568 cooked
= mputstr(cooked
, slash
);
572 // If the path variable could not be substituted,
573 // return (a copy of) the original.
574 return mcopystr(raw
);
577 void replacechar(char** content
) {
579 std::string s
= *content
;
581 while ((found
= s
.find('['))!= std::string::npos
){
582 s
.replace(found
,1, "${");
584 while ((found
= s
.find(']')) != std::string::npos
){
585 s
.replace(found
,1, "}");
587 *content
= mcopystr(s
.c_str());
590 static void clear_seen_tpd_files(map
<cstring
, int>& seen_tpd_files
) {
591 for (size_t i
= 0, num
= seen_tpd_files
.size(); i
< num
; ++i
) {
592 const cstring
& key
= seen_tpd_files
.get_nth_key(i
);
593 int *elem
= seen_tpd_files
.get_nth_elem(i
);
597 seen_tpd_files
.clear();
600 const char* get_act_config(struct string2_list
* cfg
, const char* project_name
) {
601 while (cfg
&& cfg
->str1
&& project_name
) {
602 if (!strcmp(cfg
->str1
, project_name
)) return cfg
->str2
;
608 static tpd_result
process_tpd_internal(const char *p_tpd_name
, const char *actcfg
,
609 const char *file_list_path
, int *p_argc
, char ***p_argv
,
610 int *p_optind
, char **p_ets_name
, char **p_project_name
,
611 boolean
*p_gflag
, boolean
*p_sflag
, boolean
*p_cflag
, boolean
*p_aflag
, boolean
*preprocess
,
612 boolean
*p_Rflag
, boolean
*p_lflag
, boolean
*p_mflag
, boolean
*p_Pflag
,
613 boolean
*p_Lflag
, boolean recursive
, boolean force_overwrite
, boolean gen_only_top_level
,
614 const char *output_file
, char** abs_work_dir_p
, struct string_list
* sub_project_dirs
,
615 const char* program_name
, FILE* prj_graph_fp
, struct string2_list
* create_symlink_list
, struct string_list
* ttcn3_prep_includes
,
616 struct string_list
* ttcn3_prep_defines
, struct string_list
* ttcn3_prep_undefines
, struct string_list
* prep_includes
,
617 struct string_list
* prep_defines
, struct string_list
* prep_undefines
, boolean
*p_csflag
, boolean
*p_quflag
, boolean
* p_dsflag
,
618 char** cxxcompiler
, char** optlevel
, char** optflags
, boolean
* p_dbflag
, boolean
* p_drflag
, boolean
* p_dtflag
, boolean
* p_dxflag
,
619 boolean
* p_djflag
, boolean
* p_fxflag
, boolean
* p_doflag
, boolean
* p_gfflag
, boolean
* p_lnflag
, boolean
* p_isflag
,
620 boolean
* p_asflag
, boolean
* p_swflag
, boolean
* p_Yflag
, boolean
* p_Mflag
, struct string_list
* solspeclibs
, struct string_list
* sol8speclibs
,
621 struct string_list
* linuxspeclibs
, struct string_list
* freebsdspeclibs
, struct string_list
* win32speclibs
, char** ttcn3prep
,
622 struct string_list
* linkerlibs
, struct string_list
* additionalObjects
, struct string_list
* linkerlibsearchp
, boolean Vflag
, boolean Dflag
,
623 boolean
*p_Zflag
, boolean
*p_Hflag
, char** generatorCommandOutput
, struct string2_list
* target_placement_list
, boolean prefix_workdir
,
624 struct string2_list
* run_command_list
, map
<cstring
, int>& seen_tpd_files
, struct string2_list
* required_configs
, struct string_list
** profiled_file_list
);
626 extern "C" tpd_result
process_tpd(const char *p_tpd_name
, const char *actcfg
,
627 const char *file_list_path
, int *p_argc
, char ***p_argv
,
628 int *p_optind
, char **p_ets_name
, char **p_project_name
,
629 boolean
*p_gflag
, boolean
*p_sflag
, boolean
*p_cflag
, boolean
*p_aflag
, boolean
*preprocess
,
630 boolean
*p_Rflag
, boolean
*p_lflag
, boolean
*p_mflag
, boolean
*p_Pflag
,
631 boolean
*p_Lflag
, boolean recursive
, boolean force_overwrite
, boolean gen_only_top_level
,
632 const char *output_file
, char** abs_work_dir_p
, struct string_list
* sub_project_dirs
,
633 const char* program_name
, FILE* prj_graph_fp
, struct string2_list
* create_symlink_list
, struct string_list
* ttcn3_prep_includes
,
634 struct string_list
* ttcn3_prep_defines
, struct string_list
* ttcn3_prep_undefines
, struct string_list
* prep_includes
,
635 struct string_list
* prep_defines
, struct string_list
* prep_undefines
, boolean
*p_csflag
, boolean
*p_quflag
, boolean
* p_dsflag
,
636 char** cxxcompiler
, char** optlevel
, char** optflags
, boolean
* p_dbflag
, boolean
* p_drflag
, boolean
* p_dtflag
, boolean
* p_dxflag
,
637 boolean
* p_djflag
, boolean
* p_fxflag
, boolean
* p_doflag
, boolean
* p_gfflag
, boolean
* p_lnflag
, boolean
* p_isflag
,
638 boolean
* p_asflag
, boolean
* p_swflag
, boolean
* p_Yflag
, boolean
* p_Mflag
, struct string_list
* solspeclibs
, struct string_list
* sol8speclibs
,
639 struct string_list
* linuxspeclibs
, struct string_list
* freebsdspeclibs
, struct string_list
* win32speclibs
, char** ttcn3prep
,
640 string_list
* linkerlibs
, string_list
* additionalObjects
, string_list
* linkerlibsearchp
, boolean Vflag
, boolean Dflag
, boolean
*p_Zflag
,
641 boolean
*p_Hflag
, char** generatorCommandOutput
, struct string2_list
* target_placement_list
, boolean prefix_workdir
,
642 struct string2_list
* run_command_list
, struct string2_list
* required_configs
, struct string_list
** profiled_file_list
) {
644 map
<cstring
, int> seen_tpd_files
;
645 projGenHelper
.setZflag(*p_Zflag
);
646 projGenHelper
.setWflag(prefix_workdir
);
647 projGenHelper
.setHflag(*p_Hflag
);
649 tpd_result success
= process_tpd_internal(p_tpd_name
,
650 actcfg
, file_list_path
, p_argc
, p_argv
, p_optind
, p_ets_name
, p_project_name
,
651 p_gflag
, p_sflag
, p_cflag
, p_aflag
, preprocess
,
652 p_Rflag
, p_lflag
, p_mflag
, p_Pflag
,
653 p_Lflag
, recursive
, force_overwrite
, gen_only_top_level
,
654 output_file
, abs_work_dir_p
, sub_project_dirs
,
655 program_name
, prj_graph_fp
, create_symlink_list
, ttcn3_prep_includes
,
656 ttcn3_prep_defines
, ttcn3_prep_undefines
, prep_includes
, prep_defines
,
657 prep_undefines
, p_csflag
, p_quflag
, p_dsflag
, cxxcompiler
,
658 optlevel
, optflags
, p_dbflag
, p_drflag
, p_dtflag
, p_dxflag
, p_djflag
,
659 p_fxflag
, p_doflag
, p_gfflag
, p_lnflag
, p_isflag
,
660 p_asflag
, p_swflag
, p_Yflag
, p_Mflag
, solspeclibs
, sol8speclibs
,
661 linuxspeclibs
, freebsdspeclibs
, win32speclibs
, ttcn3prep
,
662 linkerlibs
, additionalObjects
, linkerlibsearchp
, Vflag
, Dflag
, p_Zflag
,
663 p_Hflag
, generatorCommandOutput
, target_placement_list
, prefix_workdir
,
664 run_command_list
, seen_tpd_files
, required_configs
, profiled_file_list
);
666 if (TPD_FAILED
== success
) exit(EXIT_FAILURE
);
668 if (false == projGenHelper
.sanityCheck()) {
669 fprintf (stderr
, "makefilegen exits\n");
673 projGenHelper
.generateRefProjectWorkingDirsTo(*p_project_name
);
675 for (size_t i
= 0, num
= seen_tpd_files
.size(); i
< num
; ++i
) {
676 const cstring
& key
= seen_tpd_files
.get_nth_key(i
);
677 int *elem
= seen_tpd_files
.get_nth_elem(i
);
681 seen_tpd_files
.clear();
686 // optind is the index of the next element of argv to be processed.
687 // Return TPD_SUCESS if parsing successful, TPD_SKIPPED if the tpd was
688 // seen already, or TPD_FAILED.
690 // Note: if process_tpd() returns TPD_SUCCESS, it is expected that all strings
691 // (argv[], ets_name, other_files[], output_file) are allocated on the heap
692 // and need to be freed. On input, these strings point into argv.
693 // process_tpd() may alter these strings; new values will be on the heap.
694 // If process_tpd() preserves the content of such a string (e.g. ets_name),
695 // it must nevertheless make a copy on the heap via mcopystr().
696 static tpd_result
process_tpd_internal(const char *p_tpd_name
, const char *actcfg
,
697 const char *file_list_path
, int *p_argc
, char ***p_argv
,
698 int *p_optind
, char **p_ets_name
, char **p_project_name
,
699 boolean
*p_gflag
, boolean
*p_sflag
, boolean
*p_cflag
, boolean
*p_aflag
, boolean
*preprocess
,
700 boolean
*p_Rflag
, boolean
*p_lflag
, boolean
*p_mflag
, boolean
*p_Pflag
,
701 boolean
*p_Lflag
, boolean recursive
, boolean force_overwrite
, boolean gen_only_top_level
,
702 const char *output_file
, char** abs_work_dir_p
, struct string_list
* sub_project_dirs
,
703 const char* program_name
, FILE* prj_graph_fp
, struct string2_list
* create_symlink_list
, struct string_list
* ttcn3_prep_includes
,
704 struct string_list
* ttcn3_prep_defines
, struct string_list
* ttcn3_prep_undefines
, struct string_list
* prep_includes
,
705 struct string_list
* prep_defines
, struct string_list
* prep_undefines
, boolean
*p_csflag
, boolean
*p_quflag
, boolean
* p_dsflag
,
706 char** cxxcompiler
, char** optlevel
, char** optflags
, boolean
* p_dbflag
, boolean
* p_drflag
, boolean
* p_dtflag
, boolean
* p_dxflag
,
707 boolean
* p_djflag
, boolean
* p_fxflag
, boolean
* p_doflag
, boolean
* p_gfflag
, boolean
* p_lnflag
, boolean
* p_isflag
,
708 boolean
* p_asflag
, boolean
* p_swflag
, boolean
* p_Yflag
, boolean
* p_Mflag
, struct string_list
* solspeclibs
, struct string_list
* sol8speclibs
,
709 struct string_list
* linuxspeclibs
, struct string_list
* freebsdspeclibs
, struct string_list
* win32speclibs
, char** ttcn3prep
,
710 string_list
* linkerlibs
, string_list
* additionalObjects
, string_list
* linkerlibsearchp
, boolean Vflag
, boolean Dflag
, boolean
*p_Zflag
,
711 boolean
*p_Hflag
, char** generatorCommandOutput
, struct string2_list
* target_placement_list
, boolean prefix_workdir
,
712 struct string2_list
* run_command_list
, map
<cstring
, int>& seen_tpd_files
, struct string2_list
* required_configs
, struct string_list
** profiled_file_list
)
714 tpd_result result
= TPD_SUCCESS
;
715 // read-only non-pointer aliases
716 //char** const& local_argv = *p_argv;
717 int const& local_argc
= *p_argc
;
718 int const& local_optind
= *p_optind
;
719 *abs_work_dir_p
= NULL
;
721 assert(local_optind
>= 2 // at least '-ttpd_name' must be in the args
722 || local_optind
== 0); // if called for a referenced project
724 assert(local_argc
>= local_optind
);
726 autostring
tpd_dir(get_dir_from_path(p_tpd_name
));
727 autostring
abs_tpd_dir(get_absolute_dir(tpd_dir
, NULL
));
728 if (NULL
== (const char*)abs_tpd_dir
) {
729 ERROR("absolute TPD directory could not be retrieved from %s", (const char*)tpd_dir
);
732 autostring
tpd_filename(get_file_from_path(p_tpd_name
));
733 autostring
abs_tpd_name(compose_path_name(abs_tpd_dir
, tpd_filename
));
735 if (seen_tpd_files
.has_key(abs_tpd_name
)) {
736 ++*seen_tpd_files
[abs_tpd_name
];
737 return TPD_SKIPPED
; // nothing to do
740 if (recursive
&& !prefix_workdir
) {
741 // check that this tpd file is not inside a directory of another tpd file
742 for (size_t i
= 0; i
< seen_tpd_files
.size(); ++i
) {
743 const cstring
& other_tpd_name
= seen_tpd_files
.get_nth_key(i
);
744 autostring
other_tpd_dir(get_dir_from_path((const char*)other_tpd_name
));
745 if (strcmp((const char*)abs_tpd_dir
,(const char*)other_tpd_dir
)==0) {
746 ERROR("TPD files `%s' and `%s' are in the same directory! Use the `-W' option.", (const char*)abs_tpd_name
, (const char*)other_tpd_name
);
751 // mcopystr makes another copy for the map
752 seen_tpd_files
.add(cstring(mcopystr(abs_tpd_name
)), new int(1));
755 vector
<char> base_files
; // values Malloc'd but we pass them to the caller
757 XmlDoc
doc(xmlParseFile(p_tpd_name
));
759 fprintf(stderr
, "Error: unable to parse file \"%s\"\n", p_tpd_name
);
764 // try schema validation if tpd schema file was found
765 bool tpd_is_valid
= false;
766 const char* ttcn3_dir
= getenv("TTCN3_DIR");
768 size_t ttcn3_dir_len
= strlen(ttcn3_dir
);
769 bool ends_with_slash
= (ttcn3_dir_len
>0) && (ttcn3_dir
[ttcn3_dir_len
- 1]=='/');
770 expstring_t xsd_file_name
= mprintf("%s%setc/xsd/TPD.xsd", ttcn3_dir
, ends_with_slash
?"":"/");
771 autostring
xsd_file_name_as(xsd_file_name
);
772 if (get_path_status(xsd_file_name
)==PS_FILE
) {
773 if (validate_tpd(doc
, p_tpd_name
, xsd_file_name
)) {
775 NOTIFY("TPD file `%s' validated successfully with schema file `%s'", p_tpd_name
, xsd_file_name
);
778 ERROR("Cannot find XSD for schema for validation of TPD on path `%s'", xsd_file_name
);
781 ERROR("Environment variable TTCN3_DIR not present, cannot find XSD for schema validation of TPD");
789 // Key is projectRelativePath, value is relativeURI or rawURI.
790 map
<cstring
, const char> files
; // values Malloc'd
791 map
<cstring
, const char> folders
; // values Malloc'd
792 // NOTE! files and folders must be local variables of process_tpd.
793 // This is because the keys (not the values) are owned by the XmlDoc.
795 map
<cstring
, const char> path_vars
;
797 XPathContext
xpathCtx(xmlXPathNewContext(doc
));
798 if (xpathCtx
== NULL
) {
799 fprintf(stderr
,"Error: unable to create new XPath context\n");
802 // Collect path variables
804 XPathObject
pathsObj(run_xpath(xpathCtx
,
805 "/TITAN_Project_File_Information/PathVariables/PathVariable"));
806 xmlNodeSetPtr nodes
= pathsObj
->nodesetval
;
808 const char *name
= 0, *value
= 0;
809 if (nodes
) for (int i
= 0; i
< nodes
->nodeNr
; ++i
) {
810 // nodes->nodeTab[i]->name === "PathVariable"
811 for (xmlAttrPtr attr
= nodes
->nodeTab
[i
]->properties
; attr
; attr
= attr
->next
) {
812 if (!strcmp((const char*)attr
->name
, "name")) {
813 name
= (const char*)attr
->children
->content
;
815 else if (!strcmp((const char*)attr
->name
, "value")) {
816 value
= (const char*)attr
->children
->content
;
819 WARNING("Unknown attribute %s", (const char*)nodes
->nodeTab
[i
]->name
);
823 if (name
&& value
) path_vars
.add(cstring(name
), value
);
824 else ERROR("A PathVariable must have both name and value");
825 } // next PathVariable
830 XPathObject
foldersObj(run_xpath(xpathCtx
,
831 "/TITAN_Project_File_Information/Folders/FolderResource"));
833 xmlNodeSetPtr nodes
= foldersObj
->nodesetval
;
834 if (nodes
) for (int i
= 0; i
< nodes
->nodeNr
; ++i
) {
835 // nodes->nodeTab[i]->name === "FolderResource"
836 const char *uri
= 0, *path
= 0, *raw
= 0;
838 // projectRelativePath is the path as it appears in Project Explorer (illusion)
839 // relativeURI is the actual location, relative to the project root (reality)
840 // rawURI is present if the relative path can not be calculated
842 // Theoretically these attributes could be in any order, loop over them
843 for (xmlAttrPtr attr
= nodes
->nodeTab
[i
]->properties
; attr
; attr
= attr
->next
) {
844 if (!strcmp((const char*)attr
->name
, "projectRelativePath")) {
845 path
= (const char*)attr
->children
->content
;
847 else if (!strcmp((const char*)attr
->name
, "relativeURI")) {
848 uri
= (const char*)attr
->children
->content
;
850 else if (!strcmp((const char*)attr
->name
, "rawURI")) {
851 raw
= (const char*)attr
->children
->content
;
854 WARNING("Unknown attribute %s", (const char*)nodes
->nodeTab
[i
]->name
);
859 ERROR("A FolderResource must have a projectRelativePath");
863 if (uri
== NULL
&& raw
== NULL
) {
864 ERROR("A FolderResource must have either relativeURI or rawURI");
867 // relativeURI wins over rawURI
868 folders
.add(cstring(path
), uri
? mcopystr(uri
) : cook(raw
, path_vars
));
869 // TODO uri: cut "file:", complain on anything else
870 } // next FolderResource
873 /////////////////////////////////////////////////////////////////////////////
875 char *projectNameXpath
= mprintf("/TITAN_Project_File_Information/ProjectName/text()");
876 XPathObject
projectNameObj(run_xpath(xpathCtx
, projectNameXpath
));
877 Free(projectNameXpath
);
878 if (projectNameObj
->nodesetval
&& projectNameObj
->nodesetval
->nodeNr
> 0) {
879 *p_project_name
= mcopystr((const char*)projectNameObj
->nodesetval
->nodeTab
[0]->content
);
880 projGenHelper
.addTarget(*p_project_name
);
881 projGenHelper
.setToplevelProjectName(*p_project_name
);
882 ProjectDescriptor
* projDesc
= projGenHelper
.getTargetOfProject(*p_project_name
);
883 if (projDesc
) projDesc
->setProjectAbsTpdDir((const char*)abs_tpd_dir
);
886 /////////////////////////////////////////////////////////////////////////////
889 actcfg
= get_act_config(required_configs
,*p_project_name
);
891 if (actcfg
== NULL
) {
892 // Find out the active config
893 XPathObject
activeConfig(run_xpath(xpathCtx
,
894 "/TITAN_Project_File_Information/ActiveConfiguration/text()"));
895 if (activeConfig
->nodesetval
&& activeConfig
->nodesetval
->nodeNr
== 1) {
897 actcfg
= (const char*)activeConfig
->nodesetval
->nodeTab
[0]->content
;
901 if (actcfg
== NULL
) {
902 ERROR("Can not find the active build configuration.");
903 for (size_t i
= 0; i
< folders
.size(); ++i
) {
904 Free(const_cast<char*>(folders
.get_nth_elem(i
)));
910 { // check if the active configuration exists
911 expstring_t xpathActCfg
= mprintf(
912 "/TITAN_Project_File_Information/Configurations/"
913 "Configuration[@name='%s']/text()", actcfg
);
914 XPathObject
theConfigEx(run_xpath(xpathCtx
, xpathActCfg
));
917 xmlNodeSetPtr nodes
= theConfigEx
->nodesetval
;
919 ERROR("The active build configuration named '%s' does not exist",
921 for (size_t i
= 0; i
< folders
.size(); ++i
) {
922 Free(const_cast<char*>(folders
.get_nth_elem(i
)));
928 // working directory stuff
931 const char* workdirFromTpd
= "bin"; // default value
932 char *workdirXpath
= mprintf(
933 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
934 "/ProjectProperties/LocalBuildSettings/workingDirectory/text()",
936 XPathObject
workdirObj(run_xpath(xpathCtx
, workdirXpath
));
938 if (workdirObj
->nodesetval
&& workdirObj
->nodesetval
->nodeNr
> 0) {
939 workdirFromTpd
= (const char*)workdirObj
->nodesetval
->nodeTab
[0]->content
;
941 if (prefix_workdir
) { // the working directory is: prjNameStr + "_" + workdirFromTpd
942 const char* prjNameStr
= "unnamedproject";
943 XPathObject
prjName(run_xpath(xpathCtx
, "/TITAN_Project_File_Information/ProjectName/text()"));
944 if (prjName
->nodesetval
&& prjName
->nodesetval
->nodeNr
== 1) {
945 prjNameStr
= (const char*)prjName
->nodesetval
->nodeTab
[0]->content
;
947 workdir
= mprintf("%s_%s", prjNameStr
, workdirFromTpd
);
949 workdir
= mcopystr(workdirFromTpd
);
952 if (!folders
.has_key(workdir
)) {
953 // Maybe the tpd was saved with the option "No info about work dir"
954 folders
.add(workdir
, mcopystr(workdir
)); // fake it
956 const char *real_workdir
= folders
[workdir
]; // This is relative to the location of the tpd file
957 excluded_folders
.add(real_workdir
); // excluded by convention
959 autostring proj_abs_workdir
;
961 autostring abs_workdir
;
962 // If -D flag was specified then we ignore the workdir
963 // in the TPD (the current dir is considered the work dir).
965 bool hasWorkDir
= false;
966 // if the working directory does not exist create it
967 autostring
saved_work_dir(get_working_dir());
968 if (set_working_dir(abs_tpd_dir
)) {
969 ERROR("Could not change to project directory `%s'", (const char*)abs_tpd_dir
);
971 switch (get_path_status(real_workdir
)) {
973 ERROR("Cannot create working directory `%s' in project directory `%s' because a file with the same name exists", (const char*)abs_tpd_dir
, real_workdir
);
980 if (recursive
|| local_argc
!= 0) { // we only want to create workdir if necessary
981 fprintf(stderr
, "Working directory `%s' in project `%s' does not exist, trying to create it...\n",
982 real_workdir
, (const char*)abs_tpd_dir
);
983 int rv
= mkdir(real_workdir
, 0755);
984 if (rv
) ERROR("Could not create working directory, mkdir() failed: %s", strerror(errno
));
985 else printf("Working directory created\n");
991 if (local_argc
==0) { // if not top level
992 set_working_dir(saved_work_dir
); // restore working directory
993 } else { // if top level
994 set_working_dir(real_workdir
); // go into the working dir
996 if (hasWorkDir
) { //we created working directory, or its already been created (from a parent makefilegen process maybe)
997 *abs_work_dir_p
= get_absolute_dir(real_workdir
, abs_tpd_dir
);
998 abs_workdir
= (mcopystr(*abs_work_dir_p
));
999 proj_abs_workdir
= mcopystr(*abs_work_dir_p
);
1003 if (Dflag
) { // the path to subproject working dir is needed to find the linkerlibsearchpath
1004 proj_abs_workdir
= compose_path_name(abs_tpd_dir
, real_workdir
);
1007 ProjectDescriptor
* projDesc
= projGenHelper
.getTargetOfProject(*p_project_name
);
1009 projDesc
->setProjectAbsWorkingDir((const char*)proj_abs_workdir
);
1010 projDesc
->setProjectWorkingDir(real_workdir
);
1011 projDesc
->setTPDFileName(p_tpd_name
);
1014 /////////////////////////////////////////////////////////////////////////////
1016 // Gather the excluded folders in the active config
1018 expstring_t xpathActCfgPaths
= mprintf(
1019 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1020 "/FolderProperties/FolderResource/FolderProperties/ExcludeFromBuild[text()='true']"
1021 // This was the selection criterium, we need to go up and down for the actual information
1022 "/parent::*/parent::*/FolderPath/text()",
1024 XPathObject
theConfigEx(run_xpath(xpathCtx
, xpathActCfgPaths
));
1025 Free(xpathActCfgPaths
);
1027 xmlNodeSetPtr nodes
= theConfigEx
->nodesetval
;
1028 if (nodes
) for (int i
= 0; i
< nodes
->nodeNr
; ++i
) {
1030 excluded_folders
.add((const char*)nodes
->nodeTab
[i
]->content
);
1034 // Gather individual excluded files in the active config
1036 expstring_t xpathActCfgPaths
= mprintf(
1037 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1038 "/FileProperties/FileResource/FileProperties/ExcludeFromBuild[text()='true']"
1039 "/parent::*/parent::*/FilePath/text()",
1041 XPathObject
theConfigEx(run_xpath(xpathCtx
, xpathActCfgPaths
));
1042 Free(xpathActCfgPaths
);
1044 xmlNodeSetPtr nodes
= theConfigEx
->nodesetval
;
1045 if (nodes
) for (int i
= 0; i
< nodes
->nodeNr
; ++i
) {
1046 xmlNodePtr curnode
= nodes
->nodeTab
[i
];
1048 cstring
aa((const char*)curnode
->content
);
1049 excluded_files
.add(aa
, *p_project_name
);
1053 // Collect files; filter out excluded ones
1055 XPathObject
filesObj(run_xpath(xpathCtx
,
1056 "TITAN_Project_File_Information/Files/FileResource"));
1058 xmlNodeSetPtr nodes
= filesObj
->nodesetval
;
1059 if (nodes
) for (int i
= 0; i
< nodes
->nodeNr
; ++i
) {
1060 // nodes->nodeTab[i]->name === "FileResource"
1061 const char *uri
= 0, *path
= 0, *raw
= 0;
1063 // projectRelativePath is the path as it appears in Project Explorer (illusion)
1064 // relativeURI is the actual location, relative to the project root (reality)
1065 // rawURI is present if the relative path can not be calculated
1067 // Theoretically these attributes could be in any order, loop over them
1068 for (xmlAttrPtr attr
= nodes
->nodeTab
[i
]->properties
; attr
; attr
= attr
->next
) {
1069 if (!strcmp((const char*)attr
->name
, "projectRelativePath")) {
1070 path
= (const char*)attr
->children
->content
;
1072 else if (!strcmp((const char*)attr
->name
, "relativeURI")) {
1073 uri
= (const char*)attr
->children
->content
;
1075 else if (!strcmp((const char*)attr
->name
, "rawURI")) {
1076 raw
= (const char*)attr
->children
->content
;
1079 WARNING("Unknown attribute %s", (const char*)nodes
->nodeTab
[i
]->name
);
1084 ERROR("A FileResource must have a projectRelativePath");
1088 if (uri
== NULL
&& raw
== NULL
) {
1089 ERROR("A FileResource must have either relativeURI or rawURI");
1093 cstring
cpath(path
);
1094 if (!is_excluded_file(cpath
, *p_project_name
) && !is_excluded_folder(path
)) {
1095 // relativeURI wins over rawURI
1096 char *ruri
= uri
? mcopystr(uri
) : cook(raw
, path_vars
);
1097 if (files
.has_key(cpath
)) {
1098 ERROR("A FileResource %s must be unique!", (const char*)cpath
);
1102 const char* file_path
= ruri
;
1103 expstring_t rel_file_dir
= get_dir_from_path(file_path
);
1104 expstring_t file_name
= get_file_from_path(file_path
);
1105 expstring_t abs_dir_path
= get_absolute_dir(rel_file_dir
, abs_tpd_dir
);
1106 expstring_t abs_file_name
= compose_path_name(abs_dir_path
, file_name
);
1107 if (abs_file_name
!= NULL
) {
1108 if (get_path_status(abs_file_name
) == PS_FILE
) {
1109 FILE *fp
= fopen(abs_file_name
, "r");
1111 char* ttcn3_module_name
;
1112 if (is_ttcn3_module(abs_file_name
, fp
, &ttcn3_module_name
)) {
1113 projGenHelper
.addTtcn3ModuleToProject(*p_project_name
, ttcn3_module_name
);
1115 Free(ttcn3_module_name
);
1116 char* asn1_module_name
;
1117 if (is_asn1_module(abs_file_name
, fp
, &asn1_module_name
)) {
1118 projGenHelper
.addAsn1ModuleToProject(*p_project_name
, asn1_module_name
);
1120 Free(asn1_module_name
);
1121 if (projGenHelper
.isCPPSourceFile(file_name
)) {
1122 projGenHelper
.addUserSourceToProject(*p_project_name
, file_name
);
1124 if (projGenHelper
.isCPPHeaderFile(file_name
)) {
1125 projGenHelper
.addUserHeaderToProject(*p_project_name
, file_name
);
1127 if (projGenHelper
.isTtcnPPFile(file_name
)) {
1128 projGenHelper
.addTtcnPPToProject(*p_project_name
, file_name
);
1134 ERROR("%s does not exist", abs_file_name
);
1137 if(abs_dir_path
!= NULL
&& !drop
){
1138 files
.add(cpath
, ruri
); // relativeURI to the TPD location
1141 result
= TPD_FAILED
;
1143 { // set the *preprocess value if .ttcnpp file was found
1144 const size_t ttcnpp_extension_len
= 7; // ".ttcnpp"
1145 const size_t ruri_len
= strlen(ruri
);
1146 if ( ruri_len
>ttcnpp_extension_len
&& strcmp(ruri
+(ruri_len
-ttcnpp_extension_len
),".ttcnpp")==0 ) {
1153 Free(abs_file_name
);
1156 } // next FileResource
1160 xsdbool2boolean(xpathCtx
, actcfg
, "useAbsolutePath", p_aflag
);
1161 xsdbool2boolean(xpathCtx
, actcfg
, "GNUMake", p_gflag
);
1162 if (*p_Zflag
) *p_lflag
= FALSE
;
1163 xsdbool2boolean(xpathCtx
, actcfg
, "dynamicLinking", p_lflag
);
1164 xsdbool2boolean(xpathCtx
, actcfg
, "functiontestRuntime", p_Rflag
);
1165 xsdbool2boolean(xpathCtx
, actcfg
, "singleMode", p_sflag
);
1166 xsdbool2boolean(xpathCtx
, actcfg
, "codeSplitting", p_csflag
);
1167 xsdbool2boolean(xpathCtx
, actcfg
, "quietly", p_quflag
);
1168 xsdbool2boolean(xpathCtx
, actcfg
, "disableSubtypeChecking", p_dsflag
);
1169 xsdbool2boolean(xpathCtx
, actcfg
, "disableBER", p_dbflag
);
1170 xsdbool2boolean(xpathCtx
, actcfg
, "disableRAW", p_drflag
);
1171 xsdbool2boolean(xpathCtx
, actcfg
, "disableTEXT", p_dtflag
);
1172 xsdbool2boolean(xpathCtx
, actcfg
, "disableXER", p_dxflag
);
1173 xsdbool2boolean(xpathCtx
, actcfg
, "disableJSON", p_djflag
);
1174 xsdbool2boolean(xpathCtx
, actcfg
, "forceXERinASN.1", p_fxflag
);
1175 xsdbool2boolean(xpathCtx
, actcfg
, "defaultasOmit", p_doflag
);
1176 xsdbool2boolean(xpathCtx
, actcfg
, "gccMessageFormat", p_gfflag
);
1177 xsdbool2boolean(xpathCtx
, actcfg
, "lineNumbersOnlyInMessages", p_lnflag
);
1178 xsdbool2boolean(xpathCtx
, actcfg
, "includeSourceInfo", p_isflag
);
1179 xsdbool2boolean(xpathCtx
, actcfg
, "addSourceLineInfo", p_asflag
);
1180 xsdbool2boolean(xpathCtx
, actcfg
, "suppressWarnings", p_swflag
);
1181 xsdbool2boolean(xpathCtx
, actcfg
, "outParamBoundness", p_Yflag
); //not documented, obsolete
1182 xsdbool2boolean(xpathCtx
, actcfg
, "forceOldFuncOutParHandling", p_Yflag
);
1183 xsdbool2boolean(xpathCtx
, actcfg
, "omitInValueList", p_Mflag
);
1185 projDesc
= projGenHelper
.getTargetOfProject(*p_project_name
);
1186 if (projDesc
) projDesc
->setLinkingStrategy(*p_lflag
);
1188 // Extract the "incremental dependencies" option
1190 boolean incremental_deps
= TRUE
;
1191 xsdbool2boolean(xpathCtx
, actcfg
, "incrementalDependencyRefresh", &incremental_deps
);
1193 // For makefilegen, "Use GNU make" implies incremental deps by default,
1194 // unless explicitly disabled by "use makedepend" (a.k.a. mflag).
1195 // For Eclipse, incremental deps must be explicitly specified,
1196 // even if GNU make is being used.
1198 if (incremental_deps
) {
1200 WARNING("Incremental dependency ordered but it requires gnu make");
1205 // GNU make but no incremental deps
1211 // Extract the default target option
1212 // if it is not defined as a command line argument
1214 expstring_t defTargetXpath
= mprintf(
1215 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1216 "/ProjectProperties/MakefileSettings/defaultTarget/text()",
1218 XPathObject
defTargetObj(run_xpath(xpathCtx
, defTargetXpath
));
1219 Free(defTargetXpath
);
1220 if (defTargetObj
->nodesetval
&& defTargetObj
->nodesetval
->nodeNr
> 0) {
1221 const char* content
= (const char*)defTargetObj
->nodesetval
->nodeTab
[0]->content
;
1222 if (!strcmp(content
, "library")) {
1224 } else if (!strcmp(content
, "executable")) {
1227 ERROR("Unknown default target: '%s'."
1228 " The available targets are: 'executable', 'library'", content
);
1231 ProjectDescriptor
* projDesc
= projGenHelper
.getTargetOfProject(*p_project_name
);
1232 if (projDesc
) projDesc
->setLibrary(*p_Lflag
);
1235 // Executable name (don't care unless top-level invocation)
1236 if (local_argc
!= 0)
1238 char *exeXpath
= mprintf(
1239 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1240 "/ProjectProperties/MakefileSettings/targetExecutable/text()",
1242 XPathObject
exeObj(run_xpath(xpathCtx
, exeXpath
));
1244 if (exeObj
->nodesetval
&& exeObj
->nodesetval
->nodeNr
> 0) {
1245 const char* target_executable
= (const char*)exeObj
->nodesetval
->nodeTab
[0]->content
;
1246 autostring
target_exe_dir(get_dir_from_path(target_executable
));
1247 autostring
target_exe_file(get_file_from_path(target_executable
));
1248 if (target_exe_dir
!=NULL
) { // if it's not only a file name
1249 if (get_path_status(target_exe_dir
)==PS_NONEXISTENT
) {
1250 if (strcmp(real_workdir
,target_exe_dir
)!=0) {
1251 WARNING("Provided targetExecutable directory `%s' does not exist, only file name `%s' will be used", (const char*)target_exe_dir
, (const char*)target_exe_file
);
1253 target_executable
= target_exe_file
;
1256 if (!*p_ets_name
) { // Command line will win
1257 *p_ets_name
= mcopystr(target_executable
);
1262 // create an xml element for the currently processed project
1264 const char* prjNameStr
= "???";
1265 XPathObject
prjName(run_xpath(xpathCtx
, "/TITAN_Project_File_Information/ProjectName/text()"));
1266 if (prjName
->nodesetval
&& prjName
->nodesetval
->nodeNr
== 1) {
1267 prjNameStr
= (const char*)prjName
->nodesetval
->nodeTab
[0]->content
;
1269 autostring
tpd_rel_dir(get_relative_dir(tpd_dir
, NULL
));
1270 autostring
tpd_rel_path(compose_path_name(tpd_rel_dir
, (const char*)tpd_filename
));
1271 fprintf(prj_graph_fp
, "<project name=\"%s\" uri=\"%s\">\n", prjNameStr
, (const char*)tpd_rel_path
);
1272 XPathObject
subprojects(run_xpath(xpathCtx
, "/TITAN_Project_File_Information/ReferencedProjects/ReferencedProject/attribute::name"));
1273 xmlNodeSetPtr nodes
= subprojects
->nodesetval
;
1274 if (nodes
) for (int i
= 0; i
< nodes
->nodeNr
; ++i
) {
1275 const char* refd_name
= "???";
1276 if (!strcmp((const char*)nodes
->nodeTab
[i
]->name
, "name")) {
1277 refd_name
= (const char*)nodes
->nodeTab
[i
]->children
->content
;
1279 fprintf(prj_graph_fp
, "<reference name=\"%s\"/>\n", refd_name
);
1281 fprintf(prj_graph_fp
, "</project>\n");
1284 // Tpd part of the MakefileSettings
1286 //TTCN3preprocessorIncludes
1287 char *preincludeXpath
= mprintf(
1288 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1289 "/ProjectProperties/MakefileSettings/TTCN3preprocessorIncludes/listItem/text()",
1291 XPathObject
preincludeObj(run_xpath(xpathCtx
, preincludeXpath
));
1292 Free(preincludeXpath
);
1294 xmlNodeSetPtr nodes
= preincludeObj
->nodesetval
;
1296 if (nodes
) for (int i
= 0; i
< nodes
->nodeNr
; ++i
) {
1297 char* content
= (char*)preincludeObj
->nodesetval
->nodeTab
[i
]->content
;
1299 // add includes to the end of list
1300 if (ttcn3_prep_includes
) {
1301 // go to last element
1302 struct string_list
* last_elem
= ttcn3_prep_includes
;
1303 while (last_elem
->next
) last_elem
= last_elem
->next
;
1304 // add string to last element if empty or create new last element and add it to that
1305 if (last_elem
->str
) {
1306 last_elem
->next
= (struct string_list
*)Malloc(sizeof(struct string_list
));
1307 last_elem
= last_elem
->next
;
1308 last_elem
->next
= NULL
;
1310 replacechar(&content
);
1311 last_elem
->str
= content
;
1316 //TTCN3preprocessorDefines
1317 char *ttcn3predefinesXpath
= mprintf(
1318 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1319 "/ProjectProperties/MakefileSettings/TTCN3preprocessorDefines/listItem/text()",
1321 XPathObject
ttcn3predefinesObj(run_xpath(xpathCtx
, ttcn3predefinesXpath
));
1322 Free(ttcn3predefinesXpath
);
1324 xmlNodeSetPtr nodes
= ttcn3predefinesObj
->nodesetval
;
1326 if (nodes
) for (int i
= 0; i
< nodes
->nodeNr
; ++i
) {
1327 const char* content
= (const char*)ttcn3predefinesObj
->nodesetval
->nodeTab
[i
]->content
;
1329 // add includes to the end of list
1330 if (ttcn3_prep_defines
) {
1331 // go to last element
1332 struct string_list
* last_elem
= ttcn3_prep_defines
;
1333 while (last_elem
->next
) last_elem
= last_elem
->next
;
1334 // add string to last element if empty or create new last element and add it to that
1335 if (last_elem
->str
) {
1336 last_elem
->next
= (struct string_list
*)Malloc(sizeof(struct string_list
));
1337 last_elem
= last_elem
->next
;
1338 last_elem
->next
= NULL
;
1340 last_elem
->str
= mcopystr(content
);
1345 //TTCN3preprocessorUnDefines
1346 char *ttcn3preUndefinesXpath
= mprintf(
1347 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1348 "/ProjectProperties/MakefileSettings/TTCN3preprocessorUndefines/listItem/text()",
1350 XPathObject
ttcn3preUndefinesObj(run_xpath(xpathCtx
, ttcn3preUndefinesXpath
));
1351 Free(ttcn3preUndefinesXpath
);
1353 xmlNodeSetPtr nodes
= ttcn3preUndefinesObj
->nodesetval
;
1355 if (nodes
) for (int i
= 0; i
< nodes
->nodeNr
; ++i
) {
1356 const char* content
= (const char*)ttcn3preUndefinesObj
->nodesetval
->nodeTab
[i
]->content
;
1358 // add includes to the end of list
1359 if (ttcn3_prep_undefines
) {
1360 // go to last element
1361 struct string_list
* last_elem
= ttcn3_prep_undefines
;
1362 while (last_elem
->next
) last_elem
= last_elem
->next
;
1363 // add string to last element if empty or create new last element and add it to that
1364 if (last_elem
->str
) {
1365 last_elem
->next
= (struct string_list
*)Malloc(sizeof(struct string_list
));
1366 last_elem
= last_elem
->next
;
1367 last_elem
->next
= NULL
;
1369 last_elem
->str
= mcopystr(content
);
1375 //preprocessorIncludes
1376 char *preincludesXpath
= mprintf(
1377 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1378 "/ProjectProperties/MakefileSettings/preprocessorIncludes/listItem/text()",
1380 XPathObject
preincludesObj(run_xpath(xpathCtx
, preincludesXpath
));
1381 Free(preincludesXpath
);
1383 xmlNodeSetPtr nodes
= preincludesObj
->nodesetval
;
1385 if (nodes
) for (int i
= 0; i
< nodes
->nodeNr
; ++i
) {
1386 char* content
= (char*)preincludesObj
->nodesetval
->nodeTab
[i
]->content
;
1388 // add includes to the end of list
1389 if (prep_includes
) {
1390 // go to last element
1391 struct string_list
* last_elem
= prep_includes
;
1392 while (last_elem
->next
) last_elem
= last_elem
->next
;
1393 // add string to last element if empty or create new last element and add it to that
1394 if (last_elem
->str
) {
1395 last_elem
->next
= (struct string_list
*)Malloc(sizeof(struct string_list
));
1396 last_elem
= last_elem
->next
;
1397 last_elem
->next
= NULL
;
1399 replacechar(&content
);
1400 last_elem
->str
= content
;
1405 //preprocessorDefines
1406 char *predefinesXpath
= mprintf(
1407 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1408 "/ProjectProperties/MakefileSettings/preprocessorDefines/listItem/text()",
1410 XPathObject
predefinesObj(run_xpath(xpathCtx
, predefinesXpath
));
1411 Free(predefinesXpath
);
1413 xmlNodeSetPtr nodes
= predefinesObj
->nodesetval
;
1415 if (nodes
) for (int i
= 0; i
< nodes
->nodeNr
; ++i
) {
1416 const char* content
= (const char*)predefinesObj
->nodesetval
->nodeTab
[i
]->content
;
1418 // add includes to the end of list
1420 // go to last element
1421 struct string_list
* last_elem
= prep_defines
;
1422 while (last_elem
->next
) last_elem
= last_elem
->next
;
1423 // add string to last element if empty or create new last element and add it to that
1424 if (last_elem
->str
) {
1425 last_elem
->next
= (struct string_list
*)Malloc(sizeof(struct string_list
));
1426 last_elem
= last_elem
->next
;
1427 last_elem
->next
= NULL
;
1429 last_elem
->str
= mcopystr(content
);
1434 //preprocessorUnDefines
1435 char *preUndefinesXpath
= mprintf(
1436 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1437 "/ProjectProperties/MakefileSettings/preprocessorUndefines/listItem/text()",
1439 XPathObject
preUndefinesObj(run_xpath(xpathCtx
, preUndefinesXpath
));
1440 Free(preUndefinesXpath
);
1442 xmlNodeSetPtr nodes
= preUndefinesObj
->nodesetval
;
1444 if (nodes
) for (int i
= 0; i
< nodes
->nodeNr
; ++i
) {
1445 const char* content
= (const char*)preUndefinesObj
->nodesetval
->nodeTab
[i
]->content
;
1447 // add includes to the end of list
1448 if (prep_undefines
) {
1449 // go to last element
1450 struct string_list
* last_elem
= prep_undefines
;
1451 while (last_elem
->next
) last_elem
= last_elem
->next
;
1452 // add string to last element if empty or create new last element and add it to that
1453 if (last_elem
->str
) {
1454 last_elem
->next
= (struct string_list
*)Malloc(sizeof(struct string_list
));
1455 last_elem
= last_elem
->next
;
1456 last_elem
->next
= NULL
;
1458 last_elem
->str
= mcopystr(content
);
1463 char *cxxCompilerXpath
= mprintf(
1464 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1465 "/ProjectProperties/MakefileSettings/CxxCompiler/text()",
1467 XPathObject
cxxCompilerObj(run_xpath(xpathCtx
, cxxCompilerXpath
));
1468 Free(cxxCompilerXpath
);
1469 xmlNodeSetPtr nodes
= cxxCompilerObj
->nodesetval
;
1471 *cxxcompiler
= mcopystr((const char*)cxxCompilerObj
->nodesetval
->nodeTab
[0]->content
);
1475 char *optLevelXpath
= mprintf(
1476 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1477 "/ProjectProperties/MakefileSettings/optimizationLevel/text()",
1479 XPathObject
optLevelObj(run_xpath(xpathCtx
, optLevelXpath
));
1480 Free(optLevelXpath
);
1481 xmlNodeSetPtr nodes
= optLevelObj
->nodesetval
;
1483 *optlevel
= mcopystr((const char*)optLevelObj
->nodesetval
->nodeTab
[0]->content
);
1487 char *optFlagsXpath
= mprintf(
1488 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1489 "/ProjectProperties/MakefileSettings/otherOptimizationFlags/text()",
1491 XPathObject
optFlagsObj(run_xpath(xpathCtx
, optFlagsXpath
));
1492 Free(optFlagsXpath
);
1493 xmlNodeSetPtr nodes
= optFlagsObj
->nodesetval
;
1495 *optflags
= mcopystr((const char*)optFlagsObj
->nodesetval
->nodeTab
[0]->content
);
1499 //SolarisSpecificLibraries
1500 char *solspeclibXpath
= mprintf(
1501 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1502 "/ProjectProperties/MakefileSettings/SolarisSpecificLibraries/listItem/text()",
1504 XPathObject
solspeclibObj(run_xpath(xpathCtx
, solspeclibXpath
));
1505 Free(solspeclibXpath
);
1507 xmlNodeSetPtr nodes
= solspeclibObj
->nodesetval
;
1509 if (nodes
) for (int i
= 0; i
< nodes
->nodeNr
; ++i
) {
1510 char* content
= (char*)solspeclibObj
->nodesetval
->nodeTab
[i
]->content
;
1512 // add includes to the end of list
1514 // go to last element
1515 struct string_list
* last_elem
=solspeclibs
;
1516 while (last_elem
->next
) last_elem
= last_elem
->next
;
1517 // add string to last element if empty or create new last element and add it to that
1518 if (last_elem
->str
) {
1519 last_elem
->next
= (struct string_list
*)Malloc(sizeof(struct string_list
));
1520 last_elem
= last_elem
->next
;
1521 last_elem
->next
= NULL
;
1523 replacechar(&content
);
1524 last_elem
->str
= content
;
1529 //Solaris8SpecificLibraries
1530 char *sol8speclibXpath
= mprintf(
1531 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1532 "/ProjectProperties/MakefileSettings/Solaris8SpecificLibraries/listItem/text()",
1534 XPathObject
sol8speclibObj(run_xpath(xpathCtx
, sol8speclibXpath
));
1535 Free(sol8speclibXpath
);
1537 xmlNodeSetPtr nodes
= sol8speclibObj
->nodesetval
;
1539 if (nodes
) for (int i
= 0; i
< nodes
->nodeNr
; ++i
) {
1540 char* content
= (char*)sol8speclibObj
->nodesetval
->nodeTab
[i
]->content
;
1542 // add includes to the end of list
1544 // go to last element
1545 struct string_list
* last_elem
= sol8speclibs
;
1546 while (last_elem
->next
) last_elem
= last_elem
->next
;
1547 // add string to last element if empty or create new last element and add it to that
1548 if (last_elem
->str
) {
1549 last_elem
->next
= (struct string_list
*)Malloc(sizeof(struct string_list
));
1550 last_elem
= last_elem
->next
;
1551 last_elem
->next
= NULL
;
1553 replacechar(&content
);
1554 last_elem
->str
= content
;
1559 //LinuxSpecificLibraries
1560 char *linuxspeclibXpath
= mprintf(
1561 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1562 "/ProjectProperties/MakefileSettings/LinuxSpecificLibraries/listItem/text()",
1564 XPathObject
linuxspeclibObj(run_xpath(xpathCtx
, linuxspeclibXpath
));
1565 Free(linuxspeclibXpath
);
1567 xmlNodeSetPtr nodes
= linuxspeclibObj
->nodesetval
;
1569 if (nodes
) for (int i
= 0; i
< nodes
->nodeNr
; ++i
) {
1570 char* content
= (char*)linuxspeclibObj
->nodesetval
->nodeTab
[i
]->content
;
1572 // add includes to the end of list
1573 if (linuxspeclibs
) {
1574 // go to last element
1575 struct string_list
* last_elem
= linuxspeclibs
;
1576 while (last_elem
->next
) last_elem
= last_elem
->next
;
1577 // add string to last element if empty or create new last element and add it to that
1578 if (last_elem
->str
) {
1579 last_elem
->next
= (struct string_list
*)Malloc(sizeof(struct string_list
));
1580 last_elem
= last_elem
->next
;
1581 last_elem
->next
= NULL
;
1583 replacechar(&content
);
1584 last_elem
->str
= content
;
1589 //FreeBSDSpecificLibraries
1590 char *freebsdspeclibXpath
= mprintf(
1591 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1592 "/ProjectProperties/MakefileSettings/FreeBSDSpecificLibraries/listItem/text()",
1594 XPathObject
freebsdspeclibObj(run_xpath(xpathCtx
, freebsdspeclibXpath
));
1595 Free(freebsdspeclibXpath
);
1597 xmlNodeSetPtr nodes
= freebsdspeclibObj
->nodesetval
;
1599 if (nodes
) for (int i
= 0; i
< nodes
->nodeNr
; ++i
) {
1600 char* content
= (char*)freebsdspeclibObj
->nodesetval
->nodeTab
[i
]->content
;
1602 // add includes to the end of list
1603 if (freebsdspeclibs
) {
1604 // go to last element
1605 struct string_list
* last_elem
= freebsdspeclibs
;
1606 while (last_elem
->next
) last_elem
= last_elem
->next
;
1607 // add string to last element if empty or create new last element and add it to that
1608 if (last_elem
->str
) {
1609 last_elem
->next
= (struct string_list
*)Malloc(sizeof(struct string_list
));
1610 last_elem
= last_elem
->next
;
1611 last_elem
->next
= NULL
;
1613 replacechar(&content
);
1614 last_elem
->str
= content
;
1619 //Win32SpecificLibraries
1620 char *win32speclibXpath
= mprintf(
1621 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1622 "/ProjectProperties/MakefileSettings/Win32SpecificLibraries/listItem/text()",
1624 XPathObject
win32speclibObj(run_xpath(xpathCtx
, win32speclibXpath
));
1625 Free(win32speclibXpath
);
1627 xmlNodeSetPtr nodes
= win32speclibObj
->nodesetval
;
1629 if (nodes
) for (int i
= 0; i
< nodes
->nodeNr
; ++i
) {
1630 char* content
= (char*)win32speclibObj
->nodesetval
->nodeTab
[i
]->content
;
1632 // add includes to the end of list
1633 if (win32speclibs
) {
1634 // go to last element
1635 struct string_list
* last_elem
= win32speclibs
;
1636 while (last_elem
->next
) last_elem
= last_elem
->next
;
1637 // add string to last element if empty or create new last element and add it to that
1638 if (last_elem
->str
) {
1639 last_elem
->next
= (struct string_list
*)Malloc(sizeof(struct string_list
));
1640 last_elem
= last_elem
->next
;
1641 last_elem
->next
= NULL
;
1643 replacechar(&content
);
1644 last_elem
->str
= content
;
1651 char *ttcn3preproc
= mprintf(
1652 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1653 "/ProjectProperties/MakefileSettings/TTCN3preprocessor/text()",
1655 XPathObject
ttcn3preprocObj(run_xpath(xpathCtx
, ttcn3preproc
));
1657 xmlNodeSetPtr nodes
= ttcn3preprocObj
->nodesetval
;
1659 *ttcn3prep
= mcopystr((const char*)ttcn3preprocObj
->nodesetval
->nodeTab
[0]->content
);
1663 // additionalObjects
1664 char *additionalObjectsXpath
= mprintf(
1665 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1666 "/ProjectProperties/MakefileSettings/additionalObjects/listItem/text()",
1668 XPathObject
additionalObjectsObj(run_xpath(xpathCtx
, additionalObjectsXpath
));
1669 Free(additionalObjectsXpath
);
1671 xmlNodeSetPtr nodes
= additionalObjectsObj
->nodesetval
;
1673 if (nodes
) for (int i
= 0; i
< nodes
->nodeNr
; ++i
) {
1674 char* content
= (char*)additionalObjectsObj
->nodesetval
->nodeTab
[i
]->content
;
1676 // add to the end of list
1677 if (additionalObjects
) {
1678 // go to last element
1679 struct string_list
* last_elem
= additionalObjects
;
1680 while (last_elem
->next
) last_elem
= last_elem
->next
;
1681 // add string to last element if empty or create new last element and add it to that
1682 if (last_elem
->str
) {
1683 last_elem
->next
= (struct string_list
*)Malloc(sizeof(struct string_list
));
1684 last_elem
= last_elem
->next
;
1685 last_elem
->next
= NULL
;
1687 replacechar(&content
);
1688 last_elem
->str
= content
;
1693 //The project name needed the hierarchical projects
1694 char* prjNameStr
= 0;
1695 char *prjNameStrXpath
= mprintf("/TITAN_Project_File_Information/ProjectName/text()");
1696 XPathObject
prjName(run_xpath(xpathCtx
, prjNameStrXpath
));
1697 if (prjName
->nodesetval
&& prjName
->nodesetval
->nodeNr
== 1) {
1698 prjNameStr
= (char*)prjName
->nodesetval
->nodeTab
[0]->content
;
1700 Free(prjNameStrXpath
);
1701 append_to_library_list (prjNameStr
, xpathCtx
, actcfg
);
1704 char *linkerlibsXpath
= mprintf(
1705 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1706 "/ProjectProperties/MakefileSettings/linkerLibraries/listItem/text()",
1708 XPathObject
linkerlibsObj(run_xpath(xpathCtx
, linkerlibsXpath
));
1709 Free(linkerlibsXpath
);
1711 xmlNodeSetPtr nodes
= linkerlibsObj
->nodesetval
;
1713 if (nodes
) for (int i
= 0; i
< nodes
->nodeNr
; ++i
) {
1714 char* content
= (char*)linkerlibsObj
->nodesetval
->nodeTab
[i
]->content
;
1716 // add includes to the end of list
1718 // go to last element
1719 struct string_list
* last_elem
= linkerlibs
;
1720 while (last_elem
->next
) last_elem
= last_elem
->next
;
1721 // add string to last element if empty or create new last element and add it to that
1722 if (last_elem
->str
) {
1723 last_elem
->next
= (struct string_list
*)Malloc(sizeof(struct string_list
));
1724 last_elem
= last_elem
->next
;
1725 last_elem
->next
= NULL
;
1727 replacechar(&content
);
1728 last_elem
->str
= content
;
1730 ProjectDescriptor
* projDesc
= projGenHelper
.getTargetOfProject(*p_project_name
);
1731 if (projDesc
) projDesc
->addToLinkerLibs(last_elem
->str
);
1736 //linkerLibrarySearchPath
1737 char *linkerlibsearchXpath
= mprintf(
1738 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1739 "/ProjectProperties/MakefileSettings/linkerLibrarySearchPath/listItem/text()",
1741 XPathObject
linkerlibsearchObj(run_xpath(xpathCtx
, linkerlibsearchXpath
));
1742 Free(linkerlibsearchXpath
);
1744 xmlNodeSetPtr nodes
= linkerlibsearchObj
->nodesetval
;
1746 if (nodes
) for (int i
= 0; i
< nodes
->nodeNr
; ++i
) {
1747 char* content
= (char*)linkerlibsearchObj
->nodesetval
->nodeTab
[i
]->content
;
1749 // add includes to the end of list
1750 if (linkerlibsearchp
) {
1751 // go to last element
1752 struct string_list
* last_elem
= linkerlibsearchp
;
1753 while (last_elem
->next
) last_elem
= last_elem
->next
;
1754 // add string to last element if empty or create new last element and add it to that
1755 if (last_elem
->str
) {
1756 last_elem
->next
= (struct string_list
*)Malloc(sizeof(struct string_list
));
1757 last_elem
= last_elem
->next
;
1758 last_elem
->next
= NULL
;
1760 replacechar(&content
);
1761 last_elem
->str
= content
;
1763 ProjectDescriptor
* projDesc
= projGenHelper
.getTargetOfProject(*p_project_name
);
1764 if (projDesc
) projDesc
->addToLibSearchPaths(last_elem
->str
);
1769 if (generatorCommandOutput
&& local_argc
!= 0) { // only in case of top-level invocation
1770 char* generatorCommandXpath
= mprintf(
1771 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1772 "/ProjectProperties/MakefileSettings/ProjectSpecificRulesGenerator/GeneratorCommand/text()",
1774 XPathObject
generatorCommandObj(run_xpath(xpathCtx
, generatorCommandXpath
));
1775 Free(generatorCommandXpath
);
1776 autostring generatorCommand
;
1777 if (generatorCommandObj
->nodesetval
&& generatorCommandObj
->nodesetval
->nodeNr
> 0) {
1778 generatorCommand
= mcopystr((const char*)generatorCommandObj
->nodesetval
->nodeTab
[0]->content
);
1779 // run the command and capture the output
1780 printf("Executing generator command `%s' specified in `%s'...\n", (const char*)generatorCommand
, (const char*)abs_tpd_name
);
1781 FILE* gc_fp
= popen(generatorCommand
, "r");
1783 ERROR("Could not execute command `%s'", (const char*)generatorCommand
);
1786 while (fgets(buff
, sizeof(buff
), gc_fp
)!=NULL
) {
1787 *generatorCommandOutput
= mputstr(*generatorCommandOutput
, buff
);
1794 if (target_placement_list
&& local_argc
!= 0) { // only in case of top-level invocation
1795 char* targetPlacementXpath
= mprintf(
1796 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1797 "/ProjectProperties/MakefileSettings/ProjectSpecificRulesGenerator/Targets/Target/attribute::*",
1799 XPathObject
targetPlacementObj(run_xpath(xpathCtx
, targetPlacementXpath
));
1800 Free(targetPlacementXpath
);
1801 xmlNodeSetPtr nodes
= targetPlacementObj
->nodesetval
;
1802 const char* targetName
= NULL
;
1803 const char* targetPlacement
= NULL
;
1804 if (nodes
) for (int i
= 0; i
< nodes
->nodeNr
; ++i
) {
1805 if (!strcmp((const char*)nodes
->nodeTab
[i
]->name
, "name")) {
1806 targetName
= (const char*)nodes
->nodeTab
[i
]->children
->content
;
1808 else if (!strcmp((const char*)nodes
->nodeTab
[i
]->name
,"placement")) {
1809 targetPlacement
= (const char*)nodes
->nodeTab
[i
]->children
->content
;
1811 if (targetName
&& targetPlacement
) { // collected both
1812 if (target_placement_list
) {
1813 // go to last element
1814 struct string2_list
* last_elem
= target_placement_list
;
1815 while (last_elem
->next
) last_elem
= last_elem
->next
;
1816 // add strings to last element if empty or create new last element and add it to that
1817 if (last_elem
->str1
) {
1818 last_elem
->next
= (struct string2_list
*)Malloc(sizeof(struct string2_list
));
1819 last_elem
= last_elem
->next
;
1820 last_elem
->next
= NULL
;
1822 last_elem
->str1
= mcopystr(targetName
);
1823 last_elem
->str2
= mcopystr(targetPlacement
);
1825 targetName
= targetPlacement
= NULL
; // forget both
1831 // profiler file name
1832 char* profilerXpath
= mprintf(
1833 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1834 "/ProjectProperties/MakefileSettings/profiledFileList", actcfg
);
1835 XPathObject
profiledFilesNameObj(run_xpath(xpathCtx
, profilerXpath
));
1836 Free(profilerXpath
);
1837 xmlNodeSetPtr nodes
= profiledFilesNameObj
->nodesetval
;
1838 if (nodes
&& nodes
->nodeNr
> 0) {
1839 const char *uri
= 0, *path
= 0, *raw
= 0;
1840 for (xmlAttrPtr attr
= nodes
->nodeTab
[0]->properties
; attr
; attr
= attr
->next
) {
1841 if (!strcmp((const char*)attr
->name
, "projectRelativePath")) {
1842 path
= (const char*)attr
->children
->content
;
1844 else if (!strcmp((const char*)attr
->name
, "relativeURI")) {
1845 uri
= (const char*)attr
->children
->content
;
1847 else if (!strcmp((const char*)attr
->name
, "rawURI")) {
1848 raw
= (const char*)attr
->children
->content
;
1851 WARNING("Unknown attribute %s", (const char*)nodes
->nodeTab
[0]->name
);
1856 ERROR("A profiledFileList must have a projectRelativePath");
1859 if (uri
== NULL
&& raw
== NULL
) {
1860 ERROR("A profiledFileList must have either relativeURI or rawURI");
1863 cstring
cpath(path
);
1864 if (files
.has_key(cpath
)) {
1865 ERROR("profiledFileLists and FileResources must be unique!");
1868 // add the file to the end of the list
1869 struct string_list
* new_item
= NULL
;
1870 if (*profiled_file_list
== NULL
) {
1871 *profiled_file_list
= (struct string_list
*)Malloc(sizeof(struct string_list
));
1872 new_item
= *profiled_file_list
;
1875 new_item
= *profiled_file_list
;
1876 while(new_item
->next
!= NULL
) {
1877 new_item
= new_item
->next
;
1879 new_item
->next
= (struct string_list
*)Malloc(sizeof(struct string_list
));
1880 new_item
= new_item
->next
;
1882 new_item
->str
= mcopystr(path
);
1883 new_item
->next
= NULL
;
1885 // add the file to the map of files to be copied to the working directory
1886 char *ruri
= uri
? mcopystr(uri
) : cook(raw
, path_vars
);
1887 files
.add(cpath
, ruri
);
1894 // collect the required configurations
1896 if (required_configs
) {
1897 char* cfgReqsXpath(mprintf(
1898 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1899 "/ProjectProperties/ConfigurationRequirements/configurationRequirement",
1901 XPathObject
reqcfgObjects(run_xpath(xpathCtx
, cfgReqsXpath
));
1902 Free (cfgReqsXpath
);
1903 xmlNodeSetPtr configs
= reqcfgObjects
->nodesetval
;
1904 if (configs
) for (int i
= 0; i
< configs
->nodeNr
; ++i
) {
1905 xmlNodePtr curNodePtr
= configs
->nodeTab
[i
]->children
;
1906 const char* projectName
= NULL
;
1907 const char* reqConfig
= NULL
;
1909 if (!strcmp((const char*)curNodePtr
->name
, "projectName")) {
1910 projectName
= (const char*)curNodePtr
->children
->content
;
1912 if (!strcmp((const char*)curNodePtr
->name
, "rerquiredConfiguration") || // backward compatibility
1913 !strcmp((const char*)curNodePtr
->name
, "requiredConfiguration")) {
1914 reqConfig
= (const char*)curNodePtr
->children
->content
;
1916 curNodePtr
= curNodePtr
->next
;
1918 struct string2_list
* last_elem
= required_configs
;
1919 bool duplicate
= false;
1920 while (last_elem
->next
) {
1921 if (!strcmp(last_elem
->str1
, projectName
) && !strcmp(last_elem
->str2
, reqConfig
)) {
1924 else if (!strcmp(last_elem
->str1
, projectName
) && strcmp(last_elem
->str2
, reqConfig
)) {
1925 ERROR("Required configuration is inconsistent : Project '%s' cannot have 2 "
1926 "different configuration '%s' '%s'",
1927 last_elem
->str1
, last_elem
->str2
, reqConfig
);
1928 result
= TPD_FAILED
;
1930 last_elem
= last_elem
->next
;
1932 // add string to last element if empty or create new last element and add it to that
1933 if (last_elem
->str1
&& !duplicate
) {
1934 if (strcmp(last_elem
->str1
, projectName
) || strcmp(last_elem
->str2
, reqConfig
)) {
1935 last_elem
->next
= (struct string2_list
*)Malloc(sizeof(struct string2_list
));
1936 last_elem
= last_elem
->next
;
1937 last_elem
->next
= NULL
;
1944 last_elem
->str1
= mcopystr(projectName
);
1945 last_elem
->str2
= mcopystr(reqConfig
);
1951 // Referenced projects
1953 XPathObject
subprojects(run_xpath(xpathCtx
,
1954 "/TITAN_Project_File_Information/ReferencedProjects/ReferencedProject/attribute::*"));
1955 xmlNodeSetPtr nodes
= subprojects
->nodesetval
;
1956 const char *name
= NULL
, *projectLocationURI
= NULL
;
1957 if (nodes
) for (int i
= 0; i
< nodes
->nodeNr
; ++i
) {
1958 // FIXME: this assumes every ReferencedProject has name and URI.
1959 // This is not necessarily so if the referenced project was closed
1960 // when the project was exported to TPD.
1961 // Luckily, the name from the closed project will be overwritten
1962 // by the name from the next ReferencedProject. However, if some pervert
1963 // changes the next ReferencedProject to have the projectLocationURI
1964 // as the first attribute, it will be joined to the name
1965 // of the previous, closed, ReferencedProject.
1966 if (!strcmp((const char*)nodes
->nodeTab
[i
]->name
, "name")) {
1967 name
= (const char*)nodes
->nodeTab
[i
]->children
->content
;
1969 else if (!strcmp((const char*)nodes
->nodeTab
[i
]->name
,"projectLocationURI")) {
1970 projectLocationURI
= (const char*)nodes
->nodeTab
[i
]->children
->content
;
1973 if (name
&& projectLocationURI
) { // collected both
1974 // see if there is a specified configuration for the project
1976 ProjectDescriptor
* projDesc
= projGenHelper
.getTargetOfProject(*p_project_name
);
1977 if (projDesc
) projDesc
->addToReferencedProjects(name
);
1979 const char *my_actcfg
= NULL
;
1981 char *my_args
[] = { NULL
};
1982 char **my_argv
= my_args
+ 0;
1984 boolean my_gflag
= *p_gflag
, my_aflag
= *p_aflag
, my_cflag
= *p_cflag
, // pass down
1985 my_Rflag
= *p_Rflag
, my_Pflag
= *p_Pflag
, my_Zflag
= *p_Zflag
, my_Hflag
= *p_Hflag
,
1986 my_sflag
= 0, my_Lflag
= 0, my_lflag
= 0, my_mflag
= 0, my_csflag
= 0,
1987 my_quflag
= 0, my_dsflag
= 0, my_dbflag
= 0, my_drflag
= 0,
1988 my_dtflag
= 0, my_dxflag
= 0, my_djflag
= 0, my_fxflag
= 0, my_doflag
= 0,
1989 my_gfflag
= 0, my_lnflag
= 0, my_isflag
= 0, my_asflag
= 0,
1990 my_swflag
= 0, my_Yflag
= 0, my_Mflag
= *p_Mflag
;
1992 char *my_ets
= NULL
;
1993 char *my_proj_name
= NULL
;
1994 autostring
abs_projectLocationURI(
1995 compose_path_name(abs_tpd_dir
, projectLocationURI
));
1997 char* sub_proj_abs_work_dir
= NULL
;
1999 tpd_result success
= process_tpd_internal((const char*)abs_projectLocationURI
,
2000 my_actcfg
, file_list_path
, &my_argc
, &my_argv
, &my_optind
, &my_ets
, &my_proj_name
,
2001 &my_gflag
, &my_sflag
, &my_cflag
, &my_aflag
, preprocess
, &my_Rflag
, &my_lflag
,
2002 &my_mflag
, &my_Pflag
, &my_Lflag
, recursive
, force_overwrite
, gen_only_top_level
, NULL
, &sub_proj_abs_work_dir
,
2003 sub_project_dirs
, program_name
, prj_graph_fp
, create_symlink_list
, ttcn3_prep_includes
, ttcn3_prep_defines
, ttcn3_prep_undefines
,
2004 prep_includes
, prep_defines
, prep_undefines
, &my_csflag
,
2005 &my_quflag
, &my_dsflag
, cxxcompiler
, optlevel
, optflags
, &my_dbflag
, &my_drflag
,
2006 &my_dtflag
, &my_dxflag
, &my_djflag
, &my_fxflag
, &my_doflag
,
2007 &my_gfflag
, &my_lnflag
, &my_isflag
, &my_asflag
, &my_swflag
, &my_Yflag
, &my_Mflag
,
2008 solspeclibs
, sol8speclibs
, linuxspeclibs
, freebsdspeclibs
, win32speclibs
,
2009 ttcn3prep
, linkerlibs
, additionalObjects
, linkerlibsearchp
, Vflag
, FALSE
, &my_Zflag
,
2010 &my_Hflag
, NULL
, NULL
, prefix_workdir
, run_command_list
, seen_tpd_files
, required_configs
, profiled_file_list
);
2012 autostring
sub_proj_abs_work_dir_as(sub_proj_abs_work_dir
); // ?!
2014 if (success
== TPD_SUCCESS
) {
2015 my_actcfg
= get_act_config(required_configs
, my_proj_name
);
2016 if (recursive
) { // call ttcn3_makefilegen on referenced project's tpd file
2017 // -r is not needed any more because top level process traverses all projects recursively
2018 expstring_t command
= mprintf("%s -cVD", program_name
);
2019 if (force_overwrite
) command
= mputc(command
, 'f');
2020 if (prefix_workdir
) command
= mputc(command
, 'W');
2021 if (*p_gflag
) command
= mputc(command
, 'g');
2022 if (*p_sflag
) command
= mputc(command
, 's');
2023 if (*p_aflag
) command
= mputc(command
, 'a');
2024 if (*p_Rflag
) command
= mputc(command
, 'R');
2025 if (*p_lflag
) command
= mputc(command
, 'l');
2026 if (*p_mflag
) command
= mputc(command
, 'm');
2027 if (*p_Zflag
) command
= mputc(command
, 'Z');
2028 if (*p_Hflag
) command
= mputc(command
, 'H');
2029 command
= mputstr(command
, " -t ");
2030 command
= mputstr(command
, (const char*)abs_projectLocationURI
);
2032 command
= mputstr(command
, " -b ");
2033 command
= mputstr(command
, my_actcfg
);
2036 autostring
sub_tpd_dir(get_dir_from_path((const char*)abs_projectLocationURI
));
2037 const char * sub_proj_effective_work_dir
= sub_proj_abs_work_dir
? sub_proj_abs_work_dir
: (const char*)sub_tpd_dir
;
2038 if (!gen_only_top_level
) {
2039 if (run_command_list
) {
2040 // go to last element
2041 struct string2_list
* last_elem
= run_command_list
;
2042 while (last_elem
->next
) last_elem
= last_elem
->next
;
2043 // add strings to last element if empty or create new last element and add it to that
2044 if (last_elem
->str1
|| last_elem
->str2
) {
2045 last_elem
->next
= (struct string2_list
*)Malloc(sizeof(struct string2_list
));
2046 last_elem
= last_elem
->next
;
2047 last_elem
->next
= NULL
;
2049 last_elem
->str1
= mcopystr(sub_proj_effective_work_dir
);
2050 last_elem
->str2
= command
;
2052 ERROR("Internal error: cannot add command to list");
2055 // add working dir to the end of list
2056 if (sub_project_dirs
) {
2057 // go to last element
2058 struct string_list
* last_elem
= sub_project_dirs
;
2059 while (last_elem
->next
) last_elem
= last_elem
->next
;
2060 // add string to last element if empty or create new last element and add it to that
2061 if (last_elem
->str
) {
2062 last_elem
->next
= (struct string_list
*)Malloc(sizeof(struct string_list
));
2063 last_elem
= last_elem
->next
;
2064 last_elem
->next
= NULL
;
2066 autostring
cwd_as(get_working_dir());
2067 last_elem
->str
= (*p_aflag
) ? mcopystr(sub_proj_effective_work_dir
) : get_relative_dir(sub_proj_effective_work_dir
, (const char*)cwd_as
);
2071 for (int z
= 0; z
< my_argc
; ++z
) {
2073 // central storage, keep in separate container
2074 base_files
.add(my_argv
[z
]); // string was allocated with new
2077 const cstring
tmp(my_argv
[z
]);
2078 if (!files
.has_key(tmp
)){
2079 files
.add(tmp
, my_argv
[z
]);
2086 Free(my_argv
); // free the array; we keep the pointers
2090 else if (success
== TPD_FAILED
) {
2091 ERROR("Failed to process %s", (const char*)abs_projectLocationURI
);
2092 result
= TPD_FAILED
;
2094 // else TPD_SKIPPED, keep quiet
2096 name
= projectLocationURI
= NULL
; // forget both
2098 } // next referenced project
2102 if (get_path_status(output_file
) == PS_DIRECTORY
) {
2103 // points to existing dir; use as-is
2105 else { // we assume it points to a file: not our problem
2110 // (argc - optind) is the number of non-option arguments (assumed to be files)
2111 // given on the command line.
2112 int new_argc
= local_argc
- local_optind
+ files
.size() + base_files
.size();
2113 char ** new_argv
= (char**)Malloc(sizeof(char*) * new_argc
);
2117 // First, copy the filenames gathered from the TPD
2119 // We symlink the files into the working directory
2120 // and pass only the filename to the makefile generator
2121 for (int nf
= files
.size(); n
< nf
; ++n
) {
2122 const char *fn
= files
.get_nth_elem(n
); // relativeURI to the TPD location
2123 autostring
dir_n (get_dir_from_path (fn
));
2124 autostring
file_n(get_file_from_path(fn
));
2125 autostring
rel_n (get_absolute_dir(dir_n
, abs_tpd_dir
));
2126 autostring
abs_n (compose_path_name(rel_n
, file_n
));
2128 if (local_argc
== 0) {
2129 // We are being invoked recursively, for a referenced TPD.
2130 // Do not symlink; just return absolute paths to the files.
2133 // compose with workdir
2134 new_argv
[n
] = compose_path_name(abs_workdir
, file_n
);
2136 // it's an absolute path, copy verbatim
2137 new_argv
[n
] = mcopystr(fn
); // fn will be destroyed, pass a copy
2140 else { // relative path
2142 // compose with workdir
2143 new_argv
[n
] = compose_path_name(abs_workdir
, file_n
);
2144 // Do not call file_n.extract() : the composed path will be returned,
2145 // its component will need to be deallocated here.
2148 // compose with tpd dir
2149 new_argv
[n
] = const_cast<char*>(abs_n
.extract());
2153 else { // we are processing the top-level TPD
2156 int fd
= open(abs_n
, O_RDONLY
);
2157 if (fd
>= 0) { // successfully opened
2160 file_n
= compose_path_name(output_file
, file_n
);
2162 //TODO ! compose with output_file
2163 // save into list: add symlink data to the end of list
2164 if (create_symlink_list
) {
2165 // go to last element
2166 struct string2_list
* last_elem
= create_symlink_list
;
2167 while (last_elem
->next
) last_elem
= last_elem
->next
;
2168 // add strings to last element if empty or create new last element and add it to that
2169 if (last_elem
->str1
) {
2170 last_elem
->next
= (struct string2_list
*)Malloc(sizeof(struct string2_list
));
2171 last_elem
= last_elem
->next
;
2172 last_elem
->next
= NULL
;
2174 last_elem
->str1
= mcopystr(abs_n
);
2175 last_elem
->str2
= mcopystr(file_n
);
2179 ERROR("%s does not exist", (const char*)abs_n
);
2185 puts((const char *)abs_n
);
2187 autostring
dir_part(get_dir_from_path(abs_n
));
2188 autostring
file_part(get_file_from_path(abs_n
));
2189 autostring
rel_dir_part(get_relative_dir((const char *)dir_part
, file_list_path
? file_list_path
: (const char *)abs_tpd_dir
));
2190 autostring
rel_dir_file_part(compose_path_name((const char *)rel_dir_part
, (const char *)file_part
));
2191 puts((const char *)rel_dir_file_part
);
2194 new_argv
[n
] = const_cast<char *>(file_n
.extract());
2197 // Print the TPD too.
2199 autostring
dir_part(get_dir_from_path(p_tpd_name
));
2200 autostring
file_part(get_file_from_path(p_tpd_name
));
2202 puts((const char *)abs_tpd_name
);
2204 autostring
rel_dir_part(get_relative_dir(dir_part
, file_list_path
? file_list_path
: abs_tpd_dir
));
2205 autostring
rel_dir_file_part(compose_path_name(rel_dir_part
, file_part
));
2206 const char *rel_tpd_name
= (const char *)rel_dir_file_part
;
2211 // base_files from referenced projects
2212 for (size_t bf
= 0, bs
= base_files
.size(); bf
< bs
; ++bf
, ++n
) {
2213 new_argv
[n
] = base_files
[bf
];
2215 base_files
.clear(); // string ownership transfered
2217 // Then, copy the filenames from the command line.
2218 for (int a
= *p_optind
; a
< *p_argc
; ++a
, ++n
) {
2219 // String may be from main's argv; copy to the heap.
2220 new_argv
[n
] = mcopystr((*p_argv
)[a
]);
2223 if (local_argc
> 0) { // it is the outermost call
2224 clear_seen_tpd_files(seen_tpd_files
);
2232 for (size_t i
= 0, e
= files
.size(); i
< e
; ++i
) {
2233 Free(const_cast<char*>(files
.get_nth_elem(i
)));
2237 for (size_t i
= 0, e
= folders
.size(); i
< e
; ++i
) {
2238 Free(const_cast<char*>(folders
.get_nth_elem(i
)));
2242 excluded_files
.clear();
2243 excluded_folders
.clear();