//----------------------------------------------------------- // Copyright Christian Arnault LAL-Orsay CNRS // arnault@lal.in2p3.fr // See the complete license in cmt_license.txt "http://www.cecill.info". //----------------------------------------------------------- #include "cmt_syntax.h" #include "cmt.h" #include "cmt_symbol.h" #include "cmt_constituent.h" #include "cmt_pattern.h" #include "cmt_error.h" #include "cmt_branch.h" #include "cmt_error.h" #include "cmt_script.h" #include "cmt_language.h" #include "cmt_project.h" #include "cmt_cmtpath_pattern.h" void Kwd::action (const CmtSystem::cmt_string_vector& words, Project* project, const cmt_string& file_name, int line_number) { } class KwdAction : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { Symbol::action (words, CommandAction, use); } }; class KwdAlias : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { Symbol::action (words, CommandAlias, use); } }; class KwdApplication : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { if (use == &(Use::current ())) { Constituent::action (Application, words); } } }; class KwdApplyPattern : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { ApplyPattern::action (words, use); } }; class KwdApplyTag : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { Tag::action_apply (words, use); } }; class KwdAuthor : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { use->author_action (words); } }; class KwdBranches : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { if (use == &(Use::current ())) { Branch::action (words); } } }; class KwdBuildStrategy : public Kwd { public: bool decode (const cmt_string& w, int& mask, int& strategy) { bool result = true; if (w == "prototypes") { mask = PrototypesMask; strategy = Prototypes; } else if (w == "no_prototypes") { mask = PrototypesMask; strategy = NoPrototypes; } else if ((w == "with_installarea") || (w == "with_install_area")) { mask = InstallAreaMask; strategy = WithInstallArea; } else if ((w == "without_installarea") || (w == "without_install_area")) { mask = InstallAreaMask; strategy = WithoutInstallArea; } else { result = false; } return (result); } void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { cmt_string cmtpath; cmt_string offset; use->get_cmtpath_and_offset (cmtpath, offset); Project* p = Project::find_by_cmtpath (cmtpath); for (int i = 1; i < words.size (); i++) { const cmt_string& w = words[i]; int mask = 0; int strategy = 0; bool in_error = false; if (!decode (w, mask, strategy)) { in_error = true; CmtError::set (CmtError::syntax_error, "ParseRequirements> bad strategy keyword"); } if (mask != 0) { if (p == 0) Cmt::set_current_build_strategy (strategy); else p->set_build_strategy (mask, strategy); } if ((Cmt::get_action () == action_show_strategies) && !Cmt::get_quiet ()) { if (!in_error) { cerr << "# Package " << use->get_package_name () << " adds " << w << " to build strategy" << endl; } else { cerr << "# Error: Package " << use->get_package_name () << " uses unknown " << w << " keyword to build strategy" << endl; } } } } void action (const CmtSystem::cmt_string_vector& words, Project* project, const cmt_string& file_name, int line_number) { for (int i = 1; i < words.size (); i++) { const cmt_string& w = words[i]; int mask = 0; int strategy = 0; bool in_error = false; if (!decode (w, mask, strategy)) { in_error = true; CmtError::set (CmtError::syntax_error, "ParseRequirements> bad strategy keyword"); } if (mask != 0) { if (project == 0) Cmt::set_current_build_strategy (strategy); else project->set_build_strategy (mask, strategy); } if ((Cmt::get_action () == action_show_strategies) && !Cmt::get_quiet ()) { if (!in_error) { cerr << "# Project " << project->get_name () << " adds " << w << " to build strategy" << endl; } else { cerr << "# Error: Project " << project->get_name () << " uses unknown " << w << " keyword to build strategy" << endl; } } } } }; class KwdCleanupScript : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { Script::action (words, CleanupScript, use); Symbol::action (words, CommandCleanupScript, use); } }; class KwdCmtPathPattern : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& /*file_name*/, int /*line_number*/) { CmtPathPattern::action (words, use); } }; class KwdDocument : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { if (use == &(Use::current ())) { Constituent::action (Document, words); } } }; class KwdEndPrivate : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { if (use != &(Use::current ())) { use->pop_scope_section (); } } }; class KwdEndPublic : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { if (use != &(Use::current ())) { use->pop_scope_section (); } } }; class KwdIgnorePattern : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { IgnorePattern::action (words, use); } }; class KwdIncludeDirs : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { Include::action (words, use); } }; class KwdIncludePath : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { if (words.size () > 1) { use->set_include_path (words[1]); } } }; class KwdLanguage : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { Language::action (words); } }; class KwdLibrary : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { if (use == &(Use::current ())) { Constituent::action (Library, words); } } }; class KwdMacro : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { Symbol::action (words, CommandMacro, use); } }; class KwdMacroPrepend : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { Symbol::action (words, CommandMacroPrepend, use); } }; class KwdMacroAppend : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { Symbol::action (words, CommandMacroAppend, use); } }; class KwdMacroRemove : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { Symbol::action (words, CommandMacroRemove, use); } }; class KwdMacroRemoveRegexp : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { Symbol::action (words, CommandMacroRemoveRegexp, use); } }; class KwdMacroRemoveAll : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { Symbol::action (words, CommandMacroRemoveAll, use); } }; class KwdMacroRemoveAllRegexp : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { Symbol::action (words, CommandMacroRemoveAllRegexp, use); } }; class KwdMakeFragment : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { Fragment::action (words, use); } }; class KwdManager : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { use->manager_action (words); } }; class KwdPackage : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { /* if (words.size () > 1) { if (use == &(Use::current())) { m_current_package = words[1]; build_prefix (m_current_package, m_current_prefix); if ((use->get_package_name () != "") && (use->get_package_name () != m_current_package)) { if (!m_quiet) { // cerr << "#CMT> package name mismatch in requirements of " << // use->get_package_name () << " " << // use->version << " line #" << line_number; // cerr << " : " << m_current_package << " versus " << // use->get_package_name () << endl; } } use->set (m_current_package, m_current_version, m_current_path, "", ""); use->change_path (m_current_path); use->style = m_current_style; } } */ } }; class KwdPath : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { Symbol::action (words, CommandPath, use); } }; class KwdPathAppend : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { Symbol::action (words, CommandPathAppend, use); } }; class KwdPathPrepend : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { Symbol::action (words, CommandPathPrepend, use); } }; class KwdPathRemove : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { Symbol::action (words, CommandPathRemove, use); } }; class KwdPathRemoveRegexp : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { Symbol::action (words, CommandPathRemoveRegexp, use); } }; class KwdPattern : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { Pattern::action (words, use); } }; class KwdPrivate : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { if (use != &(Use::current ())) { use->push_scope_section (ScopePrivate); } } }; class KwdProject : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { } void action (const CmtSystem::cmt_string_vector& words, Project* project, const cmt_string& file_name, int line_number) { } }; class KwdPublic : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { if (use != &(Use::current ())) { use->push_scope_section (ScopePublic); } } }; class KwdSet : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { Symbol::action (words, CommandSet, use); } }; class KwdSetAppend : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { Symbol::action (words, CommandSetAppend, use); } }; class KwdSetPrepend : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { Symbol::action (words, CommandSetPrepend, use); } }; class KwdSetRemove : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { Symbol::action (words, CommandSetRemove, use); } }; class KwdSetRemoveRegexp : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { Symbol::action (words, CommandSetRemoveRegexp, use); } }; class KwdSetupScript : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { Script::action (words, SetupScript, use); Symbol::action (words, CommandSetupScript, use); } }; class KwdSetupStrategy : public Kwd { public: bool decode (const cmt_string& w, int& mask, int& strategy) { bool result = true; if (w == "config") { mask = SetupConfigMask; strategy = SetupConfig; } else if (w == "no_config") { mask = SetupConfigMask; strategy = SetupNoConfig; } else if (w == "root") { mask = SetupRootMask; strategy = SetupRoot; } else if (w == "no_root") { mask = SetupRootMask; strategy = SetupNoRoot; } else if (w == "cleanup") { mask = SetupCleanupMask; strategy = SetupCleanup; } else if (w == "no_cleanup") { mask = SetupCleanupMask; strategy = SetupNoCleanup; } else { result = false; } return (result); } void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { cmt_string cmtpath; cmt_string offset; use->get_cmtpath_and_offset (cmtpath, offset); Project* p = Project::find_by_cmtpath (cmtpath); for (int i = 1; i < words.size (); i++) { const cmt_string& w = words[i]; int mask = 0; int strategy = 0; bool in_error = false; if (!decode (w, mask, strategy)) { in_error = true; CmtError::set (CmtError::syntax_error, "ParseRequirements> bad strategy keyword"); } if (mask != 0) { if (p == 0) Cmt::set_current_setup_strategy (strategy); else p->set_setup_strategy (mask, strategy); } if ((Cmt::get_action () == action_show_strategies) && !Cmt::get_quiet ()) { if (!in_error) { cerr << "# Package " << use->get_package_name () << " adds " << w << " to setup strategy" << endl; } else { cerr << "# Error: Package " << use->get_package_name () << " uses unknown " << w << " keyword to setup strategy" << endl; } } } } void action (const CmtSystem::cmt_string_vector& words, Project* project, const cmt_string& file_name, int line_number) { for (int i = 1; i < words.size (); i++) { const cmt_string& w = words[i]; int mask = 0; int strategy = 0; bool in_error = false; if (!decode (w, mask, strategy)) { in_error = true; CmtError::set (CmtError::syntax_error, "ParseRequirements> bad strategy keyword"); } if (mask != 0) { if (project == 0) Cmt::set_current_setup_strategy (strategy); else project->set_setup_strategy (mask, strategy); } if ((Cmt::get_action () == action_show_strategies) && !Cmt::get_quiet ()) { if (!in_error) { cerr << "# Project " << project->get_name () << " adds " << w << " to setup strategy" << endl; } else { cerr << "# Error: Project " << project->get_name () << " uses unknown " << w << " keyword to setup strategy" << endl; } } } } }; class KwdTag : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { Tag::action (words, use); } }; class KwdTagExclude : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { Tag::action_exclude (words, use); } }; class KwdUse : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { Use::action (words, use); } }; class KwdVersionStrategy : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { cerr << "# Package " << use->get_package_name () << " sets obsolescent version strategy" << endl; } }; class KwdVersion : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { } }; class KwdDefault : public Kwd { public: void action (const CmtSystem::cmt_string_vector& words, Use* use, const cmt_string& file_name, int line_number) { /* Unknown keyword : just ignore the line */ if (!Cmt::get_quiet ()) { cerr << "#CMT> bad syntax in requirements of " << use->get_package_name () << " " << use->version << " line #" << line_number; cerr << " [" << words[0] << "...]" << endl; } CmtError::set (CmtError::syntax_error, "ParseRequirements> "); } }; SyntaxParser& SyntaxParser::instance () { static SyntaxParser p; return (p); } /** * Parse the input file, rejecting comments and * rebuilding complete lines (from sections separated by * \ characters. * * Each reformatted line is parsed by filter_line */ void SyntaxParser::parse_requirements (const cmt_string& file_name, Use* use) { SyntaxParser& me = instance (); if (use != 0) { cmt_string buffer; use->fill_standard_macros (buffer); AccessMode saved_current_access = Cmt::get_current_access (); Cmt::set_current_access (UserMode); me.do_parse_text (buffer, "", package_context, use, 0); Cmt::set_current_access (saved_current_access); } me.do_parse_requirements (file_name, use); if (use != 0) { use->close_scope_sections (); } } /** */ void SyntaxParser::parse_project_file_text (const cmt_string& text, const cmt_string& file_name, Project* project) { SyntaxParser& me = instance (); me.do_parse_text (text, file_name, project_context, 0, project); } /** * Parse a text, rejecting comments and * rebuilding complete lines (from sections separated by * \ characters. * * Each reformatted line is parsed by filter_line */ void SyntaxParser::parse_requirements_text (const cmt_string& text, const cmt_string& file_name, Use* use) { SyntaxParser& me = instance (); /** * * We have to preserve m_current_access since it reflects whether * the current cmt action is run in the context of the current package. * (the opposite is when the cmt command specifies the current package * in its arguments -use=... therefore the pwd is NOT the directory * of the current package) * * m_current_access is Developer when pwd = current * User when pwd != current * * Therefore, as soon as we reach a used package, this must be switched to User * * On the other hand, Cmt::scope reflects the status of the public/private * statements. By default, we are in public context when entering a new requirements * file. * */ AccessMode saved_current_access; saved_current_access = Cmt::get_current_access (); if (use == 0) use = &(Use::current ()); if (use != &(Use::current ())) { Cmt::set_current_access (UserMode); } else { Cmt::set_current_access (DeveloperMode); } me.do_parse_text (text, file_name, package_context, use, 0); Cmt::set_current_access (saved_current_access); } /** * Apply the basic parser to one single line : * * o Append to global text if previous back_slash * o Split into words * o Apply the generic Select operator */ void SyntaxParser::parse_requirements_line (const cmt_string& line, Use* use, const cmt_string& file_name, int line_number) { SyntaxParser& me = instance (); me.do_parse_line (line, file_name, line_number, package_context, use, 0); } SyntaxParser::SyntaxParser () { m_keywords.add ("action", new KwdAction ()); m_keywords.add ("alias", new KwdAlias ()); m_keywords.add ("application", new KwdApplication ()); m_keywords.add ("apply_pattern", new KwdApplyPattern ()); m_keywords.add ("apply_tag", new KwdApplyTag ()); m_keywords.add ("author", new KwdAuthor ()); m_keywords.add ("branches", new KwdBranches ()); m_keywords.add ("build_strategy", new KwdBuildStrategy ()); m_keywords.add ("cleanup_script", new KwdCleanupScript ()); m_keywords.add ("cmtpath_pattern", new KwdCmtPathPattern ()); m_keywords.add ("document", new KwdDocument ()); m_keywords.add ("end_private", new KwdEndPrivate ()); m_keywords.add ("end_public", new KwdEndPublic ()); m_keywords.add ("ignore_pattern", new KwdIgnorePattern ()); m_keywords.add ("include_dirs", new KwdIncludeDirs ()); m_keywords.add ("include_path", new KwdIncludePath ()); m_keywords.add ("language", new KwdLanguage ()); m_keywords.add ("library", new KwdLibrary ()); m_keywords.add ("macro", new KwdMacro ()); m_keywords.add ("macro+", new KwdMacroAppend ()); m_keywords.add ("macro_prepend", new KwdMacroPrepend ()); m_keywords.add ("macro_append", new KwdMacroAppend ()); m_keywords.add ("macro_remove", new KwdMacroRemove ()); m_keywords.add ("macro_remove_regexp", new KwdMacroRemoveRegexp ()); m_keywords.add ("macro_remove_all", new KwdMacroRemoveAll ()); m_keywords.add ("macro_remove_all_regexp", new KwdMacroRemoveAllRegexp ()); m_keywords.add ("make_fragment", new KwdMakeFragment ()); m_keywords.add ("manager", new KwdManager ()); m_keywords.add ("package", new KwdPackage ()); m_keywords.add ("path", new KwdPath ()); m_keywords.add ("path_append", new KwdPathAppend ()); m_keywords.add ("path_prepend", new KwdPathPrepend ()); m_keywords.add ("path_remove", new KwdPathRemove ()); m_keywords.add ("path_remove_regexp", new KwdPathRemoveRegexp ()); m_keywords.add ("pattern", new KwdPattern ()); m_keywords.add ("public", new KwdPublic ()); m_keywords.add ("private", new KwdPrivate ()); m_keywords.add ("project", new KwdProject ()); m_keywords.add ("set", new KwdSet ()); m_keywords.add ("set_append", new KwdSetAppend ()); m_keywords.add ("set_prepend", new KwdSetPrepend ()); m_keywords.add ("set_remove", new KwdSetRemove ()); m_keywords.add ("set_remove_regexp", new KwdSetRemoveRegexp ()); m_keywords.add ("setup_script", new KwdSetupScript ()); m_keywords.add ("setup_strategy", new KwdSetupStrategy ()); m_keywords.add ("tag", new KwdTag ()); m_keywords.add ("tag_exclude", new KwdTagExclude ()); m_keywords.add ("use", new KwdUse ()); m_keywords.add ("version_strategy", new KwdVersionStrategy ()); m_keywords.add ("version", new KwdVersion ()); m_project_keywords.add ("build_strategy", new KwdBuildStrategy ()); m_project_keywords.add ("project", new KwdProject ()); m_project_keywords.add ("setup_strategy", new KwdSetupStrategy ()); } void SyntaxParser::do_parse_requirements (const cmt_string& file_name, Use* use) { cmt_string actual_file_name = file_name; cmt_string text; CmtError::clear (); if (!CmtSystem::test_file (actual_file_name)) { actual_file_name = ".."; actual_file_name += CmtSystem::file_separator (); actual_file_name += "cmt"; actual_file_name += CmtSystem::file_separator (); actual_file_name += file_name; if (!CmtSystem::test_file (actual_file_name)) { actual_file_name = ".."; actual_file_name += CmtSystem::file_separator (); actual_file_name += "mgr"; actual_file_name += CmtSystem::file_separator (); actual_file_name += file_name; if (!CmtSystem::test_file (actual_file_name)) { return; } } } text.read (actual_file_name); SyntaxParser::parse_requirements_text (text, actual_file_name, use); } /** * Parse a text, rejecting comments and * rebuilding complete lines (from sections separated by * \ characters. * * Each reformatted line is parsed by filter_line */ void SyntaxParser::do_parse_text (const cmt_string& text, const cmt_string& file_name, ContextType context, Use* use, Project* project) { cmt_string line; int pos; int max_pos; int line_number = 1; if (context == package_context) { if (use == 0) use = &(Use::current ()); } m_filtered_text.erase (0); pos = 0; max_pos = text.size (); for (pos = 0; pos < max_pos;) { int cr = text.find (pos, "\r\n"); int nl = text.find (pos, '\n'); int first = nl; int length = 1; if (cr != cmt_string::npos) { if (nl == cmt_string::npos) { first = cr; length = 2; } else { first = (nl < cr) ? nl : cr; length = (nl < cr) ? 1 : 2; } } if (first == cmt_string::npos) { text.substr (pos, line); pos = max_pos; } else if (first > pos) { text.substr (pos, first - pos, line); pos = first + length; } else { line.erase (0); pos += length; } do_parse_line (line, file_name, line_number, context, use, project); if ((Cmt::get_action () == action_check_configuration) && CmtError::has_pending_error ()) { //break; } line_number++; } } void SyntaxParser::do_parse_line (const cmt_string& line, const cmt_string& file_name, int line_number, ContextType context, Use* use, Project* project) { int length; int nl; int back_slash; cmt_string temp_line = line; if (temp_line.size () == 0) return; if (temp_line[0] == '#') return; nl = temp_line.find_last_of ('\n'); if (nl != cmt_string::npos) temp_line.erase (nl); length = temp_line.size (); if (length == 0) return; // // We scan the line for handling backslashes. // // o Really terminating backslashes (ie those only followed by spaces/tabs // mean continued line // // bool finished = true; length = temp_line.size (); back_slash = temp_line.find_last_of ('\\'); if (back_slash != cmt_string::npos) { // // This is the last backslash // check if there are only space chars after it // bool at_end = true; for (int i = (back_slash + 1); i < length; i++) { char c = temp_line[i]; if ((c != ' ') && (c != '\t')) { at_end = false; break; } } if (at_end) { temp_line.erase (back_slash); finished = false; } else { // This was not a trailing backslash. finished = true; } } m_filtered_text += temp_line; if (!finished) { // We still need to accumulate forthcoming lines // before parsing the resulting text. return; } /* Here a full line (possibly accumulating several lines ended by backslashes) is parsed : o Special characters are filtered now : \t \r \n o Split into words (a word is a string not containing spaces or enclosed in quotes) o Parse the word array (function Select) */ m_filtered_text.replace_all ("", "\t"); m_filtered_text.replace_all ("", "\r"); m_filtered_text.replace_all ("", "\n"); if (Cmt::get_debug ()) { cout << "parse_requirements_line [" << m_filtered_text << "]" << endl; } static CmtSystem::cmt_string_vector words; CmtSystem::split (m_filtered_text, " \t", words); if (words.size () != 0) { switch (context) { case project_context: do_parse_words (words, file_name, line_number, project); break; case package_context: do_parse_words (words, file_name, line_number, use); break; } } m_filtered_text.erase (0); } void SyntaxParser::do_parse_words (const CmtSystem::cmt_string_vector& words, const cmt_string& file_name, int line_number, Use* use) { CmtError::clear (); if (words.size () == 0) return; const cmt_string& command = words[0]; if (command.size () == 0) return; // // First analyze the syntax // Kwd* keyword = m_keywords.find (command); if (keyword == 0) { /* When the first word of the line is not a keyword, it may be an implicit pattern application. */ Pattern* p = Pattern::find (command); if (p == 0) { CmtError::set (CmtError::syntax_error, "ParseRequirements> "); } else { keyword = m_keywords.find ("apply_pattern"); } } if (CmtError::has_pending_error ()) { if (!Cmt::get_quiet ()) { cerr << "#CMT> bad syntax in requirements of " << use->get_package_name () << " " << use->version << " " << use->specified_path << " line #" << line_number; cerr << " [" << command << " ...]" << endl; } return; } // // Then interpret the action // keyword->action (words, use, file_name, line_number); } void SyntaxParser::do_parse_words (const CmtSystem::cmt_string_vector& words, const cmt_string& file_name, int line_number, Project* project) { CmtError::clear (); if (words.size () == 0) return; const cmt_string& command = words[0]; if (command.size () == 0) return; // // First analyze the syntax // Kwd* keyword = m_project_keywords.find (command); if (keyword == 0) { CmtError::set (CmtError::syntax_error, "ParseRequirements> "); } if (CmtError::has_pending_error ()) { if (!Cmt::get_quiet ()) { cerr << "#CMT> bad syntax in project file of " << project->get_name () << " line #" << line_number; cerr << " [" << command << " ...]" << endl; } return; } // // Then interpret the action // keyword->action (words, project, file_name, line_number); }