// Filename: cppManifest.cxx // Created by: drose (22Oct99) // //////////////////////////////////////////////////////////////////// // // PANDA 3D SOFTWARE // Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved // // All use of this software is subject to the terms of the Panda 3d // Software license. You should have received a copy of this license // along with this source code; you will also find a current copy of // the license at http://www.panda3d.org/license.txt . // // To contact the maintainers of this program write to // panda3d@yahoogroups.com . // //////////////////////////////////////////////////////////////////// #include "cppManifest.h" #include "cppExpression.h" #include //////////////////////////////////////////////////////////////////// // Function: CPPManifest::ExpansionNode::Constructor // Access: Public // Description: //////////////////////////////////////////////////////////////////// CPPManifest::ExpansionNode:: ExpansionNode(int parm_number) : _parm_number(parm_number) { } //////////////////////////////////////////////////////////////////// // Function: CPPManifest::ExpansionNode::Constructor // Access: Public // Description: //////////////////////////////////////////////////////////////////// CPPManifest::ExpansionNode:: ExpansionNode(const string &str) : _parm_number(-1), _str(str) { } //////////////////////////////////////////////////////////////////// // Function: CPPManifest::Constructor // Access: Public // Description: //////////////////////////////////////////////////////////////////// CPPManifest:: CPPManifest(const string &args, const CPPFile &file) : _file(file) { assert(!args.empty()); assert(!isspace(args[0])); _expr = (CPPExpression *)NULL; _vis = V_public; // First, identify the manifest name. size_t p = 0; while (p < args.size() && !isspace(args[p]) && args[p] != '(') { p++; } _name = args.substr(0, p); vector_string parameter_names; if (args[p] == '(') { // Hmm, parameters. _has_parameters = true; parse_parameters(args, p, parameter_names); _num_parameters = parameter_names.size(); p++; } else { _has_parameters = false; _num_parameters = 0; } // Now identify the expansion. Skip whitespace. while (p < args.size() && isspace(args[p])) { p++; } save_expansion(args.substr(p), parameter_names); } //////////////////////////////////////////////////////////////////// // Function: CPPManifest::Destructor // Access: Public // Description: //////////////////////////////////////////////////////////////////// CPPManifest:: ~CPPManifest() { if (_expr != (CPPExpression *)NULL) { delete _expr; } } //////////////////////////////////////////////////////////////////// // Function: CPPManifest::expand // Access: Public // Description: //////////////////////////////////////////////////////////////////// string CPPManifest:: expand(const vector_string &args) const { string result; Expansion::const_iterator ei; for (ei = _expansion.begin(); ei != _expansion.end(); ++ei) { if ((*ei)._parm_number >= 0) { int i = (*ei)._parm_number; if (i < (int)args.size()) { result += " " + args[i] + " "; } else { result += " "; } } if (!(*ei)._str.empty()) { result += (*ei)._str; } } return result; } //////////////////////////////////////////////////////////////////// // Function: CPPManifest::determine_type // Access: Public // Description: Returns the type of the manifest, if it is known, // or NULL if the type cannot be determined. //////////////////////////////////////////////////////////////////// CPPType *CPPManifest:: determine_type() const { if (_expr != (CPPExpression *)NULL) { return _expr->determine_type(); } return (CPPType *)NULL; } //////////////////////////////////////////////////////////////////// // Function: CPPManifest::output // Access: Public // Description: //////////////////////////////////////////////////////////////////// void CPPManifest:: output(ostream &out) const { out << _name; if (_has_parameters) { out << "("; if (_num_parameters > 0) { out << "$1"; for (int i = 1; i < _num_parameters; i++) { out << ", $" << i + 1; } } out << ")"; } out << " "; Expansion::const_iterator ei; for (ei = _expansion.begin(); ei != _expansion.end(); ++ei) { if ((*ei)._parm_number >= 0) { out << " $" << (*ei)._parm_number + 1 << " "; } if (!(*ei)._str.empty()) { out << (*ei)._str; } } } //////////////////////////////////////////////////////////////////// // Function: CPPManifest::parse_parameters // Access: Private // Description: //////////////////////////////////////////////////////////////////// void CPPManifest:: parse_parameters(const string &args, size_t &p, vector_string ¶meter_names) { assert(p < args.size()); assert(args[p] == '('); p++; while (p < args.size() && isspace(args[p])) { p++; } while (p < args.size() && args[p] != ')') { // Here's the beginning of a parm. size_t q = p; while (p < args.size() && !isspace(args[p]) && args[p] != ')' && args[p] != ',') { p++; } parameter_names.push_back(args.substr(q, p - q)); // Skip whitespace after the parameter name. while (p < args.size() && isspace(args[p])) { p++; } if (p < args.size() && args[p] == ',') { p++; // Skip whitespace after a comma. while (p < args.size() && isspace(args[p])) { p++; } } } } //////////////////////////////////////////////////////////////////// // Function: CPPManifest::save_expansion // Access: Private // Description: //////////////////////////////////////////////////////////////////// void CPPManifest:: save_expansion(const string &exp, const vector_string ¶meter_names) { if (parameter_names.empty()) { // No parameters; this is an easy case. _expansion.push_back(ExpansionNode(exp)); return; } // Walk through the expansion string. For each substring that is an // identifier, check it against parameter_names. size_t p = 0; size_t last = 0; while (p < exp.size()) { if (isalpha(exp[p]) || exp[p] == '_') { // Here's the start of an identifier. Find the end of it. size_t q = p; p++; while (p < exp.size() && isalnum(exp[p]) || exp[p] == '_') { p++; } string ident = exp.substr(q, p - q); // Is this identifier one of our parameters? int pnum = -1; for (int i = 0; pnum == -1 && i < (int)parameter_names.size(); i++) { if (parameter_names[i] == ident) { pnum = i; } } if (pnum != -1) { // Yep! if (last != q) { _expansion.push_back(ExpansionNode(exp.substr(last, q - last))); } _expansion.push_back(pnum); last = p; } } else { p++; } } if (last != p) { _expansion.push_back(exp.substr(last, p - last)); } }