$search
00001 #include "preprocess.hh" 00002 00003 #include <sys/types.h> 00004 #include <sys/stat.h> 00005 #include <sys/wait.h> 00006 #include <fcntl.h> 00007 #include <stdlib.h> 00008 #include <unistd.h> 00009 #include <errno.h> 00010 00011 #include <vector> 00012 00013 #include <iostream> 00014 using namespace std; 00015 00020 #ifndef STDINCPP 00021 # define STDINCPP "gcc -E -" 00022 #endif /* STDINCPP */ 00023 00024 typedef std::list<std::string> StringList; 00025 typedef std::vector<std::string> StringVector; 00026 00027 static StringVector split(const string& str, const char* char_set = " \t") 00028 { 00029 StringVector ret; 00030 00031 size_t length(str.length()); 00032 size_t begin = 0; 00033 while (begin < length) 00034 { 00035 size_t end = str.find_first_of(char_set, begin); 00036 if (end > length) 00037 end = length; 00038 00039 ret.push_back(str.substr(begin, end - begin)); 00040 begin = end + 1; 00041 } 00042 00043 return ret; 00044 } 00045 00046 std::string preprocess(const string& fichier, const StringList& options) 00047 { 00048 char tmpName[17] = "/tmp/genomXXXXXX"; 00049 00050 /* open input and output files */ 00051 int in = open(fichier.c_str(), O_RDONLY, 0); 00052 if (in < 0) { 00053 cerr << "Cannot open " << fichier << " for reading: " << strerror(errno) << endl; 00054 return string(); 00055 } 00056 00057 /* use a safe temporary file */ 00058 int out = mkstemp(tmpName); 00059 if (out < 0) { 00060 cerr << "Cannot open temporary file " << tmpName << "for writing: " << strerror(errno) << endl; 00061 return string(); 00062 } 00063 00064 /* build the argv array: split cpp into argvs and copy options */ 00065 StringVector argv = split(STDINCPP); 00066 if (argv.empty()) 00067 { 00068 cerr << "No C preprocessor specified, aborting" << endl; 00069 return string(); 00070 } 00071 argv.insert(argv.end(), options.begin(), options.end()); 00072 00073 // Convert argv into a C-style array (null terminated) 00074 int argv_size = argv.size(); 00075 char** c_argv = new char*[argv_size + 1]; 00076 for (int i = 0; i < argv_size; ++i) 00077 c_argv[i] = const_cast<char *>(argv[i].c_str()); 00078 c_argv[argv_size] = 0; 00079 00080 /* cpp output goes to stdout */ 00081 pid_t pid = fork(); 00082 if (pid == 0) { 00083 /* read stdin from nomFic */ 00084 if (dup2(in, fileno(stdin)) < 0) 00085 cerr << "Cannot redirect cpp input: " << strerror(errno) << endl; 00086 else if (dup2(out, fileno(stdout)) < 0) 00087 cerr << "Cannot redirect cpp output: " << strerror(errno) << endl; 00088 else if (execvp(c_argv[0], c_argv) == -1) 00089 { 00090 cerr << "Error running " << c_argv[0] << ": " << strerror(errno) << endl; 00091 exit(1); 00092 } 00093 } 00094 00095 // Cleanup 00096 // If we are still in the child, pid == 0 and it means 00097 // that one of the calls to dup2 or execvp failed 00098 delete[] c_argv; 00099 close(in); 00100 close(out); 00101 if (pid == 0) return string(); 00102 00103 int status; 00104 wait( &status ); 00105 if (! WIFEXITED(status) || WEXITSTATUS(status) != 0) 00106 { 00107 cerr << "C preprocessor failure" << endl; 00108 return string(); 00109 } 00110 00111 return tmpName; 00112 } /* callCpp */ 00113