// -*- Mode: C++ -*- // // CForall Version 1.0, Copyright (C) Peter A. Buhr 2002 // // cpp.cc -- // // Author : Peter A. Buhr // Created On : Thu Aug 29 12:24:06 2002 // Last Modified By : Peter A. Buhr // Last Modified On : Tue Apr 21 07:23:38 2015 // Update Count : 52 // #include #include #include // tempnam, freopen, perror #include // execvp, fork, unlink #include // wait #include "../config.h" // configure info using namespace std; //#define __DEBUG_H__ int main( int argc, char *argv[] ) { int code; int i; string arg; string bprefix; string cpp_in; string cpp_out; string cpp; string cpp_name( "gcc" ); bool CFA_flag = false; bool cpp_flag = false; bool gnu = false; const char *args[argc + 100]; // leave space for 100 additional cfa command line values int nargs = 1; // 0 => command name const char *argsCppOnly[argc]; // cpp only arguments int nargsCppOnly = 0; const char *argsCFAOnly[argc]; // CFA only arguments int nargsCFAOnly = 0; // get a name of a temporary file char *tmpfile = tempnam( NULL, "CFA" ); // storage is not freed #ifdef __DEBUG_H__ cerr << "CPP:" << endl; #endif // __DEBUG_H__ // process all the arguments for ( i = 1; i < argc; i += 1 ) { #ifdef __DEBUG_H__ cerr << "argv[" << i << "]:\"" << argv[i] << "\"" << endl; #endif // __DEBUG_H__ arg = argv[i]; #ifdef __DEBUG_H__ cerr << "arg:\"" << arg << "\"" << endl; #endif // __DEBUG_H__ if ( arg.substr(0,1) == "-" ) { if ( arg == "-D__CFA__" ) { CFA_flag = true; // strip -D__CFA__ flag } else if ( arg == "-D__CPP__" ) { cpp_flag = true; // strip -D__CPP__ flag } else if ( arg.substr(0,sizeof("-D__GNU")-1) == "-D__GNU" ) { gnu = true; // strip -D__GNUxxx flags to remove duplication } else if ( arg == "-lang-c" ) { // strip -lang-c flag } else if ( arg.substr(0,sizeof("-A")-1) == "-A" ) { // strip -A flags } else if ( arg.substr(0,sizeof("-D__STDC_HOSTED__")-1) == "-D__STDC_HOSTED__" ) { // strip this define: causes conflict } else if ( arg.substr(0,sizeof("-o")-1) == "-o" ) { i += 1; // strip -o flag and its argument } else if ( arg.substr(0,sizeof("-D__CFA_FLAG__")-1) == "-D__CFA_FLAG__" ) { argsCFAOnly[nargsCFAOnly] = ( *new string( arg.substr(sizeof("-D__CFA_FLAG__")) ) ).c_str(); // pass argument along nargsCFAOnly += 1; } else if ( arg == "-v" ) { argsCppOnly[nargsCppOnly] = argv[i]; // pass argument along nargsCppOnly += 1; } else if ( arg.substr(0,sizeof("-I")-1) == "-I" ) { argsCppOnly[nargsCppOnly] = argv[i]; // pass argument along nargsCppOnly += 1; } else if ( arg == "-C" || arg == "-P" || arg == "-H" ) { argsCppOnly[nargsCppOnly] = argv[i]; // pass argument along nargsCppOnly += 1; } else if ( arg.substr(0,sizeof("-W")-1) == "-W" ) { argsCppOnly[nargsCppOnly] = argv[i]; // pass argument along nargsCppOnly += 1; } else if ( arg == "-lint" ) { argsCppOnly[nargsCppOnly] = argv[i]; // pass argument along nargsCppOnly += 1; } else if ( arg == "-pedantic" || arg == "-pedantic-errors" ) { argsCppOnly[nargsCppOnly] = argv[i]; // pass argument along nargsCppOnly += 1; } else if ( arg == "-traditional" || arg == "-trigraphs" ) { argsCppOnly[nargsCppOnly] = argv[i]; // pass argument along nargsCppOnly += 1; } else if ( arg == "-dM" || arg == "-dD" ) { argsCppOnly[nargsCppOnly] = argv[i]; // pass argument along nargsCppOnly += 1; } else if ( arg == "-M" || arg == "-MG" || arg == "-MM" ) { argsCppOnly[nargsCppOnly] = argv[i]; // pass argument along nargsCppOnly += 1; } else if ( arg == "-MD" || arg == "-MMD" ) { argsCppOnly[nargsCppOnly] = argv[i]; // pass argument along nargsCppOnly += 1; i += 1; argsCppOnly[nargsCppOnly] = argv[i]; // pass argument along nargsCppOnly += 1; #ifdef __DEBUG_H__ cerr << "argv[" << i << "]:\"" << argv[i] << "\"" << endl; #endif // __DEBUG_H__ } else if ( arg == "-imacros" ) { argsCppOnly[nargsCppOnly] = argv[i]; // pass argument along nargsCppOnly += 1; i += 1; argsCppOnly[nargsCppOnly] = argv[i]; // pass argument along nargsCppOnly += 1; #ifdef __DEBUG_H__ cerr << "argv[" << i << "]:\"" << argv[i] << "\"" << endl; #endif // __DEBUG_H__ } else if ( arg == "-include" ) { argsCppOnly[nargsCppOnly] = argv[i]; // pass argument along nargsCppOnly += 1; i += 1; argsCppOnly[nargsCppOnly] = argv[i]; // pass argument along nargsCppOnly += 1; #ifdef __DEBUG_H__ cerr << "argv[" << i << "]:\"" << argv[i] << "\"" << endl; #endif // __DEBUG_H__ } else if ( arg == "-idirafter" ) { argsCppOnly[nargsCppOnly] = argv[i]; // pass argument along nargsCppOnly += 1; i += 1; argsCppOnly[nargsCppOnly] = argv[i]; // pass argument along nargsCppOnly += 1; #ifdef __DEBUG_H__ cerr << "argv[" << i << "]:\"" << argv[i] << "\"" << endl; #endif // __DEBUG_H__ } else if ( arg == "-iprefix" ) { argsCppOnly[nargsCppOnly] = argv[i]; // pass argument along nargsCppOnly += 1; i += 1; argsCppOnly[nargsCppOnly] = argv[i]; // pass argument along nargsCppOnly += 1; #ifdef __DEBUG_H__ cerr << "argv[" << i << "]:\"" << argv[i] << "\"" << endl; #endif // __DEBUG_H__ } else if ( arg == "-iwithprefix" ) { argsCppOnly[nargsCppOnly] = argv[i]; // pass argument along nargsCppOnly += 1; i += 1; argsCppOnly[nargsCppOnly] = argv[i]; // pass argument along nargsCppOnly += 1; #ifdef __DEBUG_H__ cerr << "argv[" << i << "]:\"" << argv[i] << "\"" << endl; #endif // __DEBUG_H__ } else if ( arg == "-isystem" ) { argsCppOnly[nargsCppOnly] = argv[i]; // pass argument along nargsCppOnly += 1; i += 1; argsCppOnly[nargsCppOnly] = argv[i]; // pass argument along nargsCppOnly += 1; #ifdef __DEBUG_H__ cerr << "argv[" << i << "]:\"" << argv[i] << "\"" << endl; #endif // __DEBUG_H__ } else if ( arg.substr(0,sizeof("-D__GCC_BPREFIX__")-1) == "-D__GCC_BPREFIX__" ) { bprefix = arg.substr(sizeof("-D__GCC_BPREFIX__")); } else if ( arg.substr(0,sizeof("-D__GCC_MACHINE__")-1) == "-D__GCC_MACHINE__" ) { argsCppOnly[nargsCppOnly] = "-b"; // pass argument along nargsCppOnly += 1; argsCppOnly[nargsCppOnly] = ( *new string(arg.substr(sizeof("-D__GCC_MACHINE__")) ) ).c_str(); // pass argument along nargsCppOnly += 1; } else if ( arg.substr(0,sizeof("-D__GCC_VERSION__")-1) == "-D__GCC_VERSION__" ) { argsCppOnly[nargsCppOnly] = "-V"; // pass argument along nargsCppOnly += 1; argsCppOnly[nargsCppOnly] = ( *new string( arg.substr(sizeof("-D__GCC_VERSION__")) ) ).c_str(); // pass argument along nargsCppOnly += 1; } else if ( arg.substr(0,sizeof("-D__CPP_NAME__")-1) == "-D__CPP_NAME__" ) { cpp_name = arg.substr(sizeof("-D__CPP_NAME__")); } else if ( arg.substr(1,1) != "+" ) { args[nargs] = argv[i]; // pass argument along nargs += 1; } // if } else { if ( cpp_in.length() == 0 ) { cpp_in = arg; #ifdef __DEBUG_H__ cerr << "cpp_in:\"" << cpp_in << "\"" << endl; #endif // __DEBUG_H__ } else if ( cpp_out.length() == 0 ) { cpp_out = arg; #ifdef __DEBUG_H__ cerr << "cpp_out:\"" << cpp_out << "\""<< endl; #endif // __DEBUG_H__ } else { cerr << "Usage: " << argv[0] << " input-file [output-file] [options]" << endl; exit( 1 ); } // if } // if } // for argsCppOnly[nargsCppOnly] = "-D__cplusplus"; nargsCppOnly += 1; if ( cpp_in.length() == 0 ) { cerr << "Usage: " << argv[0] << " input-file [output-file] [options]" << endl; exit( 1 ); } // if if ( cpp_flag && CFA_flag ) { cerr << argv[0] << " Error cannot use -E and -CFA flags together." << endl; exit( EXIT_FAILURE ); } // if // The -E flag is specified so only run the preprocessor and output is // written to standard output. // // OR // // The preprocessor is called internally during compilation, probably by // "collect" during linking to compile some ctor/dtor code. In this case, // the cfa-cpp preprocessor is not run. Output is redirected to cpp_out if ( cpp_flag || bprefix.length() == 0 ) { if ( ! cpp_flag ) { if ( freopen( cpp_out.c_str(), "w", stdout ) == NULL ) { // redirect stdout if not -E cerr << argv[0] << ": Error can't write to " << cpp_out << endl; exit( EXIT_FAILURE ); } // if // If called by collect, must prevent the compiler from recursively // calling this cpp through the -B path. To stop the recursion, // sent the COMPILER_PATH environment variable to the NULL string, // which removes the -B path supplied on the initial cfa command. if ( gnu ) { putenv( "COMPILER_PATH=" ); } // if } // if if ( bprefix.length() == 0 ) { // collect ? args[0] = "gcc"; // use gcc } else { args[0] = cpp_name.c_str(); } // if args[nargs] = "-E"; nargs += 1; for ( i = 0; i < nargsCppOnly; i += 1 ) { // copy cpp only arguments args[nargs] = argsCppOnly[i]; nargs += 1; } // if args[nargs] = cpp_in.c_str(); nargs += 1; args[nargs] = NULL; // terminate argument list #ifdef __DEBUG_H__ cerr << "nargs: " << nargs << endl; for ( i = 0; args[i] != NULL; i += 1 ) { cerr << args[i] << " "; } // for cerr << endl; #endif // __DEBUG_H__ execvp( args[0], (char *const *)args ); // should not return perror( "CFA translator error: cpp level, exec" ); exit( EXIT_FAILURE ); } // if // Run the C preprocessor and save the output in tmpfile. if ( fork() == 0 ) { // child process ? if ( freopen( tmpfile, "w", stdout ) == NULL) { // redirect output to tmpfile cerr << argv[0] << ": Error can't write to " << tmpfile << endl; exit( EXIT_FAILURE ); } // if args[0] = cpp_name.c_str(); args[nargs] = "-E"; nargs += 1; for ( i = 0; i < nargsCppOnly; i += 1 ) { // copy cpp only arguments args[nargs] = argsCppOnly[i]; nargs += 1; } // if args[nargs] = cpp_in.c_str(); nargs += 1; args[nargs] = NULL; // terminate argument list #ifdef __DEBUG_H__ cerr << "cpp nargs: " << nargs << endl; for ( i = 0; args[i] != NULL; i += 1 ) { cerr << args[i] << " "; } // for cerr << endl; #endif // __DEBUG_H__ execvp( args[0], (char *const *)args ); // should not return perror( "CFA translator error: cpp level, exec" ); exit( EXIT_FAILURE ); } // if wait( &code ); // wait for child to finish if ( WIFSIGNALED(code) != 0 ) { // child completed successfully ? unlink( tmpfile ); cerr << "CFA translator error: cpp failed with signal " << WTERMSIG(code) << endl; exit( EXIT_FAILURE ); } // if // If -CFA flag specified, run the cfa-cpp preprocessor on the temporary // file, and output is written to standard output. Otherwise, run the // cfa-cpp preprocessor on the temporary file and save the result into the // output file. if ( fork() == 0 ) { // child process ? args[0] = ( *new string( bprefix + "/cfa-cpp" ) ).c_str(); for ( i = 0; i < nargsCFAOnly; i += 1 ) { // copy CFA only arguments args[nargs] = argsCFAOnly[i]; nargs += 1; } // if args[nargs] = "-p"; nargs += 1; args[nargs] = tmpfile; nargs += 1; if ( ! CFA_flag ) { // run cfa-cpp ? args[nargs] = cpp_out.c_str(); nargs += 1; } // if args[nargs] = NULL; // terminate argument list #ifdef __DEBUG_H__ cerr << "cfa-cpp nargs: " << nargs << endl; for ( i = 0; args[i] != NULL; i += 1 ) { cerr << args[i] << " "; } // for cerr << endl; #endif // __DEBUG_H__ execvp( args[0], (char *const *)args ); // should not return perror( "CFA translator error: cpp level, exec" ); } // if wait( &code ); // wait for child to finish if ( unlink( tmpfile ) == -1 ) { cerr << "CFA translator error: cfa-cpp failed " << errno << " to remove temporary file \"" << tmpfile << "\"" << endl; exit( EXIT_FAILURE ); } // if if ( WIFSIGNALED(code) != 0 ) { // child completed successfully ? cerr << "CFA translator error: cfa-cpp failed with signal " << WTERMSIG(code) << endl; exit( EXIT_FAILURE ); } // if if ( CFA_flag ) { // -CFA flag ? exit( EXIT_FAILURE ); // tell gcc not to go any further } else { exit( WEXITSTATUS(code) ); } // if } // main // Local Variables: // // compile-command: "gmake" // // End: //