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
;
187 #ifdef INSTALL_PREFIX
189 if (chdir(INSTALL_PREFIX
"/lib/faust")==0) {
190 ifstream
* f
= new ifstream();
192 if (f
->good()) return f
; else delete f
;
196 if (chdir("/usr/local/lib/faust")==0) {
197 ifstream
* f
= new ifstream();
199 if (f
->good()) return f
; else delete f
;
202 if (chdir("/usr/lib/faust")==0) {
203 ifstream
* f
= new ifstream();
205 if (f
->good()) return f
; else delete f
;
213 /*---------------------------------------------*/
216 * Check if a file exists.
217 * @return true if the file exist, false otherwise
220 bool check_file(const char* filename
)
222 FILE* f
= fopen(filename
, "r");
225 fprintf(stderr
, "faust: "); perror(filename
);
234 * Try to open the file '<dir>/<filename>'. If it succeed, it stores the full pathname
235 * of the file into <fullpath>
237 static FILE* fopenat(string
& fullpath
, const char* dir
, const char* filename
)
240 char olddirbuffer
[FAUST_PATH_MAX
];
241 char newdirbuffer
[FAUST_PATH_MAX
];
243 char* olddir
= getcwd (olddirbuffer
, FAUST_PATH_MAX
);
245 if (chdir(dir
) == 0) {
246 FILE* f
= fopen(filename
, "r");
247 fullpath
= getcwd (newdirbuffer
, FAUST_PATH_MAX
);
249 fullpath
+= filename
;
258 * Try to open the file '<dir>/<filename>'. If it succeed, it stores the full pathname
259 * of the file into <fullpath>
261 static FILE* fopenat(string
& fullpath
, const string
& dir
, const char* filename
)
263 return fopenat(fullpath
, dir
.c_str(), filename
);
267 * Try to open the file '<dir>/<path>/<filename>'. If it succeed, it stores the full pathname
268 * of the file into <fullpath>
270 static FILE* fopenat(string
& fullpath
, const string
& dir
, const char* path
, const char* filename
)
273 char olddirbuffer
[FAUST_PATH_MAX
];
274 char newdirbuffer
[FAUST_PATH_MAX
];
276 char* olddir
= getcwd (olddirbuffer
, FAUST_PATH_MAX
);
277 if (chdir(dir
.c_str()) == 0) {
278 if (chdir(path
) == 0) {
279 FILE* f
= fopen(filename
, "r");
280 fullpath
= getcwd (newdirbuffer
, FAUST_PATH_MAX
);
282 fullpath
+= filename
;
294 * Test absolute pathname.
296 static bool isAbsolutePathname(const string
& filename
)
298 //test windows absolute pathname "x:xxxxxx"
299 if (filename
.size()>1 && filename
[1] == ':') return true;
301 // test unix absolute pathname "/xxxxxx"
302 if (filename
.size()>0 && filename
[0] == '/') return true;
309 * Build a full pathname of <filename>.
310 * <fullpath> = <currentdir>/<filename>
312 static void buildFullPathname(string
& fullpath
, const char* filename
)
314 char old
[FAUST_PATH_MAX
];
316 if (isAbsolutePathname(filename
)) {
319 fullpath
= getcwd (old
, FAUST_PATH_MAX
);
321 fullpath
+= filename
;
326 * Try to open the file <filename> searching in various directories. If succesful
327 * place its full pathname in the string <fullpath>
331 FILE* fopensearch(const char* filename
, string
& fullpath
)
336 if ((f
= fopen(filename
, "r"))) {
337 buildFullPathname(fullpath
, filename
);
340 if ((f
= fopenat(fullpath
, gMasterDirectory
, filename
))) {
343 if ((envpath
= getenv("FAUST_LIB_PATH")) && (f
= fopenat(fullpath
, envpath
, filename
))) {
346 if ((f
= fopenat(fullpath
, gFaustDirectory
, "architecture", filename
))) {
349 if ((f
= fopenat(fullpath
, gFaustSuperDirectory
, "architecture", filename
))) {
352 if ((f
= fopenat(fullpath
, gFaustSuperSuperDirectory
, "architecture", filename
))) {
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
))) {
382 #ifdef INSTALL_PREFIX
383 if ((f
= fopenat(fullpath
, INSTALL_PREFIX
"/lib/faust", filename
))) {
387 if ((f
= fopenat(fullpath
, "/usr/local/lib/faust", filename
))) {
390 if ((f
= fopenat(fullpath
, "/usr/lib/faust", filename
))) {
399 * filebasename returns the basename of a path.
400 * (adapted by kb from basename.c)
402 * @param[in] The path to parse.
403 * @return The last component of the given path.
405 #ifndef DIR_SEPARATOR
406 #define DIR_SEPARATOR '/'
410 #define HAVE_DOS_BASED_FILE_SYSTEM
411 #ifndef DIR_SEPARATOR_2
412 #define DIR_SEPARATOR_2 '\\'
416 /* Define IS_DIR_SEPARATOR. */
417 #ifndef DIR_SEPARATOR_2
418 # define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
419 #else /* DIR_SEPARATOR_2 */
420 # define IS_DIR_SEPARATOR(ch) \
421 (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
422 #endif /* DIR_SEPARATOR_2 */
426 * returns a pointer on the basename part of name
428 const char* filebasename(const char* name
)
430 #if defined (HAVE_DOS_BASED_FILE_SYSTEM)
431 /* Skip over the disk name in MSDOS pathnames. */
432 if (isalpha(name
[0]) && name
[1] == ':')
437 for (base
= name
; *name
; name
++)
439 if (IS_DIR_SEPARATOR (*name
))
449 * returns a string containing the dirname of name
450 * If no dirname, returns "."
452 string
filedirname(const string
& name
)
454 const char* base
= filebasename(name
.c_str());
455 const unsigned int size
= base
-name
.c_str();
461 } else if (size
==1) {
465 for (unsigned int i
=0; i
<size
-1; i
++) {