FAUST compiler  0.9.9.6b8
enrobage.cpp
Go to the documentation of this file.
1 /************************************************************************
2  ************************************************************************
3  FAUST compiler
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.
10 
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.
15 
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  ************************************************************************/
21 
22 #include "enrobage.hh"
23 #include <vector>
24 #include <list>
25 #include <set>
26 #include <string>
27 #include <ctype.h>
28 #include <limits.h>
29 #include <stdlib.h>
30 #include "compatibility.hh"
31 #include "sourcefetcher.hh"
32 #include <errno.h>
33 #include <climits>
34 
35 extern string gFaustSuperSuperDirectory;
36 extern string gFaustSuperDirectory;
37 extern string gFaustDirectory;
38 extern string gMasterDirectory;
39 extern string gClassName;
40 extern bool gInlineArchSwitch;
41 extern list<string> gImportDirList; // path to search for imports, components and libraries
42 
43 //----------------------------------------------------------------
44 
48 static bool isBlank(const string& s) {
49  for (size_t i=0; i<s.size(); i++) {
50  if (s[i] != ' ' && s[i] != '\t') return false;
51  }
52  return true;
53 }
54 
59 static string& replaceOccurences(string& str, const string& oldstr, const string& newstr)
60 {
61  string::size_type l1 = oldstr.length();
62  string::size_type l2 = newstr.length();
63 
64  string::size_type pos = str.find(oldstr);
65  while (pos != string::npos) {
66  str.replace(pos, l1, newstr);
67  pos = str.find(oldstr, pos + l2);
68  }
69  return str;
70 }
71 
76 static string& replaceClassName(string& str)
77 {
78  return replaceOccurences(str, "mydsp", gClassName);
79 }
80 
87 void streamCopyLicense(istream& src, ostream& dst, const string& exceptiontag)
88 {
89  string s;
90  vector<string> H;
91 
92  // skip blank lines
93  while (getline(src,s) && isBlank(s)) dst << s << endl;
94 
95  // first non blank should start a comment
96  if (s.find("/*")==string::npos) { dst << s << endl; return; }
97 
98  // copy the header into H
99  bool remove = false;
100  H.push_back(s);
101 
102  while (getline(src,s) && s.find("*/") == string::npos) {
103  H.push_back(s);
104  if (s.find(exceptiontag) != string::npos) remove=true;
105  }
106 
107  // copy the header unless explicitely granted to remove it
108  if (!remove) {
109  // copy the header
110  for (unsigned int i=0; i<H.size(); i++) {
111  dst << H[i] << endl;
112  }
113  dst << s << endl;
114  }
115 }
116 
121 class myparser
122 {
123  string str;
124  size_t N;
125  size_t p;
126 public:
127  myparser(const string& s) : str(s), N(s.length()), p(0) {}
128  bool skip() { while ( p<N && isspace(str[p]) ) p++; return true; }
129  bool parse(const string& s) { bool f; if ((f = (p == str.find(s, p)))) p += s.length(); return f; }
130  bool filename(string& fname) {
131  size_t saved = p;
132  if (p<N) {
133  char c = str[p++];
134  if (c== '<' | c=='"') {
135  fname = "";
136  while ( p<N && (str[p] != '>') && (str[p] != '"')) fname += str[p++];
137  p++;
138  return true;
139  }
140  }
141  p = saved;
142  return false;
143  }
144 };
145 
149 bool isFaustInclude(const string& s, string& fname)
150 {
151  myparser P(s);
152  if ( P.skip() && P.parse("#include") && P.skip() && P.filename(fname) ) {
153  myparser Q(fname);
154  return Q.parse("faust/");
155  } else {
156  return false;
157  }
158 }
159 
164 // to keep track of already injected files
165 set<string> alreadyIncluded;
166 
167 void inject(ostream& dst, const string fname)
168 {
169  if (alreadyIncluded.find(fname) == alreadyIncluded.end()) {
170  alreadyIncluded.insert(fname);
171  istream* src = open_arch_stream( fname.c_str());
172  if (src) {
173  streamCopy(*src, dst);
174  } else {
175  cerr << "NOT FOUND " << fname << endl;
176  }
177  }
178 }
179 
183 void streamCopyUntil(istream& src, ostream& dst, const string& until)
184 {
185  string s;
186  string fname;
187  while ( getline(src,s) && (s != until) ) {
188  if (gInlineArchSwitch && isFaustInclude(s, fname)) {
189  inject(dst, fname);
190  } else {
191  dst << replaceClassName(s) << endl;
192  }
193  }
194 }
195 
199 void streamCopy(istream& src, ostream& dst)
200 {
201  streamCopyUntil(src, dst, "<<<FOBIDDEN LINE IN A FAUST ARCHITECTURE FILE>>>");
202 }
203 
207 void streamCopyUntilEnd(istream& src, ostream& dst)
208 {
209  streamCopyUntil(src, dst, "<<<FOBIDDEN LINE IN A FAUST ARCHITECTURE FILE>>>");
210 }
211 
212 #define TRY_OPEN(filename) \
213  ifstream* f = new ifstream(); \
214  f->open(filename, ifstream::in); \
215  if (f->is_open()) return f; else delete f; \
216 
217 
220 ifstream* open_arch_stream(const char* filename)
221 {
222  char buffer[FAUST_PATH_MAX];
223  char* old = getcwd (buffer, FAUST_PATH_MAX);
224  int err;
225 
226  TRY_OPEN(filename);
227 
228  char *envpath = getenv("FAUST_LIB_PATH");
229  if (envpath!=NULL) {
230  if (chdir(envpath)==0) {
231  TRY_OPEN(filename);
232  }
233  }
234  err = chdir(old);
235  if ( (chdir(gFaustDirectory.c_str())==0) && (chdir("architecture")==0) ) {
236  //cout << "enrobage.cpp : 'architecture' directory found in gFaustDirectory" << endl;
237  TRY_OPEN(filename);
238  }
239  err = chdir(old);
240  if ((chdir(gFaustSuperDirectory.c_str())==0) && (chdir("architecture")==0) ) {
241  //cout << "enrobage.cpp : 'architecture' directory found in gFaustSuperDirectory" << endl;
242  TRY_OPEN(filename);
243  }
244  err = chdir(old);
245  if ((chdir(gFaustSuperSuperDirectory.c_str())==0) && (chdir("architecture")==0) ) {
246  //cout << "enrobage.cpp : 'architecture' directory found in gFaustSuperSuperDirectory" << endl;
247  TRY_OPEN(filename);
248  }
249 #ifdef INSTALL_PREFIX
250  err = chdir(old);
251  if (chdir(INSTALL_PREFIX "/lib64/faust")==0) {
252  TRY_OPEN(filename);
253  }
254  err = chdir(old);
255  if (chdir(INSTALL_PREFIX "/include")==0) {
256  TRY_OPEN(filename);
257  }
258 #endif
259  err = chdir(old);
260  if (chdir("/usr/local/lib64/faust")==0) {
261  TRY_OPEN(filename);
262  }
263  err = chdir(old);
264  if (chdir("/usr/lib64/faust")==0) {
265  TRY_OPEN(filename);
266  }
267  err = chdir(old);
268  if (chdir("/usr/local/include")==0) {
269  TRY_OPEN(filename);
270  }
271  err = chdir(old);
272  if (chdir("/usr/include")==0) {
273  TRY_OPEN(filename);
274  }
275 
276  return 0;
277 }
278 
279 /*---------------------------------------------*/
280 
281 const char* strip_start(const char* filename)
282 {
283  const char* start = "file://";
284  if (strstr(filename, start) != NULL) {
285  return &filename[strlen(start)];
286  } else {
287  return filename;
288  }
289 }
290 
296 bool check_url(const char* filename)
297 {
298  char* fileBuf = 0;
299 
300  // Tries to open as an URL for a local file
301  if (strstr(filename, "file://") != 0) {
302  // Tries to open as a regular file after removing 'file://'
303  FILE* f = fopen(&filename[7], "r");
304  if (f) {
305  fclose(f);
306  return true;
307  } else {
308  cerr << "ERROR : cannot open file '" << filename << "' : " << strerror(errno) << "; for help type \"faust --help\"" << endl;
309  return false;
310  }
311 
312  // Tries to open as a http URL
313  } else if (strstr(filename, "http://") != 0) {
314  if (http_fetch(filename, &fileBuf) != -1) {
315  return true;
316  } else {
317  cerr << "ERROR : unable to access URL '" << filename << "' : " << http_strerror() << "; for help type \"faust --help\"" << endl;
318  return false;
319  }
320  } else {
321  // Otherwise tries to open as a regular file
322  FILE* f = fopen(filename, "r");
323  if (f) {
324  fclose(f);
325  return true;
326  } else {
327  cerr << "ERROR : cannot open file '" << filename << "' : " << strerror(errno) << "; for help type \"faust --help\"" << endl;
328  return false;
329  }
330  }
331 }
332 
337 static FILE* fopenat(string& fullpath, const char* dir, const char* filename)
338 {
339  int err;
340  char olddirbuffer[FAUST_PATH_MAX];
341  char newdirbuffer[FAUST_PATH_MAX];
342 
343  char* olddir = getcwd (olddirbuffer, FAUST_PATH_MAX);
344 
345  if (chdir(dir) == 0) {
346  FILE* f = fopen(filename, "r");
347  fullpath = getcwd (newdirbuffer, FAUST_PATH_MAX);
348  fullpath += '/';
349  fullpath += filename;
350  err = chdir(olddir);
351  return f;
352  }
353  err = chdir(olddir);
354  return 0;
355 }
356 
357 
362 static FILE* fopenat(string& fullpath, const string& dir, const char* filename)
363 {
364  return fopenat(fullpath, dir.c_str(), filename);
365 }
366 
371 static FILE* fopenat(string& fullpath, const string& dir, const char* path, const char* filename)
372 {
373  int err;
374  char olddirbuffer[FAUST_PATH_MAX];
375  char newdirbuffer[FAUST_PATH_MAX];
376 
377  char* olddir = getcwd (olddirbuffer, FAUST_PATH_MAX);
378 
379  if (chdir(dir.c_str()) == 0) {
380  if (chdir(path) == 0) {
381  FILE* f = fopen(filename, "r");
382  fullpath = getcwd (newdirbuffer, FAUST_PATH_MAX);
383  fullpath += '/';
384  fullpath += filename;
385  err = chdir(olddir);
386  return f;
387  }
388  }
389  err = chdir(olddir);
390  return 0;
391 }
392 
396 static bool isAbsolutePathname(const string& filename)
397 {
398  //test windows absolute pathname "x:xxxxxx"
399  if (filename.size()>1 && filename[1] == ':') return true;
400 
401  // test unix absolute pathname "/xxxxxx"
402  if (filename.size()>0 && filename[0] == '/') return true;
403 
404  return false;
405 }
406 
407 
412 static void buildFullPathname(string& fullpath, const char* filename)
413 {
414  char old[FAUST_PATH_MAX];
415 
416  if (isAbsolutePathname(filename)) {
417  fullpath = filename;
418  } else {
419  fullpath = getcwd (old, FAUST_PATH_MAX);
420  fullpath += '/';
421  fullpath += filename;
422  }
423 }
424 
430 #ifdef WIN32
431 FILE* fopensearch(const char* filename, string& fullpath)
432 {
433  FILE* f;
434  char* envpath;
435 
436  if ((f = fopen(filename, "r"))) {
437  buildFullPathname(fullpath, filename);
438  return f;
439  }
440  if ((f = fopenat(fullpath, gMasterDirectory, filename))) {
441  return f;
442  }
443  if ((envpath = getenv("FAUST_LIB_PATH")) && (f = fopenat(fullpath, envpath, filename))) {
444  return f;
445  }
446  if ((f = fopenat(fullpath, gFaustDirectory, "architecture", filename))) {
447  return f;
448  }
449  if ((f = fopenat(fullpath, gFaustSuperDirectory, "architecture", filename))) {
450  return f;
451  }
452  if ((f = fopenat(fullpath, gFaustSuperSuperDirectory, "architecture", filename))) {
453  return f;
454  }
455  return 0;
456 }
457 #else
458 FILE* fopensearch(const char* filename, string& fullpath)
459 {
460  FILE* f;
461  char* envpath;
462 
463 
464  // search in current directory
465 
466  if ((f = fopen(filename, "r"))) {
467  buildFullPathname(fullpath, filename);
468  return f;
469  }
470 
471  // search file in user supplied directory path
472 
473  for (list< string >::iterator i = gImportDirList.begin(); i != gImportDirList.end(); i++) {
474  if ((f = fopenat(fullpath, *i, filename))) {
475  //std::cerr << "found file : " << fullpath << std::endl;
476  return f;
477  }
478  }
479 
480 
481  // search in default directories
482 
483  if ((f = fopenat(fullpath, gMasterDirectory, filename))) {
484  return f;
485  }
486  if ((envpath = getenv("FAUST_LIB_PATH")) && (f = fopenat(fullpath, envpath, filename))) {
487  return f;
488  }
489  if ((f = fopenat(fullpath, gFaustDirectory, "architecture", filename))) {
490  return f;
491  }
492  if ((f = fopenat(fullpath, gFaustSuperDirectory, "architecture", filename))) {
493  return f;
494  }
495  if ((f = fopenat(fullpath, gFaustSuperSuperDirectory, "architecture", filename))) {
496  return f;
497  }
498 #ifdef INSTALL_PREFIX
499  if ((f = fopenat(fullpath, INSTALL_PREFIX "/lib64/faust", filename))) {
500  return f;
501  }
502 #endif
503  if ((f = fopenat(fullpath, "/usr/local/lib64/faust", filename))) {
504  return f;
505  }
506  if ((f = fopenat(fullpath, "/usr/lib64/faust", filename))) {
507  return f;
508  }
509  return 0;
510 }
511 #endif
512 
513 
521 #ifndef DIR_SEPARATOR
522 #define DIR_SEPARATOR '/'
523 #endif
524 
525 #ifdef WIN32
526 #define HAVE_DOS_BASED_FILE_SYSTEM
527 #ifndef DIR_SEPARATOR_2
528 #define DIR_SEPARATOR_2 '\\'
529 #endif
530 #endif
531 
532 /* Define IS_DIR_SEPARATOR. */
533 #ifndef DIR_SEPARATOR_2
534 # define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
535 #else /* DIR_SEPARATOR_2 */
536 # define IS_DIR_SEPARATOR(ch) \
537 (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
538 #endif /* DIR_SEPARATOR_2 */
539 
540 
544 const char* filebasename(const char* name)
545 {
546 #if defined (HAVE_DOS_BASED_FILE_SYSTEM)
547  /* Skip over the disk name in MSDOS pathnames. */
548  if (isalpha(name[0]) && name[1] == ':')
549  name += 2;
550 #endif
551 
552  const char* base;
553  for (base = name; *name; name++)
554  {
555  if (IS_DIR_SEPARATOR (*name))
556  {
557  base = name + 1;
558  }
559  }
560  return base;
561 }
562 
563 
568 string filedirname(const string& name)
569 {
570  const char* base = filebasename(name.c_str());
571  const unsigned int size = (const unsigned int)(base-name.c_str());
572  string dirname;
573 
574  if (size==0) {
575  dirname += '.';
576 
577  } else if (size==1) {
578  dirname += name[0];
579 
580  } else {
581  for (unsigned int i=0; i<size-1; i++) {
582  dirname += name[i];
583  }
584  }
585  return dirname;
586 }
string gClassName
Definition: main.cpp:158
string gMasterDirectory
Definition: main.cpp:105
string gFaustSuperSuperDirectory
Definition: main.cpp:101
bool gInlineArchSwitch
Definition: main.cpp:156
set< string > alreadyIncluded
Inject file fname into dst ostream if not already done.
Definition: enrobage.cpp:165
bool isFaustInclude(const string &s, string &fname)
True if string s match '#include '.
Definition: enrobage.cpp:149
void inject(ostream &dst, const string fname)
Definition: enrobage.cpp:167
A minimalistic parser used to recognize '#include ' patterns when copying architecture fil...
Definition: enrobage.cpp:121
size_t p
Definition: enrobage.cpp:125
const char * http_strerror()
void streamCopyUntil(istream &src, ostream &dst, const string &until)
Copy src to dst until specific line.
Definition: enrobage.cpp:183
#define IS_DIR_SEPARATOR(ch)
Definition: enrobage.cpp:534
ifstream * open_arch_stream(const char *filename)
Try to open an architecture file searching in various directories.
Definition: enrobage.cpp:220
string gFaustDirectory
Definition: main.cpp:103
static string & replaceOccurences(string &str, const string &oldstr, const string &newstr)
Replace every occurrence of oldstr by newstr inside str.
Definition: enrobage.cpp:59
void streamCopyLicense(istream &src, ostream &dst, const string &exceptiontag)
Copy or remove license header.
Definition: enrobage.cpp:87
#define TRY_OPEN(filename)
Definition: enrobage.cpp:212
bool filename(string &fname)
Definition: enrobage.cpp:130
static bool isAbsolutePathname(const string &filename)
Test absolute pathname.
Definition: enrobage.cpp:396
void streamCopyUntilEnd(istream &src, ostream &dst)
Copy src to dst until end.
Definition: enrobage.cpp:207
static void buildFullPathname(string &fullpath, const char *filename)
Build a full pathname of .
Definition: enrobage.cpp:412
static bool isBlank(const string &s)
Returns true is a line is blank (contains only white caracters)
Definition: enrobage.cpp:48
const char * filebasename(const char *name)
returns a pointer on the basename part of name
Definition: enrobage.cpp:544
bool check_url(const char *filename)
Check if an URL exists.
Definition: enrobage.cpp:296
FILE * fopensearch(const char *filename, string &fullpath)
Try to open the file searching in various directories.
Definition: enrobage.cpp:458
int http_fetch(const char *url_tmp, char **fileBuf)
void streamCopy(istream &src, ostream &dst)
Copy src to dst.
Definition: enrobage.cpp:199
const char * name(Symbol *sym)
Returns the name of a symbol.
Definition: symbol.hh:98
myparser(const string &s)
Definition: enrobage.cpp:127
size_t N
Definition: enrobage.cpp:124
string filedirname(const string &name)
returns a string containing the dirname of name If no dirname, returns "."
Definition: enrobage.cpp:568
bool skip()
Definition: enrobage.cpp:128
static FILE * fopenat(string &fullpath, const char *dir, const char *filename)
Try to open the file '/'.
Definition: enrobage.cpp:337
const char * strip_start(const char *filename)
Definition: enrobage.cpp:281
list< string > gImportDirList
Definition: main.cpp:161
bool parse(const string &s)
Definition: enrobage.cpp:129
string gFaustSuperDirectory
Definition: main.cpp:102
#define FAUST_PATH_MAX
string str
Definition: enrobage.cpp:123
static string & replaceClassName(string &str)
Used when copying architecture files to replace default mydsp class name with the user specified one...
Definition: enrobage.cpp:76