//----------------------------------------------------------- // Copyright Christian Arnault LAL-Orsay CNRS // arnault@lal.in2p3.fr // See the complete license in cmt_license.txt "http://www.cecill.info". //----------------------------------------------------------- #include #include #include #include #include "cmt_fragment.h" #include "cmt_use.h" #include "cmt_symbol.h" #include "cmt_system.h" #include "cmt_database.h" #include "cmt_log.h" /*----------------------------------------------------------*/ /* */ /* Operations on Variables */ /* */ /*----------------------------------------------------------*/ //---------------------------------------------------------- Variable* Variable::find (VariableVector& vector, const cmt_string& name) { for (int i = 0; i < vector.size (); i++) { Variable& v = vector[i]; if (v.name == name) return (&v); } return (0); } //---------------------------------------------------------- Variable::Variable () { } //---------------------------------------------------------- Variable::Variable (const cmt_string& n) : name (n) { m_macro_braces = "${"; m_macro_braces += name; m_macro_braces += "}"; m_macro_pars = "$("; m_macro_pars += name; m_macro_pars += ")"; } //---------------------------------------------------------- const cmt_string& Variable::macro_braces () const { return (m_macro_braces); } //---------------------------------------------------------- const cmt_string& Variable::macro_pars () const { return (m_macro_pars); } //---------------------------------------------------------- void Variable::set (const cmt_string& new_name, const cmt_string& new_value) { name = new_name; value = new_value; m_macro_braces = "${"; m_macro_braces += name; m_macro_braces += "}"; m_macro_pars = "$("; m_macro_pars += name; m_macro_pars += ")"; } //---------------------------------------------------------- Variable& Variable::operator = (const Variable& other) { value = other.value; return (*this); } //---------------------------------------------------------- Variable& Variable::operator = (const cmt_string& v) { value = v; return (*this); } //---------------------------------------------------------- void Variable::operator += (const cmt_string& v) { value += v; } //---------------------------------------------------------- cmt_string Variable::operator + (const cmt_string& v) const { return (value + v); } //---------------------------------------------------------- Variable::operator const cmt_string& () const { return (value); } //---------------------------------------------------------- bool Variable::operator == (const cmt_string& v) const { return ((value == v)); } //---------------------------------------------------------- bool Variable::operator != (const cmt_string& v) const { return ((value != v)); } /*----------------------------------------------------------*/ /* */ /* Operations on Fragments */ /* */ /*----------------------------------------------------------*/ /*----------------------------------------------------------*/ void Fragment::show (const cmt_string& name) { Fragment* fragment = Fragment::find (name); if (fragment == 0) { CmtMessage::info ("Fragment " + name + " not found"); // cerr << "Fragment " << name << " not found" << endl; } else { fragment->print (); } } /*----------------------------------------------------------*/ void Fragment::show_all () { static FragmentVector& Fragments = fragments (); int number; for (number = 0; number < Fragments.size (); number++) { Fragment& fragment = Fragments[number]; fragment.print (); } } class fragment_action_iterator { public: fragment_action_iterator (Use* use) : m_need_dependencies (false), m_state (need_name), m_use (use) { } void add_word (const cmt_string& w) { switch (m_state) { case need_name: m_name = w; m_state = need_options; break; case need_options: if (w.find ("-suffix=") != cmt_string::npos) { m_suffix = w; m_suffix.replace ("-suffix=", ""); } else if (w.find ("-dependencies") != cmt_string::npos) { m_need_dependencies = true; } else if (w.find ("-header=") != cmt_string::npos) { m_header = w; m_header.replace ("-header=", ""); if (Fragment::find (m_header) == 0) { Fragment::add (m_header, "", "", "", false, m_use); } } else if (w.find ("-trailer=") != cmt_string::npos) { m_trailer = w; m_trailer.replace ("-trailer=", ""); if (Fragment::find (m_trailer) == 0) { Fragment::add (m_trailer, "", "", "", false, m_use); } } break; } } void commit () { Fragment::add (m_name, m_suffix, m_header, m_trailer, m_need_dependencies, m_use); } private: enum { need_name, need_options } m_state; cmt_string m_name; cmt_string m_suffix; cmt_string m_header; cmt_string m_trailer; bool m_need_dependencies; Use* m_use; }; /*----------------------------------------------------------*/ void Fragment::action (const CmtSystem::cmt_string_vector& words, Use* use) { if ((Cmt::get_current_access () == UserMode) && (use->get_current_scope () == ScopePrivate)) return; if (words.size () <= 1) return; fragment_action_iterator it (use); for (int i = 1; i < words.size (); i++) { const cmt_string& w = words[i]; cmt_string ew = w; Symbol::expand (ew); if (ew != w) { CmtSystem::cmt_string_vector ws; CmtSystem::split (ew, " ", ws); for (int j = 0; j < ws.size (); ++j) { const cmt_string& ww = ws[j]; it.add_word (ww); } } else { it.add_word (ew); } } it.commit (); } /*----------------------------------------------------------*/ Fragment* Fragment::find (const cmt_string& name) { static FragmentVector& Fragments = fragments (); int fragment_index; if (Fragments.size () == 0) return (0); for (fragment_index = 0; fragment_index < Fragments.size (); fragment_index++) { Fragment& fragment = Fragments[fragment_index]; if (fragment.name == name) { return (&fragment); } } return (0); } /*----------------------------------------------------------*/ void Fragment::add (const cmt_string& name, const cmt_string& suffix, const cmt_string& header, const cmt_string& trailer, bool need_dependencies, Use* use) { static FragmentVector& Fragments = fragments (); { Fragment* fragment; if (name == "") return; fragment = find (name); if (fragment != 0) { if (suffix != "") { fragment->suffix = suffix; } if (header != "") { fragment->header = header; } if (trailer != "") { fragment->trailer = trailer; } fragment->need_dependencies = need_dependencies; fragment->use = use; return; } } Fragment& fragment = Fragments.add (); fragment.name = name; fragment.suffix = suffix; fragment.header = header; fragment.trailer = trailer; fragment.need_dependencies = need_dependencies; fragment.use = use; } /*----------------------------------------------------------*/ void Fragment::clear_all () { static FragmentVector& Fragments = fragments (); for (int i = 0; i < Fragments.size (); i++) { Fragment& f = Fragments[i]; f.clear (); } Fragments.clear (); } /*----------------------------------------------------------*/ Fragment::FragmentVector& Fragment::fragments () { static Database& db = Database::instance (); static FragmentVector& Fragments = db.fragments (); return (Fragments); } /*----------------------------------------------------------*/ Fragment::Fragment () { use = 0; } /*----------------------------------------------------------*/ Fragment::Fragment (const cmt_string& fragment_name) { name = fragment_name; use = 0; path = ""; } /*----------------------------------------------------------*/ Fragment::~Fragment () { use = 0; } /*----------------------------------------------------------*/ void Fragment::clear () { name = ""; suffix = ""; header = ""; trailer = ""; need_dependencies = false; path = ""; use = 0; } /*----------------------------------------------------------*/ int Fragment::print () { int result = 1; if (name == "") return (0); locate (); if (use == 0) { Use& u = Use::current(); use = &u; } cmt_string the_path = path; use->reduce_path (the_path); cout << the_path; if (suffix != "") { cout << "->" << suffix; } cout << endl; return (result); } /*----------------------------------------------------------*/ bool Fragment::locate () { cmt_string root_path; if (use == 0) { // Assume CMT use = Use::find ("CMT"); } use->get_full_path (root_path); if (path != "") return (true); // First try /fragments/ or /fragments/nmake/ path = root_path; path += CmtSystem::file_separator (); path += "fragments"; path += CmtSystem::file_separator (); if (Cmt::build_nmake ()) { path += "nmake"; path += CmtSystem::file_separator (); } path += name; if (CmtSystem::test_file (path)) return (true); // Then try /fragments/ for both Win and Unix path = root_path; path += CmtSystem::file_separator (); path += "fragments"; path += CmtSystem::file_separator (); path += name; if (CmtSystem::test_file (path)) return (true); // Then try /cmt/fragments/ or /cmt/fragments/nmake/ root_path += CmtSystem::file_separator (); if (use->style == mgr_style) root_path += "mgr"; else root_path += "cmt"; root_path += CmtSystem::file_separator (); root_path += "fragments"; root_path += CmtSystem::file_separator (); path = root_path; if (Cmt::build_nmake ()) { path += "nmake"; path += CmtSystem::file_separator (); } path += name; if (CmtSystem::test_file (path)) return (true); // Then try /cmt/fragments/ for both Win and Unix path = root_path; path += name; if (CmtSystem::test_file (path)) return (true); return (false); } //-------------------------------------------------- bool Fragment::copy (FILE* out, const cmt_string& name, int variables, ...) { va_list ids; Fragment* fragment = Fragment::find (name); if (fragment == 0) return (false); va_start (ids, variables); bool result = fragment->copy (out, variables, ids); va_end (ids); return (result); } //-------------------------------------------------- bool Fragment::copy (cmt_string& out, const cmt_string& name, int variables, ...) { va_list ids; Fragment* fragment = Fragment::find (name); if (fragment == 0) return (false); va_start (ids, variables); bool result = fragment->copy (out, variables, ids); va_end (ids); return (result); } //-------------------------------------------------- bool Fragment::copy (FILE* out, int variables, ...) { va_list ids; va_start (ids, variables); bool result = copy (out, variables, ids); va_end (ids); return (result); } //-------------------------------------------------- bool Fragment::copy (cmt_string& out, int variables, ...) { va_list ids; va_start (ids, variables); bool result = copy (out, variables, ids); va_end (ids); return (result); } //-------------------------------------------------- bool Fragment::copy (FILE* out, int variables, va_list ids) { static cmt_string cline; bool result = copy (cline, variables, ids); if (result) { cline.write (out); return (true); } else { return (false); } } //-------------------------------------------------- bool Fragment::copy (cmt_string& out, int variables, va_list ids) { int i; if (!locate ()) return (false); out.read (path); Variable* var = 0; for (i = 0; i < variables; i++) { var = va_arg (ids, Variable*); out.replace_all (var->macro_braces (), var->value); out.replace_all (var->macro_pars (), var->value); } return (true); } //-------------------------------------------------- bool Fragment::wincopy (FILE* out, int variables, va_list ids) { static cmt_string cline; bool result = wincopy (cline, variables, ids); if (result) { cline.write (out); return (true); } else { return (false); } } //-------------------------------------------------- bool Fragment::wincopy (cmt_string& out, int variables, va_list ids) { int i; if (!locate ()) return (false); out.read (path); Variable* var = 0; for (i = 0; i < variables; i++) { var = va_arg (ids, Variable*); out.replace_all (var->macro_braces (), var->value); out.replace_all (var->macro_pars (), var->value); } cmt_string pattern; cmt_string macro_name; char end_pattern; int start = 0; for (;;) { // // Try and substitute all ${xxx} or $(xxx) patterns // using symbol values. // int par; int brace; int begin; par = out.find (start, "$("); brace = out.find (start, "${"); if (par == cmt_string::npos) { // No parentheses. Look for brace if (brace == cmt_string::npos) { // No pattern, finish the scan. break; } // Brace found end_pattern = '}'; begin = brace; } else { // Parenthese found. Look for closest from {par, brace} if ((brace == cmt_string::npos) || (brace > par)) { end_pattern = ')'; begin = par; } else { end_pattern = '}'; begin = brace; } } // Skip the pattern intro. start = begin + 2; int end; end = out.find (start, end_pattern); if (end == cmt_string::npos) { // The pattern is a fake one (no ending!) break; } // This should never happen... if (end < begin) break; // Extract the complete pattern out.substr (begin, end - begin + 1, pattern); // Then only the macro name out.substr (begin + 2, end - begin - 2, macro_name); if (macro_name == "CFG") { // This is a Windows reserved keyword... start = end + 1; } else { Symbol* macro = Symbol::find (macro_name); if (macro != 0) { // Macro found cmt_string value = macro->resolve_macro_value (); out.replace_all (pattern, value); // The substitution will restart from the same place // allowing for recursive replacements start = begin; } else { // Macro not found. Look for env. variable cmt_string value = CmtSystem::getenv (macro_name); out.replace_all (pattern, value); // The substitution will restart from the same place // allowing for recursive replacements start = begin; } } } // Uniformly install CR-LF doublets. out.replace_all ("\r\n", "\n"); out.replace_all ("\n", "\r\n"); return (true); } //-------------------------------------------------- bool Fragment::copy (FILE* out, const cmt_string& name, const Variable::VariableVector& vector, int variables, ...) { va_list ids; Fragment* fragment = Fragment::find (name); if (fragment == 0) return (false); va_start (ids, variables); bool result = fragment->copy (out, vector, variables, ids); va_end (ids); return (result); } //-------------------------------------------------- bool Fragment::copy (cmt_string& out, const cmt_string& name, const Variable::VariableVector& vector, int variables, ...) { va_list ids; Fragment* fragment = Fragment::find (name); if (fragment == 0) return (false); va_start (ids, variables); bool result = fragment->copy (out, vector, variables, ids); va_end (ids); return (result); } //-------------------------------------------------- bool Fragment::copy (FILE* out, const Variable::VariableVector& vector, int variables, ...) { va_list ids; va_start (ids, variables); bool result = copy (out, vector, variables, ids); va_end (ids); return (result); } //-------------------------------------------------- bool Fragment::copy (cmt_string& out, const Variable::VariableVector& vector, int variables, ...) { va_list ids; va_start (ids, variables); bool result = copy (out, vector, variables, ids); va_end (ids); return (result); } //-------------------------------------------------- bool Fragment::copy (FILE* out, const Variable::VariableVector& vector, int variables, va_list ids) { static cmt_string cline; bool result = copy (cline, vector, variables, ids); if (result) { cline.write (out); return (true); } else { return (false); } } //-------------------------------------------------- bool Fragment::copy (cmt_string& out, const Variable::VariableVector& vector, int variables, va_list ids) { int i; if (!locate ()) return (false); out.read (path); Variable* var = 0; for (i = 0; i < vector.size (); i++) { var = &(vector[i]); out.replace_all (var->macro_braces (), var->value); out.replace_all (var->macro_pars (), var->value); } for (i = 0; i < variables; i++) { var = va_arg (ids, Variable*); out.replace_all (var->macro_braces (), var->value); out.replace_all (var->macro_pars (), var->value); } return (true); } //-------------------------------------------------- bool Fragment::wincopy (FILE* out, const Variable::VariableVector& vector, int variables, va_list ids) { static cmt_string cline; bool result = wincopy (cline, vector, variables, ids); if (result) { cline.write (out); return (true); } else { return (false); } } //-------------------------------------------------- bool Fragment::wincopy (cmt_string& out, const Variable::VariableVector& vector, int variables, va_list ids) { int i; if (!locate ()) return (false); out.read (path); Variable* var = 0; for (i = 0; i < vector.size (); i++) { var = &(vector[i]); out.replace_all (var->macro_braces (), var->value); out.replace_all (var->macro_pars (), var->value); } for (i = 0; i < variables; i++) { var = va_arg (ids, Variable*); out.replace_all (var->macro_braces (), var->value); out.replace_all (var->macro_pars (), var->value); } cmt_string pattern; cmt_string macro_name; char end_pattern; int start = 0; for (;;) { // // Try and substitute all ${xxx} or $(xxx) patterns // using symbol values. // int par; int brace; int begin; par = out.find (start, "$("); brace = out.find (start, "${"); if (par == cmt_string::npos) { // No parentheses. Look for brace if (brace == cmt_string::npos) { // No pattern, finish the scan. break; } // Brace found end_pattern = '}'; begin = brace; } else { // Parenthese found. Look for closest from {par, brace} if ((brace == cmt_string::npos) || (brace > par)) { end_pattern = ')'; begin = par; } else { end_pattern = '}'; begin = brace; } } // Skip the pattern intro. start = begin + 2; int end; end = out.find (start, end_pattern); if (end == cmt_string::npos) { // The pattern is a fake one (no ending!) break; } // This should never happen... if (end < begin) break; // Extract the complete pattern out.substr (begin, end - begin + 1, pattern); // Then only the macro name out.substr (begin + 2, end - begin - 2, macro_name); if (macro_name == "CFG") { // This is a Windows reserved keyword... start = end + 1; } else { Symbol* macro = Symbol::find (macro_name); if (macro != 0) { // Macro found cmt_string value = macro->resolve_macro_value (); out.replace_all (pattern, value); // The substitution will restart from the same place // allowing for recursive replacements start = begin; } else { // Macro not found. Look for env. variable cmt_string value = CmtSystem::getenv (macro_name); out.replace_all (pattern, value); // The substitution will restart from the same place // allowing for recursive replacements start = begin; } } } // Uniformly install CR-LF doublets. out.replace_all ("\r\n", "\n"); out.replace_all ("\n", "\r\n"); return (true); } //-------------------------------------------------- FragmentHandle::FragmentHandle () { _fragment = 0; _initialized = false; } //-------------------------------------------------- FragmentHandle::FragmentHandle (const cmt_string name) : _name(name) { _fragment = 0; _initialized = false; } //-------------------------------------------------- FragmentHandle& FragmentHandle::operator = (const FragmentHandle& other) { _name = other._name; _fragment = 0; _initialized = false; return (*this); } //-------------------------------------------------- void FragmentHandle::reset () { _fragment = 0; _initialized = false; } //-------------------------------------------------- void FragmentHandle::set (const cmt_string name) { _name = name; _fragment = 0; _initialized = false; } //-------------------------------------------------- cmt_string& FragmentHandle::name () { static cmt_string null_string; if (!setup ()) return (null_string); return (_fragment->name); } //-------------------------------------------------- cmt_string& FragmentHandle::suffix () { static cmt_string null_string; if (!setup ()) return (null_string); return (_fragment->suffix); } //-------------------------------------------------- cmt_string& FragmentHandle::header () { static cmt_string null_string; if (!setup ()) return (null_string); return (_fragment->header); } //-------------------------------------------------- cmt_string& FragmentHandle::trailer () { static cmt_string null_string; if (!setup ()) return (null_string); return (_fragment->trailer); } //-------------------------------------------------- bool FragmentHandle::need_dependencies () { if (!setup ()) return (false); return (_fragment->need_dependencies); } //-------------------------------------------------- bool FragmentHandle::copy (FILE* out, int variables, ...) { if (!setup ()) return (false); va_list ids; va_start (ids, variables); bool result = _fragment->copy (out, variables, ids); va_end (ids); if (!result) { CmtMessage::info ("Fragment " + _name + " not found"); // cerr << "#CMT> Fragment " << _name << " not found" << endl; _fragment = 0; } return (result); } //-------------------------------------------------- bool FragmentHandle::copy (cmt_string& out, int variables, ...) { if (!setup ()) return (false); va_list ids; va_start (ids, variables); bool result = _fragment->copy (out, variables, ids); va_end (ids); if (!result) { CmtMessage::info ("Fragment " + _name + " not found"); // cerr << "#CMT> Fragment " << _name << " not found" << endl; _fragment = 0; } return (result); } //-------------------------------------------------- bool FragmentHandle::wincopy (FILE* out, int variables, ...) { if (!setup ()) return (false); va_list ids; va_start (ids, variables); bool result = _fragment->wincopy (out, variables, ids); va_end (ids); if (!result) { CmtMessage::info ("Fragment " + _name + " not found"); // cerr << "#CMT> Fragment " << _name << " not found" << endl; _fragment = 0; } return (result); } //-------------------------------------------------- bool FragmentHandle::wincopy (cmt_string& out, int variables, ...) { if (!setup ()) return (false); va_list ids; va_start (ids, variables); bool result = _fragment->wincopy (out, variables, ids); va_end (ids); if (!result) { CmtMessage::info ("Fragment " + _name + " not found"); // cerr << "#CMT> Fragment " << _name << " not found" << endl; _fragment = 0; } return (result); } //-------------------------------------------------- bool FragmentHandle::copy (FILE* out, const Variable::VariableVector& vector, int variables, ...) { if (!setup ()) return (false); va_list ids; va_start (ids, variables); bool result = _fragment->copy (out, vector, variables, ids); va_end (ids); if (!result) { CmtMessage::info ("Fragment " + _name + " not found"); // cerr << "#CMT> Fragment " << _name << " not found" << endl; _fragment = 0; } return (result); } //-------------------------------------------------- bool FragmentHandle::copy (cmt_string& out, const Variable::VariableVector& vector, int variables, ...) { if (!setup ()) return (false); va_list ids; va_start (ids, variables); bool result = _fragment->copy (out, vector, variables, ids); va_end (ids); if (!result) { CmtMessage::info ("Fragment " + _name + " not found"); // cerr << "#CMT> Fragment " << _name << " not found" << endl; _fragment = 0; } return (result); } //-------------------------------------------------- bool FragmentHandle::wincopy (FILE* out, const Variable::VariableVector& vector, int variables, ...) { if (!setup ()) return (false); va_list ids; va_start (ids, variables); bool result = _fragment->wincopy (out, vector, variables, ids); va_end (ids); if (!result) { CmtMessage::info ("Fragment " + _name + " not found"); // cerr << "#CMT> Fragment " << _name << " not found" << endl; _fragment = 0; } return (result); } //-------------------------------------------------- bool FragmentHandle::wincopy (cmt_string& out, const Variable::VariableVector& vector, int variables, ...) { if (!setup ()) return (false); va_list ids; va_start (ids, variables); bool result = _fragment->wincopy (out, vector, variables, ids); va_end (ids); if (!result) { CmtMessage::info ("Fragment " + _name + " not found"); // cerr << "#CMT> Fragment " << _name << " not found" << endl; _fragment = 0; } return (result); } //-------------------------------------------------- bool FragmentHandle::setup () { if (!_initialized) { _initialized = true; _fragment = Fragment::find (_name); if (_fragment == 0) { CmtMessage::info ("Fragment " + _name + " not found"); // cerr << "#CMT> Fragment " << _name << " not found" << endl; } } if (_fragment == 0) { return (false); } else { return (true); } }