preprocess.cc
Go to the documentation of this file.
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 


typelib
Author(s): Sylvain Joyeux/sylvain.joyeux@m4x.org
autogenerated on Thu Jan 2 2014 11:38:41