diff --git a/ppremake/ppScope.cxx b/ppremake/ppScope.cxx index e55ad1fd20..1b156087ef 100644 --- a/ppremake/ppScope.cxx +++ b/ppremake/ppScope.cxx @@ -672,10 +672,12 @@ tokenize_numeric_pair(const string &str, double &a, double &b) { const char *param = words[i].c_str(); char *n; results[i] = strtod(param, &n); - if (n == param) { + if (*n != '\0') { // strtod failed--not a numeric representation. cerr << "Warning: " << words[i] << " is not a number.\n"; - results[i] = 0.0; + if (n == param) { + results[i] = 0.0; + } } } @@ -720,6 +722,19 @@ scan_to_whitespace(const string &str, size_t start) { return p; } +//////////////////////////////////////////////////////////////////// +// Function: PPScope::format_int +// Access: Private, Static +// Description: Formats the indicated integer as a string and returns +// the string. +//////////////////////////////////////////////////////////////////// +string PPScope:: +format_int(int num) { + char buffer[32]; + sprintf(buffer, "%d", num); + return buffer; +} + //////////////////////////////////////////////////////////////////// // Function: PPScope::p_set_variable // Access: Private @@ -1024,6 +1039,16 @@ r_expand_variable(const string &str, size_t &vp, return expand_gtn(params); } else if (funcname == ">=") { return expand_gen(params); + } else if (funcname == "+") { + return expand_plus(params); + } else if (funcname == "-") { + return expand_minus(params); + } else if (funcname == "*") { + return expand_times(params); + } else if (funcname == "/") { + return expand_divide(params); + } else if (funcname == "%") { + return expand_modulo(params); } else if (funcname == "not") { return expand_not(params); } else if (funcname == "or") { @@ -2541,6 +2566,123 @@ expand_gen(const string ¶ms) { return result; } +//////////////////////////////////////////////////////////////////// +// Function: PPScope::expand_plus +// Access: Private +// Description: Expands the "+" function variable. This operates +// on integer numbers. +//////////////////////////////////////////////////////////////////// +string PPScope:: +expand_plus(const string ¶ms) { + double a, b; + if (!tokenize_numeric_pair(params, a, b)) { + return string(); + } + + int ai = (int)a; + int bi = (int)b; + return format_int(ai + bi); +} + +//////////////////////////////////////////////////////////////////// +// Function: PPScope::expand_minus +// Access: Private +// Description: Expands the "-" function variable. This operates +// on integer numbers. +//////////////////////////////////////////////////////////////////// +string PPScope:: +expand_minus(const string ¶ms) { + // We cannot use tokenize_numeric_pair(), because we also support + // unary minus. + + vector words; + tokenize_params(params, words, true); + double results[2]; + int num_words = words.size(); + + if (num_words == 1) { + // Simular unary minus by setting the first operand to 0. + results[0] = 0.0; + + } else if (num_words != 2) { + cerr << num_words << " parameters supplied when two were expected:\n" + << params << "\n"; + return string(); + } + + for (int i = 0; i < num_words; i++) { + const char *param = words[i].c_str(); + char *n; + int j = 2 - num_words + i; + results[j] = strtod(param, &n); + if (*n != '\0') { + // strtod failed--not a numeric representation. + cerr << "Warning: " << words[i] << " is not a number.\n"; + if (n == param) { + results[j] = 0.0; + } + } + } + + int ai = (int)results[0]; + int bi = (int)results[1]; + return format_int(ai - bi); +} + +//////////////////////////////////////////////////////////////////// +// Function: PPScope::expand_times +// Access: Private +// Description: Expands the "*" function variable. This operates +// on integer numbers. +//////////////////////////////////////////////////////////////////// +string PPScope:: +expand_times(const string ¶ms) { + double a, b; + if (!tokenize_numeric_pair(params, a, b)) { + return string(); + } + + int ai = (int)a; + int bi = (int)b; + return format_int(ai * bi); +} + +//////////////////////////////////////////////////////////////////// +// Function: PPScope::expand_divide +// Access: Private +// Description: Expands the "/" function variable. This operates +// on integer numbers. +//////////////////////////////////////////////////////////////////// +string PPScope:: +expand_divide(const string ¶ms) { + double a, b; + if (!tokenize_numeric_pair(params, a, b)) { + return string(); + } + + int ai = (int)a; + int bi = (int)b; + return format_int(ai / bi); +} + +//////////////////////////////////////////////////////////////////// +// Function: PPScope::expand_modulo +// Access: Private +// Description: Expands the "%" function variable. This operates +// on integer numbers. +//////////////////////////////////////////////////////////////////// +string PPScope:: +expand_modulo(const string ¶ms) { + double a, b; + if (!tokenize_numeric_pair(params, a, b)) { + return string(); + } + + int ai = (int)a; + int bi = (int)b; + return format_int(ai % bi); +} + //////////////////////////////////////////////////////////////////// // Function: PPScope::expand_not // Access: Private @@ -2948,8 +3090,9 @@ expand_function(const string &funcname, PPScope nested_scope(_named_scopes); nested_scope.define_formals(funcname, sub->_formals, params); - // This won't compile on VC++. It has only ostringstream, which is - // functionally equivalent but has a slightly different interface. + // This won't compile on VC++ with the new iostream library. It has + // only ostringstream, which is functionally equivalent but has a + // slightly different interface. ostrstream ostr; PPCommandFile command(&nested_scope); diff --git a/ppremake/ppScope.h b/ppremake/ppScope.h index 4cd2898440..7c5ba8d1ff 100644 --- a/ppremake/ppScope.h +++ b/ppremake/ppScope.h @@ -62,6 +62,7 @@ public: bool expand); bool tokenize_numeric_pair(const string &str, double &a, double &b); size_t scan_to_whitespace(const string &str, size_t start = 0); + static string format_int(int num); static MapVariableDefinition _null_map_def; @@ -123,6 +124,11 @@ private: string expand_len(const string ¶ms); string expand_gtn(const string ¶ms); string expand_gen(const string ¶ms); + string expand_plus(const string ¶ms); + string expand_minus(const string ¶ms); + string expand_times(const string ¶ms); + string expand_divide(const string ¶ms); + string expand_modulo(const string ¶ms); string expand_not(const string ¶ms); string expand_or(const string ¶ms); string expand_and(const string ¶ms);