//-----------------------------------------------------------
// 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);
}