//----------------------------------------------------------- // Copyright Christian Arnault LAL-Orsay CNRS // arnault@lal.in2p3.fr // See the complete license in cmt_license.txt "http://www.cecill.info". //----------------------------------------------------------- #include "cmt_model.h" #include "cmt_fragment.h" #include "cmt_symbol.h" /** * Filters out all predefined XML constructs. */ void CmtModel::filter (cmt_string& text) { text.replace_all ("", "\t"); text.replace_all ("", "\r"); text.replace_all ("", "\n"); } void CmtModel::display (cmt_string& text) { text.replace_all ("<", "<"); text.replace_all (">", ">"); text.replace_all ("\\\"", "\""); text.replace_all ("\\\'", "\'"); text.replace_all ("", ""); Symbol::expand (text); cout << text; } void CmtModel::expand (const cmt_string& input_text) { int openmarker; int closemarker; CmtSystem::cmt_string_vector subargs; cmt_string text = input_text; cmt_string remaining; filter (text); for (;;) { /** * Look for the next < ... /> pattern * If not found, then simply dump the text as it is. */ openmarker = text.find ("<"); if (openmarker == cmt_string::npos) break; closemarker = text.find (openmarker, "/>"); if (closemarker == cmt_string::npos) break; if (CmtSystem::testenv ("CMTTESTMODEL")) { cerr << "text=[" << text << "]" << endl; } /** * Extract the command from the pattern */ cmt_string command; text.substr (openmarker + 1, closemarker - openmarker - 1, command); if (CmtSystem::testenv ("CMTTESTMODEL")) { cerr << "command=[" << command << "]" << endl; } /** * Get what is left from the original text beyond the pattern */ text.substr (closemarker + 2, remaining); /** * Cut the original text up to the pattern start */ text.erase (openmarker); /** * Now display it */ display (text); /** * Convert the extracted command into words */ CmtSystem::split (command, " ", subargs); /** * Recursively expand it */ expand (subargs); /** * The next iteration will operate on the remaining text */ text = remaining; } if (CmtSystem::testenv ("CMTTESTMODEL")) { cerr << "text=[" << text << "]" << endl; } /** * Display what is left after extracting the last pattern */ display (text); cout << endl; } void CmtModel::strict_expand (const cmt_string& input_text) { CmtSystem::cmt_string_vector subargs; cmt_string text = input_text; cmt_string remaining; // The patterns for syntax parsing cmt_string open_element = " we have a multiple one it = its; multiple = true; } else if (its == exp_open_elements.end ()) { // no multiple element -> we have a single one } else if (it < its) { // the single is before the multiple } else { // the multiple is before the single it = its; multiple = true; } remaining = text.substr (pos, it._pos - pos); display (remaining); //cout << "pos=" << pos << " open_element -> p=" << it._pos << " l=" << it._length << endl; pos = it._pos + it._length; it = exp_word.begin (text, pos); if (it._pos != pos) { cerr << "Syntax error: no element name" << endl; break; } //cout << "pos=" << pos << " word -> p=" << it._pos << " l=" << it._length << endl; pos += it._length; cmt_string element = it (text); //cout << "pos=" << pos << " element=" << element << endl; subargs.clear (); { cmt_string& s = subargs.add (); s = element; } for (;;) { it = exp_skip_spaces.begin (text, pos); if (it._pos == pos) { //cout << "pos=" << pos << " skip_spaces -> p=" << it._pos << " l=" << it._length << endl; pos += it._length; } //cout << "pos=" << pos << endl; it = exp_close_element.begin (text, pos); if (it._pos == pos) { //cout << "Recursing to [" << element << "]" << endl; int i; Variable::VariableVector variables; /** * We start by decoding all [variable=value] pairs from the arguments * A vector of Variables is filled from them. */ int multiple_count = 0; CmtSystem::cmt_string_vector values; cmt_string name; cmt_string value; for (i = 1; i < subargs.size (); i++) { const cmt_string& arg = subargs[i]; int p = arg.find ("="); arg.substr (0, p, name); arg.substr (p + 1, value); if (value[0] == '"') { value.erase (0, 1); if (value[value.size()-1] == '"') value.erase (value.size ()-1); } else if (value[0] == '\'') { value.erase (0, 1); if (value[value.size()-1] == '\'') value.erase (value.size ()-1); } //cout << "+ name = [" << value << "]" << endl; if (multiple) { values.clear (); CmtSystem::split (value, " \t", values); int n = values.size (); if (n > multiple_count) multiple_count = n; } Variable* v = Variable::find (variables, name); if (v == 0) { v = &(variables.add ()); v->set (name); } (*v) = value; } cmt_string sub_text; FragmentHandle fragment (element); if (multiple) { //cout << "+ count = " << multiple_count << endl; for (int n = 0; n < multiple_count; n++) { for (i = 1; i < subargs.size (); i++) { const cmt_string& arg = subargs[i]; int p = arg.find ("="); arg.substr (p + 1, value); if (value[0] == '"') { value.erase (0, 1); if (value[value.size()-1] == '"') value.erase (value.size ()-1); } else if (value[0] == '\'') { value.erase (0, 1); if (value[value.size()-1] == '\'') value.erase (value.size ()-1); } //cout << "+ values = [" << value << "]" << endl; values.clear (); CmtSystem::split (value, " \t", values); if (n < values.size ()) { value = values[n]; } else { value = ""; } Variable& v = variables[i-1]; //cout << "+ value = [" << value << "]" << endl; v = value; } fragment.copy (sub_text, variables, 0); expand_level++; strict_expand (sub_text); expand_level--; } } else { fragment.copy (sub_text, variables, 0); expand_level++; strict_expand (sub_text); expand_level--; } pos += it._length; break; } //cout << "Try attribute at pos=" << pos << " [" << text.substr (pos) << "]" << endl; it = exp_attribute.begin (text, pos); if (it._pos != pos) { cerr << "Syntax error : no attribute before closing the element [" << text.substr (pos) << "]" << endl; break; } //cout << "pos=" << pos << " attribute -> p=" << it._pos << " l=" << it._length << endl; //cout << "pos=" << pos << " attr=[" << it (text) << "]" << endl; { cmt_string& s = subargs.add (); s = it (text); } pos += it._length; } } if (expand_level == 0) cout << endl; } void CmtModel::test_regexp (const cmt_string& pattern, const cmt_string& input_text) { cout << "Testing pattern [" << pattern << "] against [" << input_text << "]" << endl; cmt_regexp exp (pattern); cmt_regexp::iterator it; for (int pos = 0; pos < 10; pos++) { it = exp.begin (input_text, pos); if (it == exp.end ()) { cout << "No match" << endl; } else { cout << "p=" << it._pos << " l=" << it._length << " -> [" << it (input_text) << "]" << endl; } } } /** * Expands a model file * Arguments are : * model-name : name of a model file * var=value : variable value to be expanded * (will take the form ${var} ) */ void CmtModel::expand (const CmtSystem::cmt_string_vector& arguments) { int i; Variable::VariableVector variables; /** * We start by decoding all [variable=value] pairs from the arguments * A vector of Variables is filled from them. */ for (i = 0; i < arguments.size (); i++) { const cmt_string& arg = arguments[i]; if (arg.find ("=") != cmt_string::npos) { cmt_string name; cmt_string value; int pos = arg.find ("="); arg.substr (0, pos, name); arg.substr (pos + 1, value); Variable* v = Variable::find (variables, name); if (v == 0) { v = &(variables.add ()); v->set (name); } (*v) = value; } } /** * Then model names are extracted. * Each model may contain a set of <...> patterns. * The expected syntax for each of them is : * * * Therefore the current expand function is recursively restarted. * * Text around patterns is displayed after replacements of all * variable values detected by ${variable-name} patterns */ cmt_string text; for (i = 0; i < arguments.size (); i++) { const cmt_string& arg = arguments[i]; if (arg.find ("=") == cmt_string::npos) { FragmentHandle fragment (arg); fragment.copy (text, variables, 0); filter (text); int openmarker; int closemarker; CmtSystem::cmt_string_vector subargs; cmt_string remaining; for (;;) { /** * Look for the next <...> pattern * If not found, then simply dump the text as it is. */ openmarker = text.find ("<"); if (openmarker == cmt_string::npos) break; closemarker = text.find (openmarker, "/>"); if (closemarker == cmt_string::npos) { /** * The opening < was in the text */ /** * Get what is left from the original text beyond the pattern */ text.substr (openmarker + 1, remaining); text.erase (openmarker + 1); /** * Now display it */ display (text); } else { /** * Extract the command from the pattern */ cmt_string command; text.substr (openmarker + 1, closemarker - openmarker - 1, command); /** * Get what is left from the original text beyond the pattern */ text.substr (closemarker + 2, remaining); text.erase (openmarker); /** * Now display it */ display (text); /** * Convert the extracted command into words */ CmtSystem::split (command, " ", subargs); /** * Recursively expand it */ expand (subargs); } /** * The next iteration will operate on the remaining text */ text = remaining; } /** * Display what is left after extracting the last pattern */ display (text); } } }