1 /************************************************************************
2 ************************************************************************
4 Copyright (C) 2003-2004 GRAME, Centre National de Creation Musicale
5 ---------------------------------------------------------------------
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 ************************************************************************
20 ************************************************************************/
24 #include "enrobage.hh"
29 #include "compatibility.hh"
32 extern string gFaustSuperSuperDirectory
;
33 extern string gFaustSuperDirectory
;
34 extern string gFaustDirectory
;
35 extern string gMasterDirectory
;
36 extern string gClassName
;
38 //----------------------------------------------------------------
42 * Returns true is a line is blank (contains only white caracters)
44 static bool isBlank(const string
& s
) {
45 for (size_t i
=0; i
<s
.size(); i
++) {
46 if (s
[i
] != ' ' && s
[i
] != '\t') return false;
53 * Replace every occurrence of oldstr by newstr inside str. str is modified
54 * and returned as reference for convenience
56 static string
& replaceOccurences(string
& str
, const string
& oldstr
, const string
& newstr
)
58 string::size_type l1
= oldstr
.length();
59 string::size_type l2
= newstr
.length();
61 string::size_type pos
= str
.find(oldstr
);
62 while ( pos
!= string::npos
) {
63 str
.replace(pos
, l1
, newstr
);
64 pos
= str
.find(oldstr
, pos
+ l2
);
71 * Used when copying architecture files to replace default mydsp
72 * class name with the user specified one
74 static string
& replaceClassName(string
& str
)
76 return replaceOccurences(str
, "mydsp", gClassName
);
81 * Copy or remove license header. Architecture files can contain a header specifying
82 * the license. If this header contains an exception tag (for example "FAUST COMPILER EXCEPTION")
83 * it is an indication for the compiler to remove the license header from the resulting code.
84 * A header is the first non blank line that begins a comment.
86 void streamCopyLicense(istream
& src
, ostream
& dst
, const string
& exceptiontag
)
92 while (getline(src
,s
) && isBlank(s
)) dst
<< s
<< endl
;
94 // first non blank should start a comment
95 if (s
.find("/*")==string::npos
) { dst
<< s
<< endl
; return; }
97 // copy the header into H
101 while (getline(src
,s
) && s
.find("*/")==string::npos
) {
103 if (s
.find(exceptiontag
) != string::npos
) remove
=true;
106 // copy the header unless explicitely granted to remove it
109 for (unsigned int i
=0; i
<H
.size(); i
++) {
118 * Copy src to dst until specific line.
120 void streamCopyUntil(istream
& src
, ostream
& dst
, const string
& until
)
123 while ( getline(src
,s
) && (s
!= until
) ) dst
<< replaceClassName(s
) << endl
;
129 void streamCopy(istream
& src
, ostream
& dst
)
132 while ( getline(src
,s
)) dst
<< replaceClassName(s
) << endl
;
136 * Copy src to dst until end
138 void streamCopyUntilEnd(istream
& src
, ostream
& dst
)
141 while ( getline(src
,s
) ) dst
<< replaceClassName(s
) << endl
;
146 * Try to open an architecture file searching in various directories
148 ifstream
* open_arch_stream(const char* filename
)
150 char buffer
[FAUST_PATH_MAX
];
151 char* old
= getcwd (buffer
, FAUST_PATH_MAX
);
155 ifstream
* f
= new ifstream();
156 f
->open(filename
, ifstream::in
); if (f
->is_open()) return f
; else delete f
;
158 char *envpath
= getenv("FAUST_LIB_PATH");
160 if (chdir(envpath
)==0) {
161 ifstream
* f
= new ifstream();
162 f
->open(filename
, ifstream::in
);
163 if (f
->is_open()) return f
; else delete f
;
167 if ( (chdir(gFaustDirectory
.c_str())==0) && (chdir("architecture")==0) ) {
168 //cout << "enrobage.cpp : 'architecture' directory found in gFaustDirectory" << endl;
169 ifstream
* f
= new ifstream();
170 f
->open(filename
, ifstream::in
);
171 if (f
->good()) return f
; else delete f
;
174 if ((chdir(gFaustSuperDirectory
.c_str())==0) && (chdir("architecture")==0) ) {
175 //cout << "enrobage.cpp : 'architecture' directory found in gFaustSuperDirectory" << endl;
176 ifstream
* f
= new ifstream();
177 f
->open(filename
, ifstream::in
);
178 if (f
->good()) return f
; else delete f
;
181 if ((chdir(gFaustSuperSuperDirectory
.c_str())==0) && (chdir("architecture")==0) ) {
182 //cout << "enrobage.cpp : 'architecture' directory found in gFaustSuperSuperDirectory" << endl;
183 ifstream
* f
= new ifstream();
184 f
->open(filename
, ifstream::in
);
185 if (f
->good()) return f
; else delete f
;
188 /* Faustine directories (Karim Barkati 09/2013) */
190 #ifdef INSTALL_PREFIX
192 if (chdir(INSTALL_PREFIX
"/lib/faustine")==0) {
193 ifstream
* f
= new ifstream();
195 if (f
->good()) return f
; else delete f
;
199 if (chdir("/usr/local/lib/faustine")==0) {
200 ifstream
* f
= new ifstream();
202 if (f
->good()) return f
; else delete f
;
205 if (chdir("/usr/lib/faustine")==0) {
206 ifstream
* f
= new ifstream();
208 if (f
->good()) return f
; else delete f
;
211 /* End of Faustine directories */
214 #ifdef INSTALL_PREFIX
216 if (chdir(INSTALL_PREFIX
"/lib/faust")==0) {
217 ifstream
* f
= new ifstream();
219 if (f
->good()) return f
; else delete f
;
223 if (chdir("/usr/local/lib/faust")==0) {
224 ifstream
* f
= new ifstream();
226 if (f
->good()) return f
; else delete f
;
229 if (chdir("/usr/lib/faust")==0) {
230 ifstream
* f
= new ifstream();
232 if (f
->good()) return f
; else delete f
;
240 /*---------------------------------------------*/
243 * Check if a file exists.
244 * @return true if the file exist, false otherwise
247 bool check_file(const char* filename
)
249 FILE* f
= fopen(filename
, "r");
252 fprintf(stderr
, "faust: "); perror(filename
);
261 * Try to open the file '<dir>/<filename>'. If it succeed, it stores the full pathname
262 * of the file into <fullpath>
264 static FILE* fopenat(string
& fullpath
, const char* dir
, const char* filename
)
267 char olddirbuffer
[FAUST_PATH_MAX
];
268 char newdirbuffer
[FAUST_PATH_MAX
];
270 char* olddir
= getcwd (olddirbuffer
, FAUST_PATH_MAX
);
272 if (chdir(dir
) == 0) {
273 FILE* f
= fopen(filename
, "r");
274 fullpath
= getcwd (newdirbuffer
, FAUST_PATH_MAX
);
276 fullpath
+= filename
;
285 * Try to open the file '<dir>/<filename>'. If it succeed, it stores the full pathname
286 * of the file into <fullpath>
288 static FILE* fopenat(string
& fullpath
, const string
& dir
, const char* filename
)
290 return fopenat(fullpath
, dir
.c_str(), filename
);
294 * Try to open the file '<dir>/<path>/<filename>'. If it succeed, it stores the full pathname
295 * of the file into <fullpath>
297 static FILE* fopenat(string
& fullpath
, const string
& dir
, const char* path
, const char* filename
)
300 char olddirbuffer
[FAUST_PATH_MAX
];
301 char newdirbuffer
[FAUST_PATH_MAX
];
303 char* olddir
= getcwd (olddirbuffer
, FAUST_PATH_MAX
);
304 if (chdir(dir
.c_str()) == 0) {
305 if (chdir(path
) == 0) {
306 FILE* f
= fopen(filename
, "r");
307 fullpath
= getcwd (newdirbuffer
, FAUST_PATH_MAX
);
309 fullpath
+= filename
;
321 * Test absolute pathname.
323 static bool isAbsolutePathname(const string
& filename
)
325 //test windows absolute pathname "x:xxxxxx"
326 if (filename
.size()>1 && filename
[1] == ':') return true;
328 // test unix absolute pathname "/xxxxxx"
329 if (filename
.size()>0 && filename
[0] == '/') return true;
336 * Build a full pathname of <filename>.
337 * <fullpath> = <currentdir>/<filename>
339 static void buildFullPathname(string
& fullpath
, const char* filename
)
341 char old
[FAUST_PATH_MAX
];
343 if (isAbsolutePathname(filename
)) {
346 fullpath
= getcwd (old
, FAUST_PATH_MAX
);
348 fullpath
+= filename
;
353 * Try to open the file <filename> searching in various directories. If succesful
354 * place its full pathname in the string <fullpath>
358 FILE* fopensearch(const char* filename
, string
& fullpath
)
363 if ((f
= fopen(filename
, "r"))) {
364 buildFullPathname(fullpath
, filename
);
367 if ((f
= fopenat(fullpath
, gMasterDirectory
, filename
))) {
370 if ((envpath
= getenv("FAUST_LIB_PATH")) && (f
= fopenat(fullpath
, envpath
, filename
))) {
373 if ((f
= fopenat(fullpath
, gFaustDirectory
, "architecture", filename
))) {
376 if ((f
= fopenat(fullpath
, gFaustSuperDirectory
, "architecture", filename
))) {
379 if ((f
= fopenat(fullpath
, gFaustSuperSuperDirectory
, "architecture", filename
))) {
385 FILE* fopensearch(const char* filename
, string
& fullpath
)
390 if ((f
= fopen(filename
, "r"))) {
391 buildFullPathname(fullpath
, filename
);
394 if ((f
= fopenat(fullpath
, gMasterDirectory
, filename
))) {
397 if ((envpath
= getenv("FAUST_LIB_PATH")) && (f
= fopenat(fullpath
, envpath
, filename
))) {
400 if ((f
= fopenat(fullpath
, gFaustDirectory
, "architecture", filename
))) {
403 if ((f
= fopenat(fullpath
, gFaustSuperDirectory
, "architecture", filename
))) {
406 if ((f
= fopenat(fullpath
, gFaustSuperSuperDirectory
, "architecture", filename
))) {
410 /* Faustine directories (Haisheng WANG 09/2013) */
412 #ifdef INSTALL_PREFIX
413 if ((f
= fopenat(fullpath
, INSTALL_PREFIX
"/lib/faustine", filename
))) {
417 if ((f
= fopenat(fullpath
, "/usr/local/lib/faustine", filename
))) {
420 if ((f
= fopenat(fullpath
, "/usr/lib/faustine", filename
))) {
424 /* End of Faustine directories */
426 #ifdef INSTALL_PREFIX
427 if ((f
= fopenat(fullpath
, INSTALL_PREFIX
"/lib/faust", filename
))) {
431 if ((f
= fopenat(fullpath
, "/usr/local/lib/faust", filename
))) {
434 if ((f
= fopenat(fullpath
, "/usr/lib/faust", filename
))) {
443 * filebasename returns the basename of a path.
444 * (adapted by kb from basename.c)
446 * @param[in] The path to parse.
447 * @return The last component of the given path.
449 #ifndef DIR_SEPARATOR
450 #define DIR_SEPARATOR '/'
454 #define HAVE_DOS_BASED_FILE_SYSTEM
455 #ifndef DIR_SEPARATOR_2
456 #define DIR_SEPARATOR_2 '\\'
460 /* Define IS_DIR_SEPARATOR. */
461 #ifndef DIR_SEPARATOR_2
462 # define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
463 #else /* DIR_SEPARATOR_2 */
464 # define IS_DIR_SEPARATOR(ch) \
465 (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
466 #endif /* DIR_SEPARATOR_2 */
470 * returns a pointer on the basename part of name
472 const char* filebasename(const char* name
)
474 #if defined (HAVE_DOS_BASED_FILE_SYSTEM)
475 /* Skip over the disk name in MSDOS pathnames. */
476 if (isalpha(name
[0]) && name
[1] == ':')
481 for (base
= name
; *name
; name
++)
483 if (IS_DIR_SEPARATOR (*name
))
493 * returns a string containing the dirname of name
494 * If no dirname, returns "."
496 string
filedirname(const string
& name
)
498 const char* base
= filebasename(name
.c_str());
499 const unsigned int size
= base
-name
.c_str();
505 } else if (size
==1) {
509 for (unsigned int i
=0; i
<size
-1; i
++) {