added hostid function (artf724006)
[deliverable/titan.core.git] / compiler2 / xpather.cc
1 /******************************************************************************
2 * Copyright (c) 2000-2016 Ericsson Telecom AB
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 *
10 * Baji, Laszlo
11 * Balasko, Jeno
12 * Baranyi, Botond
13 * Beres, Szabolcs
14 * Delic, Adam
15 * Kovacs, Ferenc
16 * Ormandi, Matyas
17 * Pandi, Krisztian
18 * Raduly, Csaba
19 * Szabados, Kristof
20 * Szabo, Bence Janos
21 * Pandi, Krisztian
22 *
23 ******************************************************************************/
24 #include "xpather.h"
25
26 #include <string.h>
27 #include <assert.h>
28 #include <unistd.h>
29 #include <limits.h>
30 #include <errno.h>
31 #include <sys/stat.h>
32 #include <sys/types.h>
33 #include <fcntl.h>
34 #include <string>
35
36 #include <libxml/parser.h>
37 #include <libxml/tree.h>
38 #include <libxml/xpath.h>
39
40 #define LIBXML_SCHEMAS_ENABLED
41 #include <libxml/xmlschemastypes.h>
42
43 #include "../common/memory.h"
44 #include "vector.hh"
45 // Do _NOT_ #include "string.hh", it drags in ustring.o, common/Quadruple.o,
46 // Int.o, ttcn3/PatternString.o, and then the entire AST :(
47 #include "map.hh"
48 #include "ProjectGenHelper.hh"
49 #include "../common/path.h"
50 #include "ttcn3/ttcn3_preparser.h"
51 #include "asn1/asn1_preparser.h"
52
53 // in makefile.c
54 void ERROR (const char *fmt, ...);
55 void WARNING(const char *fmt, ...);
56 void NOTIFY (const char *fmt, ...);
57 void DEBUG (const char *fmt, ...);
58
59 // for vector and map
60 void fatal_error(const char * filename, int lineno, const char * fmt, ...)
61 __attribute__ ((__format__ (__printf__, 3, 4), __noreturn__));
62
63 void fatal_error(const char * filename, int lineno, const char * fmt, ...)
64 {
65 fputs(filename, stderr);
66 fprintf(stderr, ":%d: ", lineno);
67 va_list va;
68 va_start(va, fmt);
69 vfprintf(stderr, fmt, va);
70 va_end(va);
71 abort();
72 }
73
74 ProjectGenHelper& projGenHelper = ProjectGenHelper::Instance();
75
76 /// Run an XPath query and return an xmlXPathObjectPtr, which must be freed
77 xmlXPathObjectPtr run_xpath(xmlXPathContextPtr xpathCtx, const char *xpathExpr)
78 {
79 xmlXPathObjectPtr xpathObj = xmlXPathEvalExpression(
80 (const xmlChar *)xpathExpr, xpathCtx);
81 if(xpathObj == NULL) {
82 fprintf(stderr,"Error: unable to evaluate xpath expression \"%s\"\n", xpathExpr);
83 return 0;
84 }
85
86 return xpathObj;
87 }
88
89 // RAII classes
90
91 class XmlDoc {
92 public:
93 explicit XmlDoc(xmlDocPtr p) : doc_(p) {}
94 ~XmlDoc() {
95 if (doc_ != NULL) xmlFreeDoc(doc_);
96 }
97 operator xmlDocPtr() const { return doc_; }
98 private:
99 xmlDocPtr doc_;
100 };
101
102 class XPathContext {
103 public:
104 explicit XPathContext(xmlXPathContextPtr c) : ctx_(c) {}
105 ~XPathContext() {
106 if (ctx_ != NULL) xmlXPathFreeContext(ctx_);
107 }
108 operator xmlXPathContextPtr() const { return ctx_; }
109 private:
110 xmlXPathContextPtr ctx_;
111 };
112
113 class XPathObject {
114 public:
115 explicit XPathObject(xmlXPathObjectPtr o) : xpo_(o) {}
116 ~XPathObject() {
117 if (xpo_ != NULL) xmlXPathFreeObject(xpo_);
118 }
119 operator xmlXPathObjectPtr() const { return xpo_; }
120 xmlXPathObjectPtr operator->() const { return xpo_; }
121 private:
122 xmlXPathObjectPtr xpo_;
123 };
124
125 //------------------------------------------------------------------
126 /// compare-by-content wrapper of a plain C string
127 struct cstring {
128 explicit cstring(const char *s) : str(s) {}
129 void destroy() const;
130 operator const char*() const { return str; }
131 protected:
132 const char *str;
133 friend boolean operator<(const cstring& l, const cstring& r);
134 friend boolean operator==(const cstring& l, const cstring& r);
135 };
136
137 void cstring::destroy() const {
138 Free(const_cast<char*>(str)); // assumes valid pointer or NULL
139 }
140
141 boolean operator<(const cstring& l, const cstring& r) {
142 return strcmp(l.str, r.str) < 0;
143 }
144
145 boolean operator==(const cstring& l, const cstring& r) {
146 return strcmp(l.str, r.str) == 0;
147 }
148
149 /// RAII for C string
150 struct autostring : public cstring {
151 /// Constructor; takes over ownership
152 explicit autostring(const char *s = 0) : cstring(s) {}
153 ~autostring() {
154 // He who can destroy a thing, controls that thing -- Paul Muad'Dib
155 Free(const_cast<char*>(str)); // assumes valid pointer or NULL
156 }
157 /// %Assignment; takes over ownership
158 const autostring& operator=(const char *s) {
159 Free(const_cast<char*>(str)); // assumes valid pointer or NULL
160 str = s;
161 return *this;
162 }
163 /// Relinquish ownership
164 const char *extract() {
165 const char *retval = str;
166 str = 0;
167 return retval;
168 }
169 private:
170 autostring(const autostring&);
171 autostring& operator=(const autostring&);
172 };
173
174
175 bool validate_tpd(const XmlDoc& xml_doc, const char* tpd_file_name, const char* xsd_file_name)
176 {
177 xmlLineNumbersDefault(1);
178
179 xmlSchemaParserCtxtPtr ctxt = xmlSchemaNewParserCtxt(xsd_file_name);
180 if (ctxt==NULL) {
181 ERROR("Unable to create xsd context for xsd file `%s'", xsd_file_name);
182 return false;
183 }
184 xmlSchemaSetParserErrors(ctxt, (xmlSchemaValidityErrorFunc)fprintf, (xmlSchemaValidityWarningFunc)fprintf, stderr);
185
186 xmlSchemaPtr schema = xmlSchemaParse(ctxt);
187 if (schema==NULL) {
188 ERROR("Unable to parse xsd file `%s'", xsd_file_name);
189 xmlSchemaFreeParserCtxt(ctxt);
190 return false;
191 }
192
193 xmlSchemaValidCtxtPtr xsd = xmlSchemaNewValidCtxt(schema);
194 if (xsd==NULL) {
195 ERROR("Schema validation error for xsd file `%s'", xsd_file_name);
196 xmlSchemaFree(schema);
197 xmlSchemaFreeParserCtxt(ctxt);
198 return false;
199 }
200 xmlSchemaSetValidErrors(xsd, (xmlSchemaValidityErrorFunc) fprintf, (xmlSchemaValidityWarningFunc) fprintf, stderr);
201
202 int ret = xmlSchemaValidateDoc(xsd, xml_doc);
203
204 xmlSchemaFreeValidCtxt(xsd);
205 xmlSchemaFree(schema);
206 xmlSchemaFreeParserCtxt(ctxt);
207 xmlSchemaCleanupTypes();
208
209 if (ret==0) {
210 return true; // successful validation
211 } else if (ret>0) {
212 ERROR("TPD file `%s' is invalid according to schema `%s'", tpd_file_name, xsd_file_name);
213 return false;
214 } else {
215 ERROR("TPD validation of `%s' generated an internal error in libxml2", tpd_file_name);
216 return false;
217 }
218 }
219
220 /** Extract a boolean value from the XML, if it exists otherwise flag is unchanged
221 *
222 * @param xpathCtx XPath context object
223 * @param actcfg name of the active configuration
224 * @param option name of the value
225 * @param flag pointer to the variable to receive the value
226 */
227 void xsdbool2boolean(const XPathContext& xpathCtx, const char *actcfg,
228 const char *option, boolean* flag)
229 {
230 char *xpath = mprintf(
231 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
232 "/ProjectProperties/MakefileSettings/%s[text()='true']",
233 actcfg, option);
234 XPathObject xpathObj(run_xpath(xpathCtx, xpath));
235 Free(xpath);
236
237 if (xpathObj->nodesetval && xpathObj->nodesetval->nodeNr > 0) {
238 *flag = TRUE;
239 }
240 }
241
242 extern "C" string_list* getExternalLibs(const char* projName)
243 {
244 if (!projGenHelper.getZflag()) return NULL;
245 ProjectDescriptor* proj = projGenHelper.getTargetOfProject(projName);
246 if (!proj) return NULL;
247
248 std::vector<const char*> externalLibs;
249 projGenHelper.getExternalLibs(externalLibs);
250
251 if (0 == externalLibs.size()) return NULL;
252
253 struct string_list* head = (struct string_list*)Malloc(sizeof(struct string_list));
254 struct string_list* last_elem = head;
255 struct string_list* tail = head;
256
257 for (size_t i = 0; i < externalLibs.size(); ++i) {
258 tail = last_elem;
259 last_elem->str = mcopystr(externalLibs[i]);
260 last_elem->next = (struct string_list*)Malloc(sizeof(struct string_list));
261 last_elem = last_elem->next;
262 }
263 Free(last_elem);
264 tail->next = NULL;
265 return head;
266 }
267
268 extern "C" string_list* getExternalLibPaths(const char* projName)
269 {
270 if (!projGenHelper.getZflag()) return NULL;
271 ProjectDescriptor* proj = projGenHelper.getTargetOfProject(projName);
272 if (!proj) return NULL;
273
274 std::vector<const char*> externalLibs;
275 projGenHelper.getExternalLibSearchPaths(externalLibs);
276
277 if (0 == externalLibs.size()) return NULL;
278
279 struct string_list* head = (struct string_list*)Malloc(sizeof(struct string_list));
280 struct string_list* last_elem = head;
281 struct string_list* tail = head;
282
283 for (size_t i = 0; i < externalLibs.size(); ++i) {
284 tail = last_elem;
285 last_elem->str = mcopystr(externalLibs[i]);
286 last_elem->next = (struct string_list*)Malloc(sizeof(struct string_list));
287 last_elem = last_elem->next;
288 }
289 Free(last_elem);
290 tail->next = NULL;
291 return head;
292 }
293
294 extern "C" string_list* getRefWorkingDirs(const char* projName)
295 {
296 if (!projGenHelper.getZflag()) return NULL;
297 ProjectDescriptor* proj = projGenHelper.getTargetOfProject(projName);
298 if (!proj) FATAL_ERROR("Project \"%s\" was not found in the project list", projName);
299
300 struct string_list* head = (struct string_list*)Malloc(sizeof(struct string_list));
301 struct string_list* last_elem = head;
302 struct string_list* tail = head;
303 last_elem->str = NULL;
304 last_elem->next = NULL;
305 for (size_t i = 0; i < proj->numOfRefProjWorkingDirs(); ++i) {
306 tail = last_elem;
307 last_elem->str = mcopystr(proj->getRefProjWorkingDir(i).c_str());
308 last_elem->next = (struct string_list*)Malloc(sizeof(struct string_list));
309 last_elem = last_elem->next;
310 }
311 Free(last_elem);
312 tail->next = NULL;
313 return head;
314 }
315
316 extern "C" string2_list* getLinkerLibs(const char* projName)
317 {
318
319 if (!projGenHelper.getZflag()) return NULL;
320 if (1 == projGenHelper.numOfProjects() || 0 == projGenHelper.numOfLibs()){
321 return NULL; //no library
322 }
323 ProjectDescriptor* projLib = projGenHelper.getTargetOfProject(projName);
324 if (!projLib) FATAL_ERROR("Project \"%s\" was not found in the project list", projName);
325
326 struct string2_list* head = (struct string2_list*)Malloc(sizeof(struct string2_list));
327 struct string2_list* last_elem = head;
328 struct string2_list* tail = head;
329 last_elem->next = NULL;
330 last_elem->str1 = NULL;
331 last_elem->str2 = NULL;
332 for (std::map<std::string, ProjectDescriptor>::const_iterator it = projGenHelper.getHead();
333 it != projGenHelper.getEnd(); ++it) {
334 if ((it->second).isLibrary()) {
335 if (!(it->second).getLinkingStrategy() &&
336 !projLib->hasLinkerLibTo((it->second).getProjectName())) { // static linked library
337 continue;
338 }
339 std::string relPath = projLib->setRelativePathTo((it->second).getProjectAbsWorkingDir());
340 if (relPath == std::string(".")) {
341 continue; // the relpath shows to itself
342 }
343 tail = last_elem;
344 last_elem->str1 = mcopystr(relPath.c_str());
345 last_elem->str2 = mcopystr((it->second).getTargetExecName().c_str());
346 last_elem->next = (struct string2_list*)Malloc(sizeof(struct string2_list));
347 last_elem = last_elem->next;
348 }
349 }
350 tail->next = NULL;
351 Free(last_elem);
352
353 if (head->str1 && head->str2)
354 return head;
355 else
356 return NULL;
357 }
358
359 extern "C" const char* getLibFromProject(const char* projName)
360 {
361 if (!projGenHelper.getZflag()) return NULL;
362 ProjectDescriptor* lib = projGenHelper.getTargetOfProject(projName);
363 if (lib) return lib->getTargetExecName().c_str();
364 return NULL;
365 }
366
367 extern "C" void erase_libs() {
368 projGenHelper.cleanUp();
369 }
370
371 extern "C" void print_libs() {
372 projGenHelper.print();
373 }
374
375
376 extern "C" boolean hasSubProject(const char* projName) {
377 if (!projGenHelper.getZflag()) return FALSE;
378 if (projGenHelper.getHflag())
379 return static_cast<boolean>(projGenHelper.hasReferencedProject());
380 else if(std::string(projName) == projGenHelper.getToplevelProjectName())
381 return static_cast<boolean>(projGenHelper.hasReferencedProject());
382 else
383 return FALSE;
384 }
385
386 extern "C" boolean hasExternalLibrary(const char* libName, const char* projName) {
387 if (!projGenHelper.getZflag()) return FALSE;
388 ProjectDescriptor* projLib = projGenHelper.getTargetOfProject(projName);
389 if (projLib && projLib->hasLinkerLib(libName))
390 return TRUE;
391 else
392 return FALSE;
393 }
394
395 extern "C" boolean isTopLevelExecutable(const char* projName) {
396 if (!projGenHelper.getZflag()) return false;
397 ProjectDescriptor* proj = projGenHelper.getTargetOfProject(projName);
398 if (projGenHelper.getToplevelProjectName() != std::string(projName)) return FALSE;
399 if (proj && proj->isLibrary())
400 return FALSE;
401 else
402 return TRUE;
403 }
404
405 extern "C" boolean isDynamicLibrary(const char* key) {
406 if (!projGenHelper.getZflag()) return false;
407 ProjectDescriptor* proj = projGenHelper.getProjectDescriptor(key);
408 if (proj) return proj->getLinkingStrategy();
409 FATAL_ERROR("Library \"%s\" was not found", key);
410 return false;
411 }
412
413 extern "C" const char* getTPDFileName(const char* projName) {
414 if (!projGenHelper.getZflag()) return NULL;
415 ProjectDescriptor* proj = projGenHelper.getTargetOfProject(projName);
416 if (proj) return proj->getTPDFileName().c_str();
417 FATAL_ERROR("TPD file name to project \"%s\" was not found", projName);
418 }
419
420 extern "C" const char* getPathToRootDir(const char* projName) {
421 if (!projGenHelper.getZflag()) return NULL;
422 ProjectDescriptor* proj = projGenHelper.getTargetOfProject(projName);
423 const char* rootDir = projGenHelper.getRootDirOS(projName).c_str();
424 if (proj && rootDir) {
425 return rootDir;
426 }
427 FATAL_ERROR("Project \"%s\": no relative path was found to top directory at OS level.", projName);
428 }
429
430 extern "C" const char* findLibraryPath(const char* libraryName, const char* projName)
431 {
432 if (!projGenHelper.getZflag()) return NULL;
433 ProjectDescriptor* projLib = projGenHelper.getTargetOfProject(projName);
434 if (!projLib) FATAL_ERROR("Project \"%s\" was not found in the project list", projName);
435 ProjectDescriptor* libLib = projGenHelper.getProjectDescriptor(libraryName);
436 if (!libLib) return NULL;
437 std::string str = projLib->setRelativePathTo(libLib->getProjectAbsWorkingDir());
438 size_t refIndex = projLib->getLibSearchPathIndex(libLib->getProjectName());
439 if (refIndex > projLib->numOfLibSearchPaths()) return NULL;
440 projLib->setLibSearchPath(refIndex, str);
441 return projLib->getLibSearchPath(libLib->getProjectName());
442 }
443
444 extern "C" const char* findLibraryName(const char* libraryName, const char* projName)
445 {
446 if (!projGenHelper.getZflag()) return NULL;
447 ProjectDescriptor* projLib = projGenHelper.getTargetOfProject(projName);
448 if (!projLib) FATAL_ERROR("Project \"%s\" was not found in the project list", projName);
449 ProjectDescriptor* libLib = projGenHelper.getProjectDescriptor(libraryName);
450 if (!libLib) return NULL;
451 for (size_t i = 0; i < projLib->numOfReferencedProjects(); ++i) {
452 const std:: string refProjName = projLib->getReferencedProject(i);
453 ProjectDescriptor* refLib = projGenHelper.getTargetOfProject(refProjName.c_str());
454 if (refLib->getTargetExecName() == std::string(libraryName))
455 return libraryName;
456 }
457 return NULL;
458 }
459
460 extern "C" boolean isTtcn3ModuleInLibrary(const char* moduleName)
461 {
462 if (!projGenHelper.getZflag()) return FALSE;
463 return (boolean)projGenHelper.isTtcn3ModuleInLibrary(moduleName);
464 }
465
466 extern "C" boolean isAsn1ModuleInLibrary(const char* moduleName)
467 {
468 if (!projGenHelper.getZflag()) return FALSE;
469 return (boolean)projGenHelper.isAsn1ModuleInLibrary(moduleName);
470 }
471
472 extern "C" boolean isSourceFileInLibrary(const char* fileName)
473 {
474 if (!projGenHelper.getZflag()) return FALSE;
475 return (boolean)projGenHelper.isSourceFileInLibrary(fileName);
476 }
477
478 extern "C" boolean isHeaderFileInLibrary(const char* fileName)
479 {
480 if (!projGenHelper.getZflag()) return FALSE;
481 return (boolean)projGenHelper.isHeaderFileInLibrary(fileName);
482 }
483
484 extern "C" boolean isTtcnPPFileInLibrary(const char* fileName)
485 {
486 if (!projGenHelper.getZflag()) return FALSE;
487 return (boolean)projGenHelper.isTtcnPPFileInLibrary(fileName);
488 }
489
490
491 extern "C" boolean buildObjects(const char* projName, boolean add_referenced)
492 {
493 if (!projGenHelper.getZflag()) return FALSE;
494 if (projGenHelper.getHflag()) return FALSE;
495 if (add_referenced) return FALSE;
496 ProjectDescriptor* desc =projGenHelper.getTargetOfProject(projName);
497 if (desc && desc->isLibrary()) return FALSE;
498 return TRUE;
499 }
500
501 void append_to_library_list (const char* prjName,
502 const XPathContext& xpathCtx,
503 const char *actcfg)
504 {
505 if (!projGenHelper.getZflag()) return;
506
507 char *exeXpath = mprintf(
508 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
509 "/ProjectProperties/MakefileSettings/targetExecutable/text()",
510 actcfg);
511 XPathObject exeObj(run_xpath(xpathCtx, exeXpath));
512 Free(exeXpath);
513 std::string lib_name;
514 if (exeObj->nodesetval && exeObj->nodesetval->nodeNr > 0) {
515 const char* target_executable = (const char*)exeObj->nodesetval->nodeTab[0]->content;
516 autostring target_exe_dir(get_dir_from_path(target_executable));
517 autostring target_exe_file(get_file_from_path(target_executable));
518 lib_name = target_exe_file;
519 ProjectDescriptor* projDesc = projGenHelper.getTargetOfProject(prjName);
520 if (projDesc) {
521 projDesc->setTargetExecName(lib_name.c_str());
522 }
523 }
524 }
525
526 // data structures and functions to manage excluded folders/files
527
528 map<cstring, const char> excluded_files;
529
530 boolean is_excluded_file(const cstring& path, const char* project) {
531 if (!excluded_files.has_key(path)) return false;
532 const char* proj = excluded_files[path];
533 if (0 == strcmp(project, proj)) return true;
534 return false;
535 }
536
537 vector<const char> excluded_folders;
538
539 // Unfortunately, when "docs" is excluded, we need to drop
540 // files in "docs/", "docs/pdf/", "docs/txt/", "docs/txt/old/" etc;
541 // so it's not as simple as using a map :(
542
543 /** Checks whether a file is under an excluded folder
544 *
545 * @param path (relative) path of the file
546 * @return true if file is excluded, false otherwise
547 */
548 boolean is_excluded_folder(const char *path) {
549 boolean answer = FALSE;
550 size_t pathlen = strlen(path);
551
552 for (size_t i = 0, end = excluded_folders.size(); i < end; ++i) {
553 const char *xdir = excluded_folders[i];
554 size_t xdlen = strlen(xdir);
555 if (pathlen > xdlen && path[xdlen] == '/') {
556 // we may have a winner
557 if ((answer = !strncmp(path, xdir, xdlen))) break;
558 }
559 }
560 return answer;
561 }
562
563 // How do you treat a raw info? You cook it, of course!
564 // Returns a newly allocated string.
565 char *cook(const char *raw, const map<cstring, const char>& path_vars)
566 {
567 const char *slash = strchr(raw, '/');
568 if (!slash) { // Pretend that the slash is at the end of the string.
569 slash = raw + strlen(raw);
570 }
571
572 // Assume that a path variable reference is the first (or only) component
573 // of the path: ROOT in "ROOT/etc/issue".
574 autostring prefix(mcopystrn(raw, slash - raw));
575 if (path_vars.has_key(prefix)) {
576 char *cooked = mcopystr(path_vars[prefix]);
577 bool ends_with_slash = cooked[strlen(cooked)-1] == '/';
578 if (ends_with_slash && *slash == '/') {
579 // Avoid paths with two slashes at the start; Cygwin thinks it's UNC
580 ++slash;
581 }
582 // If there was no '/' (only the path variable reference e.g "ROOT")
583 // then slash points to a null byte and the mputstr is a no-op.
584 cooked = mputstr(cooked, slash);
585 return cooked;
586 }
587
588 // If the path variable could not be substituted,
589 // return (a copy of) the original.
590 return mcopystr(raw);
591 }
592
593 void replacechar(char** content) {
594
595 std::string s= *content;
596 size_t found = 0;
597 while ((found = s.find('['))!= std::string::npos){
598 s.replace(found,1, "${");
599 }
600 while ((found = s.find(']')) != std::string::npos){
601 s.replace(found,1, "}");
602 }
603 *content = mcopystr(s.c_str());
604 }
605
606 static void clear_seen_tpd_files(map<cstring, int>& seen_tpd_files) {
607 for (size_t i = 0, num = seen_tpd_files.size(); i < num; ++i) {
608 const cstring& key = seen_tpd_files.get_nth_key(i);
609 int *elem = seen_tpd_files.get_nth_elem(i);
610 key.destroy();
611 delete elem;
612 }
613 seen_tpd_files.clear();
614 }
615
616 const char* get_act_config(struct string2_list* cfg, const char* project_name) {
617 while (cfg && cfg->str1 && project_name) {
618 if (!strcmp(cfg->str1, project_name)) return cfg->str2;
619 cfg = cfg->next;
620 }
621 return NULL;
622 }
623
624 static tpd_result process_tpd_internal(const char *p_tpd_name, char* tpdName, const char *actcfg,
625 const char *file_list_path, int *p_argc, char ***p_argv,
626 int *p_optind, char **p_ets_name, char **p_project_name,
627 boolean *p_gflag, boolean *p_sflag, boolean *p_cflag, boolean *p_aflag, boolean *preprocess,
628 boolean *p_Rflag, boolean *p_lflag, boolean *p_mflag, boolean *p_Pflag,
629 boolean *p_Lflag, boolean recursive, boolean force_overwrite, boolean gen_only_top_level,
630 const char *output_file, char** abs_work_dir_p, struct string_list* sub_project_dirs,
631 const char* program_name, FILE* prj_graph_fp, struct string2_list* create_symlink_list, struct string_list* ttcn3_prep_includes,
632 struct string_list* ttcn3_prep_defines, struct string_list* ttcn3_prep_undefines, struct string_list* prep_includes,
633 struct string_list* prep_defines, struct string_list* prep_undefines, boolean *p_csflag, boolean *p_quflag, boolean* p_dsflag,
634 char** cxxcompiler, char** optlevel, char** optflags, boolean* p_dbflag, boolean* p_drflag, boolean* p_dtflag, boolean* p_dxflag,
635 boolean* p_djflag, boolean* p_fxflag, boolean* p_doflag, boolean* p_gfflag, boolean* p_lnflag, boolean* p_isflag,
636 boolean* p_asflag, boolean* p_swflag, boolean* p_Yflag, boolean* p_Mflag, boolean *p_Eflag, boolean* p_diflag, struct string_list* solspeclibs, struct string_list* sol8speclibs,
637 struct string_list* linuxspeclibs, struct string_list* freebsdspeclibs, struct string_list* win32speclibs, char** ttcn3prep,
638 struct string_list* linkerlibs, struct string_list* additionalObjects, struct string_list* linkerlibsearchp, boolean Vflag, boolean Dflag,
639 boolean *p_Zflag, boolean *p_Hflag, char** generatorCommandOutput, struct string2_list* target_placement_list, boolean prefix_workdir,
640 struct string2_list* run_command_list, map<cstring, int>& seen_tpd_files, struct string2_list* required_configs, struct string_list** profiled_file_list,
641 const char **search_paths, size_t n_search_paths);
642
643 extern "C" tpd_result process_tpd(const char *p_tpd_name, const char *actcfg,
644 const char *file_list_path, int *p_argc, char ***p_argv,
645 int *p_optind, char **p_ets_name, char **p_project_name,
646 boolean *p_gflag, boolean *p_sflag, boolean *p_cflag, boolean *p_aflag, boolean *preprocess,
647 boolean *p_Rflag, boolean *p_lflag, boolean *p_mflag, boolean *p_Pflag,
648 boolean *p_Lflag, boolean recursive, boolean force_overwrite, boolean gen_only_top_level,
649 const char *output_file, char** abs_work_dir_p, struct string_list* sub_project_dirs,
650 const char* program_name, FILE* prj_graph_fp, struct string2_list* create_symlink_list, struct string_list* ttcn3_prep_includes,
651 struct string_list* ttcn3_prep_defines, struct string_list* ttcn3_prep_undefines, struct string_list* prep_includes,
652 struct string_list* prep_defines, struct string_list* prep_undefines, boolean *p_csflag, boolean *p_quflag, boolean* p_dsflag,
653 char** cxxcompiler, char** optlevel, char** optflags, boolean* p_dbflag, boolean* p_drflag, boolean* p_dtflag, boolean* p_dxflag,
654 boolean* p_djflag, boolean* p_fxflag, boolean* p_doflag, boolean* p_gfflag, boolean* p_lnflag, boolean* p_isflag,
655 boolean* p_asflag, boolean* p_swflag, boolean* p_Yflag, boolean* p_Mflag, boolean* p_Eflag, boolean* p_diflag, struct string_list* solspeclibs, struct string_list* sol8speclibs,
656 struct string_list* linuxspeclibs, struct string_list* freebsdspeclibs, struct string_list* win32speclibs, char** ttcn3prep,
657 string_list* linkerlibs, string_list* additionalObjects, string_list* linkerlibsearchp, boolean Vflag, boolean Dflag, boolean *p_Zflag,
658 boolean *p_Hflag, char** generatorCommandOutput, struct string2_list* target_placement_list, boolean prefix_workdir,
659 struct string2_list* run_command_list, struct string2_list* required_configs, struct string_list** profiled_file_list,
660 const char **search_paths, size_t n_search_paths) {
661
662 map<cstring, int> seen_tpd_files;
663 char *tpdName = NULL;
664 projGenHelper.setZflag(*p_Zflag);
665 projGenHelper.setWflag(prefix_workdir);
666 projGenHelper.setHflag(*p_Hflag);
667 tpd_result success = process_tpd_internal(p_tpd_name, tpdName,
668 actcfg, file_list_path, p_argc, p_argv, p_optind, p_ets_name, p_project_name,
669 p_gflag, p_sflag, p_cflag, p_aflag, preprocess,
670 p_Rflag, p_lflag, p_mflag, p_Pflag,
671 p_Lflag, recursive, force_overwrite, gen_only_top_level,
672 output_file, abs_work_dir_p, sub_project_dirs,
673 program_name, prj_graph_fp, create_symlink_list, ttcn3_prep_includes,
674 ttcn3_prep_defines, ttcn3_prep_undefines, prep_includes, prep_defines,
675 prep_undefines, p_csflag, p_quflag, p_dsflag, cxxcompiler,
676 optlevel, optflags, p_dbflag, p_drflag, p_dtflag, p_dxflag, p_djflag,
677 p_fxflag, p_doflag, p_gfflag, p_lnflag, p_isflag,
678 p_asflag, p_swflag, p_Yflag, p_Mflag, p_Eflag, p_diflag, solspeclibs, sol8speclibs,
679 linuxspeclibs, freebsdspeclibs, win32speclibs, ttcn3prep,
680 linkerlibs, additionalObjects, linkerlibsearchp, Vflag, Dflag, p_Zflag,
681 p_Hflag, generatorCommandOutput, target_placement_list, prefix_workdir,
682 run_command_list, seen_tpd_files, required_configs, profiled_file_list,
683 search_paths, n_search_paths);
684
685 if (TPD_FAILED == success) exit(EXIT_FAILURE);
686
687 if (false == projGenHelper.sanityCheck()) {
688 fprintf (stderr, "makefilegen exits\n");
689 exit(EXIT_FAILURE);
690 }
691
692 projGenHelper.generateRefProjectWorkingDirsTo(*p_project_name);
693
694 for (size_t i = 0, num = seen_tpd_files.size(); i < num; ++i) {
695 const cstring& key = seen_tpd_files.get_nth_key(i);
696 int *elem = seen_tpd_files.get_nth_elem(i);
697 key.destroy();
698 delete elem;
699 }
700 seen_tpd_files.clear();
701
702 return success;
703 }
704
705 // optind is the index of the next element of argv to be processed.
706 // Return TPD_SUCESS if parsing successful, TPD_SKIPPED if the tpd was
707 // seen already, or TPD_FAILED.
708 //
709 // Note: if process_tpd() returns TPD_SUCCESS, it is expected that all strings
710 // (argv[], ets_name, other_files[], output_file) are allocated on the heap
711 // and need to be freed. On input, these strings point into argv.
712 // process_tpd() may alter these strings; new values will be on the heap.
713 // If process_tpd() preserves the content of such a string (e.g. ets_name),
714 // it must nevertheless make a copy on the heap via mcopystr().
715 static tpd_result process_tpd_internal(const char *p_tpd_name, char *tpdName, const char *actcfg,
716 const char *file_list_path, int *p_argc, char ***p_argv,
717 int *p_optind, char **p_ets_name, char **p_project_name,
718 boolean *p_gflag, boolean *p_sflag, boolean *p_cflag, boolean *p_aflag, boolean *preprocess,
719 boolean *p_Rflag, boolean *p_lflag, boolean *p_mflag, boolean *p_Pflag,
720 boolean *p_Lflag, boolean recursive, boolean force_overwrite, boolean gen_only_top_level,
721 const char *output_file, char** abs_work_dir_p, struct string_list* sub_project_dirs,
722 const char* program_name, FILE* prj_graph_fp, struct string2_list* create_symlink_list, struct string_list* ttcn3_prep_includes,
723 struct string_list* ttcn3_prep_defines, struct string_list* ttcn3_prep_undefines, struct string_list* prep_includes,
724 struct string_list* prep_defines, struct string_list* prep_undefines, boolean *p_csflag, boolean *p_quflag, boolean* p_dsflag,
725 char** cxxcompiler, char** optlevel, char** optflags, boolean* p_dbflag, boolean* p_drflag, boolean* p_dtflag, boolean* p_dxflag,
726 boolean* p_djflag, boolean* p_fxflag, boolean* p_doflag, boolean* p_gfflag, boolean* p_lnflag, boolean* p_isflag,
727 boolean* p_asflag, boolean* p_swflag, boolean* p_Yflag, boolean* p_Mflag, boolean* p_Eflag, boolean* p_diflag, struct string_list* solspeclibs, struct string_list* sol8speclibs,
728 struct string_list* linuxspeclibs, struct string_list* freebsdspeclibs, struct string_list* win32speclibs, char** ttcn3prep,
729 string_list* linkerlibs, string_list* additionalObjects, string_list* linkerlibsearchp, boolean Vflag, boolean Dflag, boolean *p_Zflag,
730 boolean *p_Hflag, char** generatorCommandOutput, struct string2_list* target_placement_list, boolean prefix_workdir,
731 struct string2_list* run_command_list, map<cstring, int>& seen_tpd_files, struct string2_list* required_configs, struct string_list** profiled_file_list,
732 const char **search_paths, size_t n_search_paths)
733 {
734 tpd_result result = TPD_SUCCESS;
735 // read-only non-pointer aliases
736 //char** const& local_argv = *p_argv;
737 int const& local_argc = *p_argc;
738 int const& local_optind = *p_optind;
739 *abs_work_dir_p = NULL;
740
741 assert(local_optind >= 2 // at least '-ttpd_name' must be in the args
742 || local_optind == 0); // if called for a referenced project
743
744 assert(local_argc >= local_optind);
745
746 autostring tpd_dir(get_dir_from_path(p_tpd_name));
747 autostring abs_tpd_dir(get_absolute_dir(tpd_dir, NULL, FALSE));
748 boolean free_name = FALSE;
749 struct stat buf;
750 //Only referenced project, when first try is failed, and when not absolute path
751 if(0 == local_optind && p_tpd_name != NULL && stat(p_tpd_name, &buf) && tpdName != NULL) {
752 //Find the first search_path that has the tpd
753 for(size_t i = 0; i<n_search_paths; i++) {
754 boolean need_slash = search_paths[i][strlen(search_paths[i]) - 1] != '/';
755 NOTIFY("Cannot find %s, trying with %s%s%s\n", p_tpd_name, search_paths[i], need_slash ? "/" : "", tpdName);
756 //Create path
757 char * prefixed_file_path = (char*)Malloc((strlen(search_paths[i]) + strlen(tpdName) + 1 + need_slash) * sizeof(char));
758 strcpy(prefixed_file_path, search_paths[i]);
759 if(need_slash) {
760 strcat(prefixed_file_path, "/");
761 }
762 strcat(prefixed_file_path, tpdName);
763
764 tpd_dir = get_dir_from_path(prefixed_file_path);
765 abs_tpd_dir = get_absolute_dir(tpd_dir, NULL, FALSE);
766
767 if(!stat(prefixed_file_path, &buf)){
768 //Ok, tpd found
769 p_tpd_name = prefixed_file_path;
770 free_name = TRUE;
771 NOTIFY("TPD with name %s found at %s.", tpdName, search_paths[i]);
772 break;
773 }else {
774 //tpd not found, continue search
775 abs_tpd_dir = NULL;
776 Free(prefixed_file_path);
777 }
778 }
779 //Error if tpd is not found in either search paths
780 if(NULL == (const char*)abs_tpd_dir) {
781 //Only write out the name in the error message (without .tpd)
782 tpdName[strlen(tpdName)-4] ='\0';
783 ERROR("Unable to find ReferencedProject with name: %s", (const char*)tpdName);
784 return TPD_FAILED;
785 }
786 }
787
788 if (NULL == (const char*)abs_tpd_dir) {
789 ERROR("absolute TPD directory could not be retrieved from %s", (const char*)tpd_dir);
790 return TPD_FAILED;
791 }
792 autostring tpd_filename(get_file_from_path(p_tpd_name));
793 autostring abs_tpd_name(compose_path_name(abs_tpd_dir, tpd_filename));
794
795 if (seen_tpd_files.has_key(abs_tpd_name)) {
796 ++*seen_tpd_files[abs_tpd_name];
797 return TPD_SKIPPED; // nothing to do
798 }
799 else {
800 if (recursive && !prefix_workdir) {
801 // check that this tpd file is not inside a directory of another tpd file
802 for (size_t i = 0; i < seen_tpd_files.size(); ++i) {
803 const cstring& other_tpd_name = seen_tpd_files.get_nth_key(i);
804 autostring other_tpd_dir(get_dir_from_path((const char*)other_tpd_name));
805 if (strcmp((const char*)abs_tpd_dir,(const char*)other_tpd_dir)==0) {
806 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);
807 return TPD_FAILED;
808 }
809 }
810 }
811 // mcopystr makes another copy for the map
812 seen_tpd_files.add(cstring(mcopystr(abs_tpd_name)), new int(1));
813 }
814
815 vector<char> base_files; // values Malloc'd but we pass them to the caller
816
817 XmlDoc doc(xmlParseFile(p_tpd_name));
818 if (doc == NULL) {
819 fprintf(stderr, "Error: unable to parse file \"%s\"\n", p_tpd_name);
820 return TPD_FAILED;
821 }
822
823 if (!Vflag) {
824 // try schema validation if tpd schema file was found
825 bool tpd_is_valid = false;
826 const char* ttcn3_dir = getenv("TTCN3_DIR");
827 if (ttcn3_dir) {
828 size_t ttcn3_dir_len = strlen(ttcn3_dir);
829 bool ends_with_slash = (ttcn3_dir_len>0) && (ttcn3_dir[ttcn3_dir_len - 1]=='/');
830 expstring_t xsd_file_name = mprintf("%s%setc/xsd/TPD.xsd", ttcn3_dir, ends_with_slash?"":"/");
831 autostring xsd_file_name_as(xsd_file_name);
832 if (get_path_status(xsd_file_name)==PS_FILE) {
833 if (validate_tpd(doc, p_tpd_name, xsd_file_name)) {
834 tpd_is_valid = true;
835 NOTIFY("TPD file `%s' validated successfully with schema file `%s'", p_tpd_name, xsd_file_name);
836 }
837 } else {
838 ERROR("Cannot find XSD for schema for validation of TPD on path `%s'", xsd_file_name);
839 }
840 } else {
841 ERROR("Environment variable TTCN3_DIR not present, cannot find XSD for schema validation of TPD");
842 }
843 if (!tpd_is_valid) {
844 return TPD_FAILED;
845 }
846 }
847
848 // Source files.
849 // Key is projectRelativePath, value is relativeURI or rawURI.
850 map<cstring, const char> files; // values Malloc'd
851 map<cstring, const char> folders; // values Malloc'd
852 // NOTE! files and folders must be local variables of process_tpd.
853 // This is because the keys (not the values) are owned by the XmlDoc.
854
855 map<cstring, const char> path_vars;
856
857 XPathContext xpathCtx(xmlXPathNewContext(doc));
858 if (xpathCtx == NULL) {
859 fprintf(stderr,"Error: unable to create new XPath context\n");
860 return TPD_FAILED;
861 }
862 // Collect path variables
863 {
864 XPathObject pathsObj(run_xpath(xpathCtx,
865 "/TITAN_Project_File_Information/PathVariables/PathVariable"));
866 xmlNodeSetPtr nodes = pathsObj->nodesetval;
867
868 const char *name = 0, *value = 0;
869 if (nodes) for (int i = 0; i < nodes->nodeNr; ++i) {
870 // nodes->nodeTab[i]->name === "PathVariable"
871 for (xmlAttrPtr attr = nodes->nodeTab[i]->properties; attr; attr = attr->next) {
872 if (!strcmp((const char*)attr->name, "name")) {
873 name = (const char*)attr->children->content;
874 }
875 else if (!strcmp((const char*)attr->name, "value")) {
876 value = (const char*)attr->children->content;
877 }
878 else {
879 WARNING("Unknown attribute %s", (const char*)nodes->nodeTab[i]->name);
880 }
881 } // next attribute
882
883 if (name && value) path_vars.add(cstring(name), value);
884 else ERROR("A PathVariable must have both name and value");
885 } // next PathVariable
886 }
887
888 // Collect folders
889 {
890 XPathObject foldersObj(run_xpath(xpathCtx,
891 "/TITAN_Project_File_Information/Folders/FolderResource"));
892
893 xmlNodeSetPtr nodes = foldersObj->nodesetval;
894 if (nodes) for (int i = 0; i < nodes->nodeNr; ++i) {
895 // nodes->nodeTab[i]->name === "FolderResource"
896 const char *uri = 0, *path = 0, *raw = 0;
897
898 // projectRelativePath is the path as it appears in Project Explorer (illusion)
899 // relativeURI is the actual location, relative to the project root (reality)
900 // rawURI is present if the relative path can not be calculated
901 //
902 // Theoretically these attributes could be in any order, loop over them
903 for (xmlAttrPtr attr = nodes->nodeTab[i]->properties; attr; attr = attr->next) {
904 if (!strcmp((const char*)attr->name, "projectRelativePath")) {
905 path = (const char*)attr->children->content;
906 }
907 else if (!strcmp((const char*)attr->name, "relativeURI")) {
908 uri = (const char*)attr->children->content;
909 }
910 else if (!strcmp((const char*)attr->name, "rawURI")) {
911 raw = (const char*)attr->children->content;
912 }
913 else {
914 WARNING("Unknown attribute %s", (const char*)nodes->nodeTab[i]->name);
915 }
916 } // next attribute
917
918 if (path == NULL) {
919 ERROR("A FolderResource must have a projectRelativePath");
920 continue;
921 }
922
923 if (uri == NULL && raw == NULL) {
924 ERROR("A FolderResource must have either relativeURI or rawURI");
925 continue;
926 }
927 // relativeURI wins over rawURI
928 folders.add(cstring(path), uri ? mcopystr(uri) : cook(raw, path_vars));
929 // TODO uri: cut "file:", complain on anything else
930 } // next FolderResource
931 }
932
933 /////////////////////////////////////////////////////////////////////////////
934 {
935 char *projectNameXpath = mprintf("/TITAN_Project_File_Information/ProjectName/text()");
936 XPathObject projectNameObj(run_xpath(xpathCtx, projectNameXpath));
937 Free(projectNameXpath);
938 if (projectNameObj->nodesetval && projectNameObj->nodesetval->nodeNr > 0) {
939 *p_project_name = mcopystr((const char*)projectNameObj->nodesetval->nodeTab[0]->content);
940 projGenHelper.addTarget(*p_project_name);
941 projGenHelper.setToplevelProjectName(*p_project_name);
942 ProjectDescriptor* projDesc = projGenHelper.getTargetOfProject(*p_project_name);
943 if (projDesc) projDesc->setProjectAbsTpdDir((const char*)abs_tpd_dir);
944 }
945 }
946 /////////////////////////////////////////////////////////////////////////////
947
948 if (!actcfg) {
949 actcfg = get_act_config(required_configs,*p_project_name);
950 }
951 if (actcfg == NULL) {
952 // Find out the active config
953 XPathObject activeConfig(run_xpath(xpathCtx,
954 "/TITAN_Project_File_Information/ActiveConfiguration/text()"));
955 if (activeConfig->nodesetval && activeConfig->nodesetval->nodeNr == 1) {
956 // there is one node
957 actcfg = (const char*)activeConfig->nodesetval->nodeTab[0]->content;
958 }
959 }
960
961 if (actcfg == NULL) {
962 ERROR("Can not find the active build configuration.");
963 for (size_t i = 0; i < folders.size(); ++i) {
964 Free(const_cast<char*>(folders.get_nth_elem(i)));
965 }
966 folders.clear();
967 return TPD_FAILED;
968 }
969
970 { // check if the active configuration exists
971 expstring_t xpathActCfg= mprintf(
972 "/TITAN_Project_File_Information/Configurations/"
973 "Configuration[@name='%s']/text()", actcfg);
974 XPathObject theConfigEx(run_xpath(xpathCtx, xpathActCfg));
975 Free(xpathActCfg);
976
977 xmlNodeSetPtr nodes = theConfigEx->nodesetval;
978 if (nodes == NULL) {
979 ERROR("The active build configuration named '%s' does not exist",
980 actcfg);
981 for (size_t i = 0; i < folders.size(); ++i) {
982 Free(const_cast<char*>(folders.get_nth_elem(i)));
983 }
984 folders.clear();
985 return TPD_FAILED;
986 }
987 }
988 // working directory stuff
989 autostring workdir;
990 {
991 const char* workdirFromTpd = "bin"; // default value
992 char *workdirXpath = mprintf(
993 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
994 "/ProjectProperties/LocalBuildSettings/workingDirectory/text()",
995 actcfg);
996 XPathObject workdirObj(run_xpath(xpathCtx, workdirXpath));
997 Free(workdirXpath);
998 if (workdirObj->nodesetval && workdirObj->nodesetval->nodeNr > 0) {
999 workdirFromTpd = (const char*)workdirObj->nodesetval->nodeTab[0]->content;
1000 }
1001 if (prefix_workdir) { // the working directory is: prjNameStr + "_" + workdirFromTpd
1002 const char* prjNameStr = "unnamedproject";
1003 XPathObject prjName(run_xpath(xpathCtx, "/TITAN_Project_File_Information/ProjectName/text()"));
1004 if (prjName->nodesetval && prjName->nodesetval->nodeNr == 1) {
1005 prjNameStr = (const char*)prjName->nodesetval->nodeTab[0]->content;
1006 }
1007 workdir = mprintf("%s_%s", prjNameStr, workdirFromTpd);
1008 } else {
1009 workdir = mcopystr(workdirFromTpd);
1010 }
1011 }
1012 if (!folders.has_key(workdir)) {
1013 // Maybe the tpd was saved with the option "No info about work dir"
1014 folders.add(workdir, mcopystr(workdir)); // fake it
1015 }
1016 const char *real_workdir = folders[workdir]; // This is relative to the location of the tpd file
1017 excluded_folders.add(real_workdir); // excluded by convention
1018
1019 autostring proj_abs_workdir;
1020
1021 autostring abs_workdir;
1022 // If -D flag was specified then we ignore the workdir
1023 // in the TPD (the current dir is considered the work dir).
1024 if (!Dflag) {
1025 bool hasWorkDir = false;
1026 // if the working directory does not exist create it
1027 autostring saved_work_dir(get_working_dir());
1028 if (set_working_dir(abs_tpd_dir)) {
1029 ERROR("Could not change to project directory `%s'", (const char*)abs_tpd_dir);
1030 } else {
1031 switch (get_path_status(real_workdir)) {
1032 case PS_FILE:
1033 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);
1034 break;
1035 case PS_DIRECTORY:
1036 // already exists
1037 hasWorkDir = true;
1038 break;
1039 default:
1040 if (recursive || local_argc != 0) { // we only want to create workdir if necessary
1041 fprintf(stderr, "Working directory `%s' in project `%s' does not exist, trying to create it...\n",
1042 real_workdir, (const char*)abs_tpd_dir);
1043 int rv = mkdir(real_workdir, 0755);
1044 if (rv) ERROR("Could not create working directory, mkdir() failed: %s", strerror(errno));
1045 else printf("Working directory created\n");
1046 hasWorkDir = true;
1047 }
1048 }
1049 }
1050
1051 if (local_argc==0) { // if not top level
1052 set_working_dir(saved_work_dir); // restore working directory
1053 } else { // if top level
1054 set_working_dir(real_workdir); // go into the working dir
1055 }
1056 if (hasWorkDir) { //we created working directory, or its already been created (from a parent makefilegen process maybe)
1057 *abs_work_dir_p = get_absolute_dir(real_workdir, abs_tpd_dir, TRUE);
1058 abs_workdir = (mcopystr(*abs_work_dir_p));
1059 proj_abs_workdir = mcopystr(*abs_work_dir_p);
1060 }
1061 }
1062
1063 if (Dflag) { // the path to subproject working dir is needed to find the linkerlibsearchpath
1064 proj_abs_workdir = compose_path_name(abs_tpd_dir, real_workdir);
1065 }
1066
1067 ProjectDescriptor* projDesc = projGenHelper.getTargetOfProject(*p_project_name);
1068 if (projDesc) {
1069 projDesc->setProjectAbsWorkingDir((const char*)proj_abs_workdir);
1070 projDesc->setProjectWorkingDir(real_workdir);
1071 projDesc->setTPDFileName(p_tpd_name);
1072 }
1073
1074 /////////////////////////////////////////////////////////////////////////////
1075
1076 // Gather the excluded folders in the active config
1077 {
1078 expstring_t xpathActCfgPaths = mprintf(
1079 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1080 "/FolderProperties/FolderResource/FolderProperties/ExcludeFromBuild[text()='true']"
1081 // This was the selection criterium, we need to go up and down for the actual information
1082 "/parent::*/parent::*/FolderPath/text()",
1083 actcfg);
1084 XPathObject theConfigEx(run_xpath(xpathCtx, xpathActCfgPaths));
1085 Free(xpathActCfgPaths);
1086
1087 xmlNodeSetPtr nodes = theConfigEx->nodesetval;
1088 if (nodes) for (int i = 0; i < nodes->nodeNr; ++i) {
1089
1090 excluded_folders.add((const char*)nodes->nodeTab[i]->content);
1091 }
1092 }
1093
1094 // Gather individual excluded files in the active config
1095 {
1096 expstring_t xpathActCfgPaths = mprintf(
1097 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1098 "/FileProperties/FileResource/FileProperties/ExcludeFromBuild[text()='true']"
1099 "/parent::*/parent::*/FilePath/text()",
1100 actcfg);
1101 XPathObject theConfigEx(run_xpath(xpathCtx, xpathActCfgPaths));
1102 Free(xpathActCfgPaths);
1103
1104 xmlNodeSetPtr nodes = theConfigEx->nodesetval;
1105 if (nodes) for (int i = 0; i < nodes->nodeNr; ++i) {
1106 xmlNodePtr curnode = nodes->nodeTab[i];
1107 cstring aa((const char*)curnode->content);
1108 if (!excluded_files.has_key(aa)) {
1109 excluded_files.add(aa, *p_project_name);
1110 } else {
1111 WARNING("Multiple exclusion of file %s", (const char*)curnode->content);
1112 }
1113 }
1114 }
1115
1116 // Collect files; filter out excluded ones
1117 {
1118 XPathObject filesObj(run_xpath(xpathCtx,
1119 "TITAN_Project_File_Information/Files/FileResource"));
1120
1121 xmlNodeSetPtr nodes = filesObj->nodesetval;
1122 if (nodes) for (int i = 0; i < nodes->nodeNr; ++i) {
1123 // nodes->nodeTab[i]->name === "FileResource"
1124 const char *uri = 0, *path = 0, *raw = 0;
1125
1126 // projectRelativePath is the path as it appears in Project Explorer (illusion)
1127 // relativeURI is the actual location, relative to the project root (reality)
1128 // rawURI is present if the relative path can not be calculated
1129 //
1130 // Theoretically these attributes could be in any order, loop over them
1131 for (xmlAttrPtr attr = nodes->nodeTab[i]->properties; attr; attr = attr->next) {
1132 if (!strcmp((const char*)attr->name, "projectRelativePath")) {
1133 path = (const char*)attr->children->content;
1134 }
1135 else if (!strcmp((const char*)attr->name, "relativeURI")) {
1136 uri = (const char*)attr->children->content;
1137 }
1138 else if (!strcmp((const char*)attr->name, "rawURI")) {
1139 raw = (const char*)attr->children->content;
1140 }
1141 else {
1142 WARNING("Unknown attribute %s", (const char*)nodes->nodeTab[i]->name);
1143 }
1144 } // next attribute
1145
1146 if (path == NULL) {
1147 ERROR("A FileResource must have a projectRelativePath");
1148 continue;
1149 }
1150
1151 if (uri == NULL && raw == NULL) {
1152 ERROR("A FileResource must have either relativeURI or rawURI");
1153 continue;
1154 }
1155
1156 cstring cpath(path);
1157 if (!is_excluded_file(cpath, *p_project_name) && !is_excluded_folder(path)) {
1158 // relativeURI wins over rawURI
1159 char *ruri = uri ? mcopystr(uri) : cook(raw, path_vars);
1160 if (files.has_key(cpath)) {
1161 ERROR("A FileResource %s must be unique!", (const char*)cpath);
1162 }
1163 else {
1164 bool drop = false;
1165 const char* file_path = ruri;
1166 expstring_t rel_file_dir = get_dir_from_path(file_path);
1167 expstring_t file_name = get_file_from_path(file_path);
1168 expstring_t abs_dir_path = get_absolute_dir(rel_file_dir, abs_tpd_dir, TRUE);
1169 expstring_t abs_file_name = compose_path_name(abs_dir_path, file_name);
1170 if (abs_file_name != NULL) {
1171 if (get_path_status(abs_file_name) == PS_FILE) {
1172 FILE *fp = fopen(abs_file_name, "r");
1173 if (fp != NULL) {
1174 char* ttcn3_module_name;
1175 if (is_ttcn3_module(abs_file_name, fp, &ttcn3_module_name)) {
1176 projGenHelper.addTtcn3ModuleToProject(*p_project_name, ttcn3_module_name);
1177 }
1178 Free(ttcn3_module_name);
1179 char* asn1_module_name;
1180 if (is_asn1_module(abs_file_name, fp, &asn1_module_name)) {
1181 projGenHelper.addAsn1ModuleToProject(*p_project_name, asn1_module_name);
1182 }
1183 Free(asn1_module_name);
1184 if (projGenHelper.isCPPSourceFile(file_name)) {
1185 projGenHelper.addUserSourceToProject(*p_project_name, file_name);
1186 }
1187 if (projGenHelper.isCPPHeaderFile(file_name)) {
1188 projGenHelper.addUserHeaderToProject(*p_project_name, file_name);
1189 }
1190 if (projGenHelper.isTtcnPPFile(file_name)) {
1191 projGenHelper.addTtcnPPToProject(*p_project_name, file_name);
1192 }
1193 }
1194 fclose(fp);
1195 }else {
1196 drop = true;
1197 ERROR("%s does not exist", abs_file_name);
1198 }
1199 }
1200 if(abs_dir_path != NULL && !drop){
1201 files.add(cpath, ruri); // relativeURI to the TPD location
1202 }else {
1203 cpath.destroy();
1204 result = TPD_FAILED;
1205 }
1206 { // set the *preprocess value if .ttcnpp file was found
1207 const size_t ttcnpp_extension_len = 7; // ".ttcnpp"
1208 const size_t ruri_len = strlen(ruri);
1209 if ( ruri_len>ttcnpp_extension_len && strcmp(ruri+(ruri_len-ttcnpp_extension_len),".ttcnpp")==0 ) {
1210 *preprocess = TRUE;
1211 }
1212 }
1213 Free(rel_file_dir);
1214 Free(file_name);
1215 Free(abs_dir_path);
1216 Free(abs_file_name);
1217 }
1218 }
1219 } // next FileResource
1220 }
1221
1222 // Check options
1223 xsdbool2boolean(xpathCtx, actcfg, "useAbsolutePath", p_aflag);
1224 xsdbool2boolean(xpathCtx, actcfg, "GNUMake", p_gflag);
1225 if (*p_Zflag) *p_lflag = FALSE;
1226 xsdbool2boolean(xpathCtx, actcfg, "dynamicLinking", p_lflag);
1227 xsdbool2boolean(xpathCtx, actcfg, "functiontestRuntime", p_Rflag);
1228 xsdbool2boolean(xpathCtx, actcfg, "singleMode", p_sflag);
1229 xsdbool2boolean(xpathCtx, actcfg, "codeSplitting", p_csflag);
1230 xsdbool2boolean(xpathCtx, actcfg, "quietly", p_quflag);
1231 xsdbool2boolean(xpathCtx, actcfg, "disableSubtypeChecking", p_dsflag);
1232 xsdbool2boolean(xpathCtx, actcfg, "disableBER", p_dbflag);
1233 xsdbool2boolean(xpathCtx, actcfg, "disableRAW", p_drflag);
1234 xsdbool2boolean(xpathCtx, actcfg, "disableTEXT", p_dtflag);
1235 xsdbool2boolean(xpathCtx, actcfg, "disableXER", p_dxflag);
1236 xsdbool2boolean(xpathCtx, actcfg, "disableJSON", p_djflag);
1237 xsdbool2boolean(xpathCtx, actcfg, "forceXERinASN.1", p_fxflag);
1238 xsdbool2boolean(xpathCtx, actcfg, "defaultasOmit", p_doflag);
1239 xsdbool2boolean(xpathCtx, actcfg, "gccMessageFormat", p_gfflag);
1240 xsdbool2boolean(xpathCtx, actcfg, "lineNumbersOnlyInMessages", p_lnflag);
1241 xsdbool2boolean(xpathCtx, actcfg, "includeSourceInfo", p_isflag);
1242 xsdbool2boolean(xpathCtx, actcfg, "addSourceLineInfo", p_asflag);
1243 xsdbool2boolean(xpathCtx, actcfg, "suppressWarnings", p_swflag);
1244 xsdbool2boolean(xpathCtx, actcfg, "outParamBoundness", p_Yflag); //not documented, obsolete
1245 xsdbool2boolean(xpathCtx, actcfg, "forceOldFuncOutParHandling", p_Yflag);
1246 xsdbool2boolean(xpathCtx, actcfg, "omitInValueList", p_Mflag);
1247 xsdbool2boolean(xpathCtx, actcfg, "warningsForBadVariants", p_Eflag);
1248 xsdbool2boolean(xpathCtx, actcfg, "disablePredefinedExternalFolder", p_diflag);
1249
1250 projDesc = projGenHelper.getTargetOfProject(*p_project_name);
1251 if (projDesc) projDesc->setLinkingStrategy(*p_lflag);
1252
1253 // Extract the "incremental dependencies" option
1254 {
1255 boolean incremental_deps = TRUE;
1256 xsdbool2boolean(xpathCtx, actcfg, "incrementalDependencyRefresh", &incremental_deps);
1257
1258 // For makefilegen, "Use GNU make" implies incremental deps by default,
1259 // unless explicitly disabled by "use makedepend" (a.k.a. mflag).
1260 // For Eclipse, incremental deps must be explicitly specified,
1261 // even if GNU make is being used.
1262
1263 if (incremental_deps) {
1264 if( !(*p_gflag) ) {
1265 WARNING("Incremental dependency ordered but it requires gnu make");
1266 }
1267 }
1268 else {
1269 if (*p_gflag) {
1270 // GNU make but no incremental deps
1271 *p_mflag = true;
1272 }
1273 }
1274 }
1275
1276 // Extract the default target option
1277 // if it is not defined as a command line argument
1278 if (!(*p_Lflag)) {
1279 expstring_t defTargetXpath = mprintf(
1280 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1281 "/ProjectProperties/MakefileSettings/defaultTarget/text()",
1282 actcfg);
1283 XPathObject defTargetObj(run_xpath(xpathCtx, defTargetXpath));
1284 Free(defTargetXpath);
1285 if (defTargetObj->nodesetval && defTargetObj->nodesetval->nodeNr > 0) {
1286 const char* content = (const char*)defTargetObj->nodesetval->nodeTab[0]->content;
1287 if (!strcmp(content, "library")) {
1288 *p_Lflag = true;
1289 } else if (!strcmp(content, "executable")) {
1290 *p_Lflag = false;
1291 } else {
1292 ERROR("Unknown default target: '%s'."
1293 " The available targets are: 'executable', 'library'", content);
1294 }
1295 }
1296 ProjectDescriptor* projDesc = projGenHelper.getTargetOfProject(*p_project_name);
1297 if (projDesc) projDesc->setLibrary(*p_Lflag);
1298 }
1299
1300 // Executable name (don't care unless top-level invocation)
1301 if (local_argc != 0)
1302 {
1303 char *exeXpath = mprintf(
1304 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1305 "/ProjectProperties/MakefileSettings/targetExecutable/text()",
1306 actcfg);
1307 XPathObject exeObj(run_xpath(xpathCtx, exeXpath));
1308 Free(exeXpath);
1309 if (exeObj->nodesetval && exeObj->nodesetval->nodeNr > 0) {
1310 const char* target_executable = (const char*)exeObj->nodesetval->nodeTab[0]->content;
1311 autostring target_exe_dir(get_dir_from_path(target_executable));
1312 autostring target_exe_file(get_file_from_path(target_executable));
1313 if (target_exe_dir!=NULL) { // if it's not only a file name
1314 if (get_path_status(target_exe_dir)==PS_NONEXISTENT) {
1315 if (strcmp(real_workdir,target_exe_dir)!=0) {
1316 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);
1317 }
1318 target_executable = target_exe_file;
1319 }
1320 }
1321 if (!*p_ets_name) { // Command line will win
1322 *p_ets_name = mcopystr(target_executable);
1323 }
1324 }
1325 }
1326
1327 // create an xml element for the currently processed project
1328 if (prj_graph_fp) {
1329 const char* prjNameStr = "???";
1330 XPathObject prjName(run_xpath(xpathCtx, "/TITAN_Project_File_Information/ProjectName/text()"));
1331 if (prjName->nodesetval && prjName->nodesetval->nodeNr == 1) {
1332 prjNameStr = (const char*)prjName->nodesetval->nodeTab[0]->content;
1333 }
1334 autostring tpd_rel_dir(get_relative_dir(tpd_dir, NULL));
1335 autostring tpd_rel_path(compose_path_name(tpd_rel_dir, (const char*)tpd_filename));
1336 fprintf(prj_graph_fp, "<project name=\"%s\" uri=\"%s\">\n", prjNameStr, (const char*)tpd_rel_path);
1337 XPathObject subprojects(run_xpath(xpathCtx, "/TITAN_Project_File_Information/ReferencedProjects/ReferencedProject/attribute::name"));
1338 xmlNodeSetPtr nodes = subprojects->nodesetval;
1339 if (nodes) for (int i = 0; i < nodes->nodeNr; ++i) {
1340 const char* refd_name = "???";
1341 if (!strcmp((const char*)nodes->nodeTab[i]->name, "name")) {
1342 refd_name = (const char*)nodes->nodeTab[i]->children->content;
1343 }
1344 fprintf(prj_graph_fp, "<reference name=\"%s\"/>\n", refd_name);
1345 }
1346 fprintf(prj_graph_fp, "</project>\n");
1347 }
1348
1349 // Tpd part of the MakefileSettings
1350 {
1351 //TTCN3preprocessorIncludes
1352 char *preincludeXpath = mprintf(
1353 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1354 "/ProjectProperties/MakefileSettings/TTCN3preprocessorIncludes/listItem/text()",
1355 actcfg);
1356 XPathObject preincludeObj(run_xpath(xpathCtx, preincludeXpath));
1357 Free(preincludeXpath);
1358
1359 xmlNodeSetPtr nodes = preincludeObj->nodesetval;
1360
1361 if (nodes) for (int i = 0; i < nodes->nodeNr; ++i) {
1362 char* content = (char*)preincludeObj->nodesetval->nodeTab[i]->content;
1363
1364 // add includes to the end of list
1365 if (ttcn3_prep_includes) {
1366 // go to last element
1367 struct string_list* last_elem = ttcn3_prep_includes;
1368 while (last_elem->next) last_elem = last_elem->next;
1369 // add string to last element if empty or create new last element and add it to that
1370 if (last_elem->str) {
1371 last_elem->next = (struct string_list*)Malloc(sizeof(struct string_list));
1372 last_elem = last_elem->next;
1373 last_elem->next = NULL;
1374 }
1375 replacechar(&content);
1376 last_elem->str = content;
1377 }
1378 }
1379 }
1380 {
1381 //TTCN3preprocessorDefines
1382 char *ttcn3predefinesXpath = mprintf(
1383 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1384 "/ProjectProperties/MakefileSettings/TTCN3preprocessorDefines/listItem/text()",
1385 actcfg);
1386 XPathObject ttcn3predefinesObj(run_xpath(xpathCtx, ttcn3predefinesXpath));
1387 Free(ttcn3predefinesXpath);
1388
1389 xmlNodeSetPtr nodes = ttcn3predefinesObj->nodesetval;
1390
1391 if (nodes) for (int i = 0; i < nodes->nodeNr; ++i) {
1392 const char* content = (const char*)ttcn3predefinesObj->nodesetval->nodeTab[i]->content;
1393
1394 // add includes to the end of list
1395 if (ttcn3_prep_defines) {
1396 // go to last element
1397 struct string_list* last_elem = ttcn3_prep_defines;
1398 while (last_elem->next) last_elem = last_elem->next;
1399 // add string to last element if empty or create new last element and add it to that
1400 if (last_elem->str) {
1401 last_elem->next = (struct string_list*)Malloc(sizeof(struct string_list));
1402 last_elem = last_elem->next;
1403 last_elem->next = NULL;
1404 }
1405 last_elem->str = mcopystr(content);
1406 }
1407 }
1408 }
1409 {
1410 //TTCN3preprocessorUnDefines
1411 char *ttcn3preUndefinesXpath = mprintf(
1412 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1413 "/ProjectProperties/MakefileSettings/TTCN3preprocessorUndefines/listItem/text()",
1414 actcfg);
1415 XPathObject ttcn3preUndefinesObj(run_xpath(xpathCtx, ttcn3preUndefinesXpath));
1416 Free(ttcn3preUndefinesXpath);
1417
1418 xmlNodeSetPtr nodes = ttcn3preUndefinesObj->nodesetval;
1419
1420 if (nodes) for (int i = 0; i < nodes->nodeNr; ++i) {
1421 const char* content = (const char*)ttcn3preUndefinesObj->nodesetval->nodeTab[i]->content;
1422
1423 // add includes to the end of list
1424 if (ttcn3_prep_undefines) {
1425 // go to last element
1426 struct string_list* last_elem = ttcn3_prep_undefines;
1427 while (last_elem->next) last_elem = last_elem->next;
1428 // add string to last element if empty or create new last element and add it to that
1429 if (last_elem->str) {
1430 last_elem->next = (struct string_list*)Malloc(sizeof(struct string_list));
1431 last_elem = last_elem->next;
1432 last_elem->next = NULL;
1433 }
1434 last_elem->str = mcopystr(content);
1435 }
1436 }
1437 }
1438
1439 {
1440 //preprocessorIncludes
1441 char *preincludesXpath = mprintf(
1442 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1443 "/ProjectProperties/MakefileSettings/preprocessorIncludes/listItem/text()",
1444 actcfg);
1445 XPathObject preincludesObj(run_xpath(xpathCtx, preincludesXpath));
1446 Free(preincludesXpath);
1447
1448 xmlNodeSetPtr nodes = preincludesObj->nodesetval;
1449
1450 if (nodes) for (int i = 0; i < nodes->nodeNr; ++i) {
1451 char* content = (char*)preincludesObj->nodesetval->nodeTab[i]->content;
1452
1453 // add includes to the end of list
1454 if (prep_includes) {
1455 // go to last element
1456 struct string_list* last_elem = prep_includes;
1457 while (last_elem->next) last_elem = last_elem->next;
1458 // add string to last element if empty or create new last element and add it to that
1459 if (last_elem->str) {
1460 last_elem->next = (struct string_list*)Malloc(sizeof(struct string_list));
1461 last_elem = last_elem->next;
1462 last_elem->next = NULL;
1463 }
1464 replacechar(&content);
1465 last_elem->str = content;
1466 }
1467 }
1468 }
1469 {
1470 //preprocessorDefines
1471 char *predefinesXpath = mprintf(
1472 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1473 "/ProjectProperties/MakefileSettings/preprocessorDefines/listItem/text()",
1474 actcfg);
1475 XPathObject predefinesObj(run_xpath(xpathCtx, predefinesXpath));
1476 Free(predefinesXpath);
1477
1478 xmlNodeSetPtr nodes = predefinesObj->nodesetval;
1479
1480 if (nodes) for (int i = 0; i < nodes->nodeNr; ++i) {
1481 const char* content = (const char*)predefinesObj->nodesetval->nodeTab[i]->content;
1482
1483 // add includes to the end of list
1484 if (prep_defines) {
1485 // go to last element
1486 struct string_list* last_elem = prep_defines;
1487 while (last_elem->next) last_elem = last_elem->next;
1488 // add string to last element if empty or create new last element and add it to that
1489 if (last_elem->str) {
1490 last_elem->next = (struct string_list*)Malloc(sizeof(struct string_list));
1491 last_elem = last_elem->next;
1492 last_elem->next = NULL;
1493 }
1494 last_elem->str = mcopystr(content);
1495 }
1496 }
1497 }
1498 {
1499 //preprocessorUnDefines
1500 char *preUndefinesXpath = mprintf(
1501 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1502 "/ProjectProperties/MakefileSettings/preprocessorUndefines/listItem/text()",
1503 actcfg);
1504 XPathObject preUndefinesObj(run_xpath(xpathCtx, preUndefinesXpath));
1505 Free(preUndefinesXpath);
1506
1507 xmlNodeSetPtr nodes = preUndefinesObj->nodesetval;
1508
1509 if (nodes) for (int i = 0; i < nodes->nodeNr; ++i) {
1510 const char* content = (const char*)preUndefinesObj->nodesetval->nodeTab[i]->content;
1511
1512 // add includes to the end of list
1513 if (prep_undefines) {
1514 // go to last element
1515 struct string_list* last_elem = prep_undefines;
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;
1522 }
1523 last_elem->str = mcopystr(content);
1524 }
1525 }
1526 }
1527 {
1528 char *cxxCompilerXpath = mprintf(
1529 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1530 "/ProjectProperties/MakefileSettings/CxxCompiler/text()",
1531 actcfg);
1532 XPathObject cxxCompilerObj(run_xpath(xpathCtx, cxxCompilerXpath));
1533 Free(cxxCompilerXpath);
1534 xmlNodeSetPtr nodes = cxxCompilerObj->nodesetval;
1535 if (nodes) {
1536 *cxxcompiler = mcopystr((const char*)cxxCompilerObj->nodesetval->nodeTab[0]->content);
1537 }
1538 }
1539 {
1540 char *optLevelXpath = mprintf(
1541 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1542 "/ProjectProperties/MakefileSettings/optimizationLevel/text()",
1543 actcfg);
1544 XPathObject optLevelObj(run_xpath(xpathCtx, optLevelXpath));
1545 Free(optLevelXpath);
1546 xmlNodeSetPtr nodes = optLevelObj->nodesetval;
1547 if (nodes) {
1548 *optlevel = mcopystr((const char*)optLevelObj->nodesetval->nodeTab[0]->content);
1549 }
1550 }
1551 {
1552 char *optFlagsXpath = mprintf(
1553 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1554 "/ProjectProperties/MakefileSettings/otherOptimizationFlags/text()",
1555 actcfg);
1556 XPathObject optFlagsObj(run_xpath(xpathCtx, optFlagsXpath));
1557 Free(optFlagsXpath);
1558 xmlNodeSetPtr nodes = optFlagsObj->nodesetval;
1559 if (nodes) {
1560 *optflags = mcopystr((const char*)optFlagsObj->nodesetval->nodeTab[0]->content);
1561 }
1562 }
1563 {
1564 //SolarisSpecificLibraries
1565 char *solspeclibXpath = mprintf(
1566 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1567 "/ProjectProperties/MakefileSettings/SolarisSpecificLibraries/listItem/text()",
1568 actcfg);
1569 XPathObject solspeclibObj(run_xpath(xpathCtx, solspeclibXpath));
1570 Free(solspeclibXpath);
1571
1572 xmlNodeSetPtr nodes = solspeclibObj->nodesetval;
1573
1574 if (nodes) for (int i = 0; i < nodes->nodeNr; ++i) {
1575 char* content = (char*)solspeclibObj->nodesetval->nodeTab[i]->content;
1576
1577 // add includes to the end of list
1578 if (solspeclibs) {
1579 // go to last element
1580 struct string_list* last_elem =solspeclibs;
1581 while (last_elem->next) last_elem = last_elem->next;
1582 // add string to last element if empty or create new last element and add it to that
1583 if (last_elem->str) {
1584 last_elem->next = (struct string_list*)Malloc(sizeof(struct string_list));
1585 last_elem = last_elem->next;
1586 last_elem->next = NULL;
1587 }
1588 replacechar(&content);
1589 last_elem->str = content;
1590 }
1591 }
1592 }
1593 {
1594 //Solaris8SpecificLibraries
1595 char *sol8speclibXpath = mprintf(
1596 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1597 "/ProjectProperties/MakefileSettings/Solaris8SpecificLibraries/listItem/text()",
1598 actcfg);
1599 XPathObject sol8speclibObj(run_xpath(xpathCtx, sol8speclibXpath));
1600 Free(sol8speclibXpath);
1601
1602 xmlNodeSetPtr nodes = sol8speclibObj->nodesetval;
1603
1604 if (nodes) for (int i = 0; i < nodes->nodeNr; ++i) {
1605 char* content = (char*)sol8speclibObj->nodesetval->nodeTab[i]->content;
1606
1607 // add includes to the end of list
1608 if (sol8speclibs) {
1609 // go to last element
1610 struct string_list* last_elem = sol8speclibs;
1611 while (last_elem->next) last_elem = last_elem->next;
1612 // add string to last element if empty or create new last element and add it to that
1613 if (last_elem->str) {
1614 last_elem->next = (struct string_list*)Malloc(sizeof(struct string_list));
1615 last_elem = last_elem->next;
1616 last_elem->next = NULL;
1617 }
1618 replacechar(&content);
1619 last_elem->str = content;
1620 }
1621 }
1622 }
1623 {
1624 //LinuxSpecificLibraries
1625 char *linuxspeclibXpath = mprintf(
1626 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1627 "/ProjectProperties/MakefileSettings/LinuxSpecificLibraries/listItem/text()",
1628 actcfg);
1629 XPathObject linuxspeclibObj(run_xpath(xpathCtx, linuxspeclibXpath));
1630 Free(linuxspeclibXpath);
1631
1632 xmlNodeSetPtr nodes = linuxspeclibObj->nodesetval;
1633
1634 if (nodes) for (int i = 0; i < nodes->nodeNr; ++i) {
1635 char* content = (char*)linuxspeclibObj->nodesetval->nodeTab[i]->content;
1636
1637 // add includes to the end of list
1638 if (linuxspeclibs) {
1639 // go to last element
1640 struct string_list* last_elem = linuxspeclibs;
1641 while (last_elem->next) last_elem = last_elem->next;
1642 // add string to last element if empty or create new last element and add it to that
1643 if (last_elem->str) {
1644 last_elem->next = (struct string_list*)Malloc(sizeof(struct string_list));
1645 last_elem = last_elem->next;
1646 last_elem->next = NULL;
1647 }
1648 replacechar(&content);
1649 last_elem->str = content;
1650 }
1651 }
1652 }
1653 {
1654 //FreeBSDSpecificLibraries
1655 char *freebsdspeclibXpath = mprintf(
1656 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1657 "/ProjectProperties/MakefileSettings/FreeBSDSpecificLibraries/listItem/text()",
1658 actcfg);
1659 XPathObject freebsdspeclibObj(run_xpath(xpathCtx, freebsdspeclibXpath));
1660 Free(freebsdspeclibXpath);
1661
1662 xmlNodeSetPtr nodes = freebsdspeclibObj->nodesetval;
1663
1664 if (nodes) for (int i = 0; i < nodes->nodeNr; ++i) {
1665 char* content = (char*)freebsdspeclibObj->nodesetval->nodeTab[i]->content;
1666
1667 // add includes to the end of list
1668 if (freebsdspeclibs) {
1669 // go to last element
1670 struct string_list* last_elem = freebsdspeclibs;
1671 while (last_elem->next) last_elem = last_elem->next;
1672 // add string to last element if empty or create new last element and add it to that
1673 if (last_elem->str) {
1674 last_elem->next = (struct string_list*)Malloc(sizeof(struct string_list));
1675 last_elem = last_elem->next;
1676 last_elem->next = NULL;
1677 }
1678 replacechar(&content);
1679 last_elem->str = content;
1680 }
1681 }
1682 }
1683 {
1684 //Win32SpecificLibraries
1685 char *win32speclibXpath = mprintf(
1686 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1687 "/ProjectProperties/MakefileSettings/Win32SpecificLibraries/listItem/text()",
1688 actcfg);
1689 XPathObject win32speclibObj(run_xpath(xpathCtx, win32speclibXpath));
1690 Free(win32speclibXpath);
1691
1692 xmlNodeSetPtr nodes = win32speclibObj->nodesetval;
1693
1694 if (nodes) for (int i = 0; i < nodes->nodeNr; ++i) {
1695 char* content = (char*)win32speclibObj->nodesetval->nodeTab[i]->content;
1696
1697 // add includes to the end of list
1698 if (win32speclibs) {
1699 // go to last element
1700 struct string_list* last_elem = win32speclibs;
1701 while (last_elem->next) last_elem = last_elem->next;
1702 // add string to last element if empty or create new last element and add it to that
1703 if (last_elem->str) {
1704 last_elem->next = (struct string_list*)Malloc(sizeof(struct string_list));
1705 last_elem = last_elem->next;
1706 last_elem->next = NULL;
1707 }
1708 replacechar(&content);
1709 last_elem->str = content;
1710 }
1711
1712 }
1713 }
1714 {
1715 //TTCN3preprocessor
1716 char *ttcn3preproc = mprintf(
1717 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1718 "/ProjectProperties/MakefileSettings/TTCN3preprocessor/text()",
1719 actcfg);
1720 XPathObject ttcn3preprocObj(run_xpath(xpathCtx, ttcn3preproc));
1721 Free(ttcn3preproc);
1722 xmlNodeSetPtr nodes = ttcn3preprocObj->nodesetval;
1723 if (nodes) {
1724 *ttcn3prep = mcopystr((const char*)ttcn3preprocObj->nodesetval->nodeTab[0]->content);
1725 }
1726 }
1727 {
1728 // additionalObjects
1729 char *additionalObjectsXpath = mprintf(
1730 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1731 "/ProjectProperties/MakefileSettings/additionalObjects/listItem/text()",
1732 actcfg);
1733 XPathObject additionalObjectsObj(run_xpath(xpathCtx, additionalObjectsXpath));
1734 Free(additionalObjectsXpath);
1735
1736 xmlNodeSetPtr nodes = additionalObjectsObj->nodesetval;
1737
1738 if (nodes) for (int i = 0; i < nodes->nodeNr; ++i) {
1739 char* content = (char*)additionalObjectsObj->nodesetval->nodeTab[i]->content;
1740
1741 // add to the end of list
1742 if (additionalObjects) {
1743 // go to last element
1744 struct string_list* last_elem = additionalObjects;
1745 while (last_elem->next) last_elem = last_elem->next;
1746 // add string to last element if empty or create new last element and add it to that
1747 if (last_elem->str) {
1748 last_elem->next = (struct string_list*)Malloc(sizeof(struct string_list));
1749 last_elem = last_elem->next;
1750 last_elem->next = NULL;
1751 }
1752 replacechar(&content);
1753 last_elem->str = content;
1754 }
1755 }
1756 }
1757 {
1758 //The project name needed the hierarchical projects
1759 char* prjNameStr = 0;
1760 char *prjNameStrXpath = mprintf("/TITAN_Project_File_Information/ProjectName/text()");
1761 XPathObject prjName(run_xpath(xpathCtx, prjNameStrXpath));
1762 if (prjName->nodesetval && prjName->nodesetval->nodeNr == 1) {
1763 prjNameStr = (char*)prjName->nodesetval->nodeTab[0]->content;
1764 }
1765 Free(prjNameStrXpath);
1766 append_to_library_list (prjNameStr, xpathCtx, actcfg);
1767
1768 //linkerLibraries
1769 char *linkerlibsXpath = mprintf(
1770 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1771 "/ProjectProperties/MakefileSettings/linkerLibraries/listItem/text()",
1772 actcfg);
1773 XPathObject linkerlibsObj(run_xpath(xpathCtx, linkerlibsXpath));
1774 Free(linkerlibsXpath);
1775
1776 xmlNodeSetPtr nodes = linkerlibsObj->nodesetval;
1777
1778 if (nodes) for (int i = 0; i < nodes->nodeNr; ++i) {
1779 char* content = (char*)linkerlibsObj->nodesetval->nodeTab[i]->content;
1780
1781 // add includes to the end of list
1782 if (linkerlibs) {
1783 // go to last element
1784 struct string_list* last_elem = linkerlibs;
1785 while (last_elem->next) last_elem = last_elem->next;
1786 // add string to last element if empty or create new last element and add it to that
1787 if (last_elem->str) {
1788 last_elem->next = (struct string_list*)Malloc(sizeof(struct string_list));
1789 last_elem = last_elem->next;
1790 last_elem->next = NULL;
1791 }
1792 replacechar(&content);
1793 last_elem->str = content;
1794
1795 ProjectDescriptor* projDesc = projGenHelper.getTargetOfProject(*p_project_name);
1796 if (projDesc) projDesc->addToLinkerLibs(last_elem->str);
1797 }
1798 }
1799 }
1800 {
1801 //linkerLibrarySearchPath
1802 char *linkerlibsearchXpath = mprintf(
1803 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1804 "/ProjectProperties/MakefileSettings/linkerLibrarySearchPath/listItem/text()",
1805 actcfg);
1806 XPathObject linkerlibsearchObj(run_xpath(xpathCtx, linkerlibsearchXpath));
1807 Free(linkerlibsearchXpath);
1808
1809 xmlNodeSetPtr nodes = linkerlibsearchObj->nodesetval;
1810
1811 if (nodes) for (int i = 0; i < nodes->nodeNr; ++i) {
1812 char* content = (char*)linkerlibsearchObj->nodesetval->nodeTab[i]->content;
1813
1814 // add includes to the end of list
1815 if (linkerlibsearchp) {
1816 // go to last element
1817 struct string_list* last_elem = linkerlibsearchp;
1818 while (last_elem->next) last_elem = last_elem->next;
1819 // add string to last element if empty or create new last element and add it to that
1820 if (last_elem->str) {
1821 last_elem->next = (struct string_list*)Malloc(sizeof(struct string_list));
1822 last_elem = last_elem->next;
1823 last_elem->next = NULL;
1824 }
1825 replacechar(&content);
1826 last_elem->str = content;
1827
1828 ProjectDescriptor* projDesc = projGenHelper.getTargetOfProject(*p_project_name);
1829 if (projDesc) projDesc->addToLibSearchPaths(last_elem->str);
1830 }
1831 }
1832 }
1833
1834 if (generatorCommandOutput && local_argc != 0) { // only in case of top-level invocation
1835 char* generatorCommandXpath = mprintf(
1836 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1837 "/ProjectProperties/MakefileSettings/ProjectSpecificRulesGenerator/GeneratorCommand/text()",
1838 actcfg);
1839 XPathObject generatorCommandObj(run_xpath(xpathCtx, generatorCommandXpath));
1840 Free(generatorCommandXpath);
1841 autostring generatorCommand;
1842 if (generatorCommandObj->nodesetval && generatorCommandObj->nodesetval->nodeNr > 0) {
1843 generatorCommand = mcopystr((const char*)generatorCommandObj->nodesetval->nodeTab[0]->content);
1844 // run the command and capture the output
1845 printf("Executing generator command `%s' specified in `%s'...\n", (const char*)generatorCommand, (const char*)abs_tpd_name);
1846 FILE* gc_fp = popen(generatorCommand, "r");
1847 if (!gc_fp) {
1848 ERROR("Could not execute command `%s'", (const char*)generatorCommand);
1849 } else {
1850 char buff[1024];
1851 while (fgets(buff, sizeof(buff), gc_fp)!=NULL) {
1852 *generatorCommandOutput = mputstr(*generatorCommandOutput, buff);
1853 }
1854 pclose(gc_fp);
1855 }
1856 }
1857 }
1858
1859 if (target_placement_list && local_argc != 0) { // only in case of top-level invocation
1860 char* targetPlacementXpath = mprintf(
1861 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1862 "/ProjectProperties/MakefileSettings/ProjectSpecificRulesGenerator/Targets/Target/attribute::*",
1863 actcfg);
1864 XPathObject targetPlacementObj(run_xpath(xpathCtx, targetPlacementXpath));
1865 Free(targetPlacementXpath);
1866 xmlNodeSetPtr nodes = targetPlacementObj->nodesetval;
1867 const char* targetName = NULL;
1868 const char* targetPlacement = NULL;
1869 if (nodes) for (int i = 0; i < nodes->nodeNr; ++i) {
1870 if (!strcmp((const char*)nodes->nodeTab[i]->name, "name")) {
1871 targetName = (const char*)nodes->nodeTab[i]->children->content;
1872 }
1873 else if (!strcmp((const char*)nodes->nodeTab[i]->name,"placement")) {
1874 targetPlacement = (const char*)nodes->nodeTab[i]->children->content;
1875 }
1876 if (targetName && targetPlacement) { // collected both
1877 if (target_placement_list) {
1878 // go to last element
1879 struct string2_list* last_elem = target_placement_list;
1880 while (last_elem->next) last_elem = last_elem->next;
1881 // add strings to last element if empty or create new last element and add it to that
1882 if (last_elem->str1) {
1883 last_elem->next = (struct string2_list*)Malloc(sizeof(struct string2_list));
1884 last_elem = last_elem->next;
1885 last_elem->next = NULL;
1886 }
1887 last_elem->str1 = mcopystr(targetName);
1888 last_elem->str2 = mcopystr(targetPlacement);
1889 }
1890 targetName = targetPlacement = NULL; // forget both
1891 }
1892 }
1893 }
1894
1895 {
1896 // profiler file name
1897 char* profilerXpath = mprintf(
1898 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1899 "/ProjectProperties/MakefileSettings/profiledFileList", actcfg);
1900 XPathObject profiledFilesNameObj(run_xpath(xpathCtx, profilerXpath));
1901 Free(profilerXpath);
1902 xmlNodeSetPtr nodes = profiledFilesNameObj->nodesetval;
1903 if (nodes && nodes->nodeNr > 0) {
1904 const char *uri = 0, *path = 0, *raw = 0;
1905 for (xmlAttrPtr attr = nodes->nodeTab[0]->properties; attr; attr = attr->next) {
1906 if (!strcmp((const char*)attr->name, "projectRelativePath")) {
1907 path = (const char*)attr->children->content;
1908 }
1909 else if (!strcmp((const char*)attr->name, "relativeURI")) {
1910 uri = (const char*)attr->children->content;
1911 }
1912 else if (!strcmp((const char*)attr->name, "rawURI")) {
1913 raw = (const char*)attr->children->content;
1914 }
1915 else {
1916 WARNING("Unknown attribute %s", (const char*)nodes->nodeTab[0]->name);
1917 }
1918 } // next attribute
1919
1920 if (path == NULL) {
1921 ERROR("A profiledFileList must have a projectRelativePath");
1922 }
1923 else {
1924 if (uri == NULL && raw == NULL) {
1925 ERROR("A profiledFileList must have either relativeURI or rawURI");
1926 }
1927 else {
1928 cstring cpath(path);
1929 if (files.has_key(cpath)) {
1930 ERROR("profiledFileLists and FileResources must be unique!");
1931 }
1932 else {
1933 // add the file to the end of the list
1934 struct string_list* new_item = NULL;
1935 if (*profiled_file_list == NULL) {
1936 *profiled_file_list = (struct string_list*)Malloc(sizeof(struct string_list));
1937 new_item = *profiled_file_list;
1938 }
1939 else {
1940 new_item = *profiled_file_list;
1941 while(new_item->next != NULL) {
1942 new_item = new_item->next;
1943 }
1944 new_item->next = (struct string_list*)Malloc(sizeof(struct string_list));
1945 new_item = new_item->next;
1946 }
1947 new_item->str = mcopystr(path);
1948 new_item->next = NULL;
1949
1950 // add the file to the map of files to be copied to the working directory
1951 char *ruri = uri ? mcopystr(uri) : cook(raw, path_vars);
1952 files.add(cpath, ruri);
1953 }
1954 }
1955 }
1956 }
1957 }
1958
1959 // collect the required configurations
1960 {
1961 if (required_configs) {
1962 char* cfgReqsXpath(mprintf(
1963 "/TITAN_Project_File_Information/Configurations/Configuration[@name='%s']"
1964 "/ProjectProperties/ConfigurationRequirements/configurationRequirement",
1965 actcfg));
1966 XPathObject reqcfgObjects(run_xpath(xpathCtx, cfgReqsXpath));
1967 Free (cfgReqsXpath);
1968 xmlNodeSetPtr configs = reqcfgObjects->nodesetval;
1969 if (configs) for (int i = 0; i < configs->nodeNr; ++i) {
1970 xmlNodePtr curNodePtr = configs->nodeTab[i]->children;
1971 const char* projectName = NULL;
1972 const char* reqConfig = NULL;
1973 while(curNodePtr) {
1974 if (!strcmp((const char*)curNodePtr->name, "projectName")) {
1975 projectName = (const char*)curNodePtr->children->content;
1976 }
1977 if (!strcmp((const char*)curNodePtr->name, "rerquiredConfiguration") || // backward compatibility
1978 !strcmp((const char*)curNodePtr->name, "requiredConfiguration")) {
1979 reqConfig = (const char*)curNodePtr->children->content;
1980 }
1981 curNodePtr = curNodePtr->next;
1982 }
1983 struct string2_list* last_elem = required_configs;
1984 bool duplicate = false;
1985 while (last_elem->next) {
1986 if (!strcmp(last_elem->str1, projectName) && !strcmp(last_elem->str2, reqConfig)) {
1987 duplicate = true;
1988 }
1989 else if (!strcmp(last_elem->str1, projectName) && strcmp(last_elem->str2, reqConfig)) {
1990 ERROR("Required configuration is inconsistent : Project '%s' cannot have 2 "
1991 "different configuration '%s' '%s'",
1992 last_elem->str1, last_elem->str2, reqConfig);
1993 result = TPD_FAILED;
1994 }
1995 last_elem = last_elem->next;
1996 }
1997 // add string to last element if empty or create new last element and add it to that
1998 if (last_elem->str1 && !duplicate) {
1999 if (strcmp(last_elem->str1, projectName) || strcmp(last_elem->str2, reqConfig)) {
2000 last_elem->next = (struct string2_list*)Malloc(sizeof(struct string2_list));
2001 last_elem = last_elem->next;
2002 last_elem->next = NULL;
2003 }
2004 else {
2005 duplicate = true;
2006 }
2007 }
2008 if (!duplicate) {
2009 last_elem->str1 = mcopystr(projectName);
2010 last_elem->str2 = mcopystr(reqConfig);
2011 }
2012 }
2013 }
2014 }
2015
2016 // Referenced projects
2017 {
2018 XPathObject subprojects(run_xpath(xpathCtx,
2019 "/TITAN_Project_File_Information/ReferencedProjects/ReferencedProject"));
2020 xmlNodeSetPtr nodes = subprojects->nodesetval;
2021 //Go through ReferencedProjects
2022 if (nodes) for (int i = 0; i < nodes->nodeNr; ++i) {
2023 const char *name = NULL, *projectLocationURI = NULL;
2024 char *tpdName_loc = NULL;
2025 // FIXME: this assumes every ReferencedProject has name and URI.
2026 // This is not necessarily so if the referenced project was closed
2027 // when the project was exported to TPD.
2028 // Luckily, the name from the closed project will be overwritten
2029 // by the name from the next ReferencedProject. However, if some pervert
2030 // changes the next ReferencedProject to have the projectLocationURI
2031 // as the first attribute, it will be joined to the name
2032 // of the previous, closed, ReferencedProject.
2033
2034 //Go through attributes
2035 for (xmlAttrPtr attr = nodes->nodeTab[i]->properties; attr; attr = attr->next) {
2036 if (!strcmp((const char*)attr->name, "name")) {
2037 name = (const char*)attr->children->content;
2038 }
2039 else if (!strcmp((const char*)attr->name,"projectLocationURI")) {
2040 projectLocationURI = (const char*)attr->children->content;
2041 }
2042 else if (!strcmp((const char*)attr->name, "tpdName")) {
2043 //Allocate memory
2044 tpdName_loc = mcopystr((char*)attr->children->content);
2045 }
2046 }
2047 //We don't want to orerride an absolute location with -I, tpdName remains NULL
2048 boolean not_abs_path = projectLocationURI &&
2049 #if defined WIN32 && defined MINGW
2050 /* On native Windows the absolute path name shall begin with
2051 * a drive letter, colon and backslash */
2052 (((projectLocationURI[0] < 'A' || projectLocationURI[0] > 'Z') &&
2053 (projectLocationURI[0] < 'a' || projectLocationURI[0] > 'z')) ||
2054 projectLocationURI[1] != ':' || projectLocationURI[2] != '\\');
2055 #else
2056 /* On UNIX-like systems the absolute path name shall begin with
2057 * a slash */
2058 projectLocationURI[0] != '/';
2059 #endif
2060 if (!tpdName_loc && not_abs_path) {
2061 //Allocate memory: +5 because .tpd + closing 0
2062 tpdName_loc = (char*)Malloc((strlen(name) + 5) * sizeof(char));
2063 //Default name: name + .tpd
2064 strcpy(tpdName_loc, name);
2065 strcat(tpdName_loc, ".tpd");
2066 }else if (!not_abs_path) {
2067 Free(tpdName_loc);
2068 tpdName_loc = NULL;
2069 }
2070
2071 if (name && projectLocationURI) { // collected both
2072 // see if there is a specified configuration for the project
2073
2074 ProjectDescriptor* projDesc = projGenHelper.getTargetOfProject(*p_project_name);
2075 if (projDesc) projDesc->addToReferencedProjects(name);
2076
2077 const char *my_actcfg = NULL;
2078 int my_argc = 0;
2079 char *my_args[] = { NULL };
2080 char **my_argv = my_args + 0;
2081 int my_optind = 0;
2082 boolean my_gflag = *p_gflag, my_aflag = *p_aflag, my_cflag = *p_cflag, // pass down
2083 my_Rflag = *p_Rflag, my_Pflag = *p_Pflag, my_Zflag = *p_Zflag, my_Hflag = *p_Hflag,
2084 my_sflag = 0, my_Lflag = 0, my_lflag = 0, my_mflag = 0, my_csflag = 0,
2085 my_quflag = 0, my_dsflag = 0, my_dbflag = 0, my_drflag = 0,
2086 my_dtflag = 0, my_dxflag = 0, my_djflag = 0, my_fxflag = 0, my_doflag = 0,
2087 my_gfflag = 0, my_lnflag = 0, my_isflag = 0, my_asflag = 0,
2088 my_swflag = 0, my_Yflag = 0, my_Mflag = *p_Mflag, my_Eflag = 0, my_diflag = *p_diflag;
2089
2090 char *my_ets = NULL;
2091 char *my_proj_name = NULL;
2092 autostring abs_projectLocationURI;
2093 if (not_abs_path) {
2094 abs_projectLocationURI = compose_path_name(abs_tpd_dir, projectLocationURI);
2095 } else {
2096 //If absolute directory, then just copy the URI
2097 abs_projectLocationURI = mcopystr(projectLocationURI);
2098 }
2099
2100 char* sub_proj_abs_work_dir = NULL;
2101
2102 tpd_result success = process_tpd_internal((const char*)abs_projectLocationURI, tpdName_loc,
2103 my_actcfg, file_list_path, &my_argc, &my_argv, &my_optind, &my_ets, &my_proj_name,
2104 &my_gflag, &my_sflag, &my_cflag, &my_aflag, preprocess, &my_Rflag, &my_lflag,
2105 &my_mflag, &my_Pflag, &my_Lflag, recursive, force_overwrite, gen_only_top_level, NULL, &sub_proj_abs_work_dir,
2106 sub_project_dirs, program_name, prj_graph_fp, create_symlink_list, ttcn3_prep_includes, ttcn3_prep_defines, ttcn3_prep_undefines,
2107 prep_includes, prep_defines, prep_undefines, &my_csflag,
2108 &my_quflag, &my_dsflag, cxxcompiler, optlevel, optflags, &my_dbflag, &my_drflag,
2109 &my_dtflag, &my_dxflag, &my_djflag, &my_fxflag, &my_doflag,
2110 &my_gfflag, &my_lnflag, &my_isflag, &my_asflag, &my_swflag, &my_Yflag, &my_Mflag, &my_Eflag, &my_diflag,
2111 solspeclibs, sol8speclibs, linuxspeclibs, freebsdspeclibs, win32speclibs,
2112 ttcn3prep, linkerlibs, additionalObjects, linkerlibsearchp, Vflag, FALSE, &my_Zflag,
2113 &my_Hflag, NULL, NULL, prefix_workdir, run_command_list, seen_tpd_files, required_configs, profiled_file_list,
2114 search_paths, n_search_paths);
2115
2116 autostring sub_proj_abs_work_dir_as(sub_proj_abs_work_dir); // ?!
2117
2118 if (success == TPD_SUCCESS) {
2119 my_actcfg = get_act_config(required_configs, my_proj_name);
2120 if (recursive) { // call ttcn3_makefilegen on referenced project's tpd file
2121 // -r is not needed any more because top level process traverses all projects recursively
2122 expstring_t command = mprintf("%s -cVD", program_name);
2123 if (force_overwrite) command = mputc(command, 'f');
2124 if (prefix_workdir) command = mputc(command, 'W');
2125 if (*p_gflag) command = mputc(command, 'g');
2126 if (*p_sflag) command = mputc(command, 's');
2127 if (*p_aflag) command = mputc(command, 'a');
2128 if (*p_Rflag) command = mputc(command, 'R');
2129 if (*p_lflag) command = mputc(command, 'l');
2130 if (*p_mflag) command = mputc(command, 'm');
2131 if (*p_Zflag) command = mputc(command, 'Z');
2132 if (*p_Hflag) command = mputc(command, 'H');
2133 command = mputstr(command, " -t ");
2134 command = mputstr(command, (const char*)abs_projectLocationURI);
2135 if (my_actcfg) {
2136 command = mputstr(command, " -b ");
2137 command = mputstr(command, my_actcfg);
2138 }
2139
2140 autostring sub_tpd_dir(get_dir_from_path((const char*)abs_projectLocationURI));
2141 const char * sub_proj_effective_work_dir = sub_proj_abs_work_dir ? sub_proj_abs_work_dir : (const char*)sub_tpd_dir;
2142 if (!gen_only_top_level) {
2143 if (run_command_list) {
2144 // go to last element
2145 struct string2_list* last_elem = run_command_list;
2146 while (last_elem->next) last_elem = last_elem->next;
2147 // add strings to last element if empty or create new last element and add it to that
2148 if (last_elem->str1 || last_elem->str2) {
2149 last_elem->next = (struct string2_list*)Malloc(sizeof(struct string2_list));
2150 last_elem = last_elem->next;
2151 last_elem->next = NULL;
2152 }
2153 last_elem->str1 = mcopystr(sub_proj_effective_work_dir);
2154 last_elem->str2 = command;
2155 } else {
2156 ERROR("Internal error: cannot add command to list");
2157 }
2158 }
2159 // add working dir to the end of list
2160 if (sub_project_dirs) {
2161 // go to last element
2162 struct string_list* last_elem = sub_project_dirs;
2163 while (last_elem->next) last_elem = last_elem->next;
2164 // add string to last element if empty or create new last element and add it to that
2165 if (last_elem->str) {
2166 last_elem->next = (struct string_list*)Malloc(sizeof(struct string_list));
2167 last_elem = last_elem->next;
2168 last_elem->next = NULL;
2169 }
2170 autostring cwd_as(get_working_dir());
2171 last_elem->str = (*p_aflag) ? mcopystr(sub_proj_effective_work_dir) : get_relative_dir(sub_proj_effective_work_dir, (const char*)cwd_as);
2172 }
2173 }
2174
2175 for (int z = 0; z < my_argc; ++z) {
2176 if (*p_cflag) {
2177 // central storage, keep in separate container
2178 base_files.add(my_argv[z]); // string was allocated with new
2179 }
2180 else {
2181 const cstring tmp(my_argv[z]);
2182 if (!files.has_key(tmp)){
2183 files.add(tmp, my_argv[z]);
2184 } else {
2185 Free(my_argv[z]);
2186 }
2187 }
2188 }
2189
2190 Free(my_argv); // free the array; we keep the pointers
2191 Free(my_ets);
2192 Free(my_proj_name);
2193 }
2194 else if (success == TPD_FAILED) {
2195 ERROR("Failed to process %s", (const char*)abs_projectLocationURI);
2196 result = TPD_FAILED;
2197 }
2198 // else TPD_SKIPPED, keep quiet
2199 Free(tpdName_loc);
2200 name = projectLocationURI = tpdName_loc = NULL; // forget all
2201 }
2202 } // next referenced project
2203 }
2204
2205 if (output_file) {
2206 if (get_path_status(output_file) == PS_DIRECTORY) {
2207 // points to existing dir; use as-is
2208 }
2209 else { // we assume it points to a file: not our problem
2210 output_file = NULL;
2211 }
2212 }
2213
2214 // (argc - optind) is the number of non-option arguments (assumed to be files)
2215 // given on the command line.
2216 int new_argc = local_argc - local_optind + files.size() + base_files.size();
2217 char ** new_argv = (char**)Malloc(sizeof(char*) * new_argc);
2218
2219 int n = 0;
2220
2221 // First, copy the filenames gathered from the TPD
2222 //
2223 // We symlink the files into the working directory
2224 // and pass only the filename to the makefile generator
2225 for (int nf = files.size(); n < nf; ++n) {
2226 const char *fn = files.get_nth_elem(n); // relativeURI to the TPD location
2227 autostring dir_n (get_dir_from_path (fn));
2228 autostring file_n(get_file_from_path(fn));
2229 autostring rel_n (get_absolute_dir(dir_n, abs_tpd_dir, TRUE));
2230 autostring abs_n (compose_path_name(rel_n, file_n));
2231
2232 if (local_argc == 0) {
2233 // We are being invoked recursively, for a referenced TPD.
2234 // Do not symlink; just return absolute paths to the files.
2235 if (*fn == '/') {
2236 if (*p_cflag) {
2237 // compose with workdir
2238 new_argv[n] = compose_path_name(abs_workdir, file_n);
2239 } else {
2240 // it's an absolute path, copy verbatim
2241 new_argv[n] = mcopystr(fn); // fn will be destroyed, pass a copy
2242 }
2243 }
2244 else { // relative path
2245 if (*p_cflag) {
2246 // compose with workdir
2247 new_argv[n] = compose_path_name(abs_workdir, file_n);
2248 // Do not call file_n.extract() : the composed path will be returned,
2249 // its component will need to be deallocated here.
2250 }
2251 else {
2252 // compose with tpd dir
2253 new_argv[n] = const_cast<char*>(abs_n.extract());
2254 }
2255 }
2256 }
2257 else { // we are processing the top-level TPD
2258 #ifndef MINGW
2259 if (!*p_Pflag) {
2260 int fd = open(abs_n, O_RDONLY);
2261 if (fd >= 0) { // successfully opened
2262 close(fd);
2263 if (output_file) {
2264 file_n = compose_path_name(output_file, file_n);
2265 }
2266 //TODO ! compose with output_file
2267 // save into list: add symlink data to the end of list
2268 if (create_symlink_list) {
2269 // go to last element
2270 struct string2_list* last_elem = create_symlink_list;
2271 while (last_elem->next) last_elem = last_elem->next;
2272 // add strings to last element if empty or create new last element and add it to that
2273 if (last_elem->str1) {
2274 last_elem->next = (struct string2_list*)Malloc(sizeof(struct string2_list));
2275 last_elem = last_elem->next;
2276 last_elem->next = NULL;
2277 }
2278 last_elem->str1 = mcopystr(abs_n);
2279 last_elem->str2 = mcopystr(file_n);
2280 }
2281 }
2282 else {
2283 ERROR("%s does not exist", (const char*)abs_n);
2284 }
2285 }
2286 #endif
2287 if (*p_Pflag) {
2288 if (*p_aflag) {
2289 puts((const char *)abs_n);
2290 } else {
2291 autostring dir_part(get_dir_from_path(abs_n));
2292 autostring file_part(get_file_from_path(abs_n));
2293 autostring rel_dir_part(get_relative_dir((const char *)dir_part, file_list_path ? file_list_path : (const char *)abs_tpd_dir));
2294 autostring rel_dir_file_part(compose_path_name((const char *)rel_dir_part, (const char *)file_part));
2295 puts((const char *)rel_dir_file_part);
2296 }
2297 }
2298 new_argv[n] = const_cast<char *>(file_n.extract());
2299 }
2300 }
2301 // Print the TPD too.
2302 if (*p_Pflag) {
2303 autostring dir_part(get_dir_from_path(p_tpd_name));
2304 autostring file_part(get_file_from_path(p_tpd_name));
2305 if (*p_aflag) {
2306 puts((const char *)abs_tpd_name);
2307 } else {
2308 autostring rel_dir_part(get_relative_dir(dir_part, file_list_path ? file_list_path : abs_tpd_dir));
2309 autostring rel_dir_file_part(compose_path_name(rel_dir_part, file_part));
2310 const char *rel_tpd_name = (const char *)rel_dir_file_part;
2311 puts(rel_tpd_name);
2312 }
2313 }
2314
2315 // base_files from referenced projects
2316 for (size_t bf = 0, bs = base_files.size(); bf < bs; ++bf, ++n) {
2317 new_argv[n] = base_files[bf];
2318 }
2319 base_files.clear(); // string ownership transfered
2320
2321 // Then, copy the filenames from the command line.
2322 for (int a = *p_optind; a < *p_argc; ++a, ++n) {
2323 // String may be from main's argv; copy to the heap.
2324 new_argv[n] = mcopystr((*p_argv)[a]);
2325 }
2326
2327 if (local_argc > 0) { // it is the outermost call
2328 clear_seen_tpd_files(seen_tpd_files);
2329 }
2330 // replace argv
2331 *p_argv = new_argv;
2332 *p_argc = new_argc;
2333 *p_optind = 0;
2334
2335 // finally...
2336 for (size_t i = 0, e = files.size(); i < e; ++i) {
2337 Free(const_cast<char*>(files.get_nth_elem(i)));
2338 }
2339 files.clear();
2340
2341 for (size_t i = 0, e = folders.size(); i < e; ++i) {
2342 Free(const_cast<char*>(folders.get_nth_elem(i)));
2343 }
2344 folders.clear();
2345
2346 if(free_name) {
2347 Free((char*)p_tpd_name);
2348 }
2349
2350 excluded_files.clear();
2351 excluded_folders.clear();
2352 path_vars.clear();
2353
2354 xmlCleanupParser();
2355 // ifdef debug
2356 xmlMemoryDump();
2357 return result;
2358 }
This page took 0.084878 seconds and 5 git commands to generate.