/* This file is part of hugin. hugin is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. hugin is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with hugin. If not, see . */ /** * @file Makefile.cpp * @brief * Created on: May 25, 2010 * @author Florian Achleitner */ #include "Makefile.h" #include "MakefileItem.h" namespace makefile { // intialize static singelton instance pointer Makefile* Makefile::instance = NULL; // static /// Used for numeric output to get a decimal dot anyways. const std::locale Makefile::locale(std::locale("C")); const std::locale GetMakefileLocale() { return Makefile::locale; }; Makefile& Makefile::getSingleton() { if(!instance) instance = new Makefile(); return *instance; } void Makefile::clean() { if(instance) delete instance; instance = NULL; } void Makefile::remove(MakefileItem* item) { if(instance && !instance->written) { std::cerr << "WARNING: A MakefileItem was removed before the Makefile::writeMakefile() was called.\n" "This is likely to be a programming error (out of scope?)" << std::endl; } clean(); } //#define WIN32 /** * Quotes and escapes characters using regular expressions. Two modes are currently distinguished, * depending on the usage of the string. * The regular expressions need a lot of backslash escaping, eg. \\\\ means backslash. We need to get * through the compiler and the boost::regex library with the special characters * * The replacements in detail: * - Shell mode * - WIN32: $ --> $$, \ --> /, # --> \#, and surround with quotes * - others: $ --> \$$, [\ ~"|'`{}[]()*#:=&] --> escape with backslash * - Make mode * - WIN32: $ --> $$, [ #=] --> escape with backslash * - others: $ --> $$, [ #:=] --> escape with backslash * * All replacements take care of variable references and do not replace $(varname) patterns. * * @note src/hugin_base/hugin_utils/platform.h is where the information is from. * Unfortunately there are lots of comments in that code, which say that the correctness * of the escaping rules is rather unsure. * * @param in Input string. * @param mode switch. * @return A new string containing the processed content. */ string Makefile::quote(const string& in, Makefile::QuoteMode mode) { regex toescape; string output; switch(mode) { case Makefile::SHELL: #ifdef WIN32 toescape.assign(cstr("(\\$[^\\(])|(\\\\)|(\\#)")); // uses a nice regex feature "recursive expressions" for doing it all in one (subexpression) cascade. output.assign(cstr("(?1\\$$&)(?2/)(?3\\\\$&)")); return string(cstr("\"") + boost::regex_replace(in, toescape, output, boost::match_default | boost::format_all) + cstr("\"")); #else // because parenthesis are replaced too, the first pattern detects variable references and passes them unchanged. toescape.assign(cstr("(\\$\\([^\\)]+\\))|(\\$)|([\\\\ \\~\"\\|\\'\\`\\{\\}\\[\\]\\(\\)\\*\\#\\:\\=\\&])")); output.assign(cstr("(?1$&)(?2\\\\\\$$&)(?3\\\\$&)")); return boost::regex_replace(in, toescape, output, boost::match_default | boost::format_all); #endif break; case Makefile::MAKE: #ifdef WIN32 toescape.assign(cstr("(\\$[^\\(])|(\\\\)|([ \\#\\=])")); output.assign(cstr("(?1\\$$&)(?2/)(?3\\\\$&)")); return boost::regex_replace(in, toescape, output, boost::match_default | boost::format_all); #else // do not replace $ if followed by a (. To allow variable references. toescape.assign(cstr("(\\$[^\\(])|([ \\#\\:\\=])")); output.assign(cstr("(?1\\$$&)(?2\\\\$&)")); return boost::regex_replace(in, toescape, output, boost::match_default | boost::format_all); #endif break; default: return string(in); } } #ifdef WIN32 /** special quoting for environemnt variables on windows * - $ --> $$, # --> escape with backslash */ string Makefile::quoteEnvironment(const string& in) { regex toescape; string output; toescape.assign(cstr("(\\$)|(\\#)")); output.assign(cstr("(?1\\$$&)(?2\\\\$&)")); return boost::regex_replace(in, toescape, output, boost::match_default | boost::format_all); }; #endif int Makefile::writeMakefile(ostream& out) { for(std::vector::iterator i = items.begin(); i != items.end(); i++) { out << **i; } written = true; return items.size(); } }