add 1.1 elements: #for, #while, #mkdir
This commit is contained in:
parent
16a371eecb
commit
b7155fcde1
|
|
@ -80,5 +80,5 @@
|
|||
** Also be sure to change the version number **
|
||||
** at the beginning of configure.in. **
|
||||
**************** ****************/
|
||||
#define VERSION "1.05"
|
||||
#define VERSION "1.1"
|
||||
/**************** UPDATE VERSION NUMBER HERE ****************/
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ dnl **************** UPDATE VERSION NUMBER HERE ****************
|
|||
dnl ** Also be sure to change the version number **
|
||||
dnl ** at the end of config_msvc.h. **
|
||||
dnl **************** ****************
|
||||
AM_INIT_AUTOMAKE(ppremake, 1.05)
|
||||
AM_INIT_AUTOMAKE(ppremake, 1.1)
|
||||
dnl **************** UPDATE VERSION NUMBER HERE ****************
|
||||
|
||||
AM_CONFIG_HEADER(config.h)
|
||||
|
|
|
|||
|
|
@ -491,6 +491,11 @@ end_read() {
|
|||
cerr << "Unclosed begin " << _block_nesting->_name << "\n";
|
||||
break;
|
||||
|
||||
case BS_while:
|
||||
case BS_nested_while:
|
||||
cerr << "Unclosed while " << _block_nesting->_name << "\n";
|
||||
break;
|
||||
|
||||
case BS_forscopes:
|
||||
case BS_nested_forscopes:
|
||||
cerr << "Unclosed forscopes " << _block_nesting->_name << "\n";
|
||||
|
|
@ -597,6 +602,12 @@ handle_command(const string &line) {
|
|||
} else if (_command == "begin") {
|
||||
return handle_begin_command();
|
||||
|
||||
} else if (_command == "while") {
|
||||
return handle_while_command();
|
||||
|
||||
} else if (_command == "for") {
|
||||
return handle_for_command();
|
||||
|
||||
} else if (_command == "forscopes") {
|
||||
return handle_forscopes_command();
|
||||
|
||||
|
|
@ -645,6 +656,9 @@ handle_command(const string &line) {
|
|||
} else if (_command == "error") {
|
||||
return handle_error_command();
|
||||
|
||||
} else if (_command == "mkdir") {
|
||||
return handle_mkdir_command();
|
||||
|
||||
} else if (_command == "defer") {
|
||||
return handle_defer_command();
|
||||
|
||||
|
|
@ -831,6 +845,70 @@ handle_begin_command() {
|
|||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPCommandFile::handle_while_command
|
||||
// Access: Protected
|
||||
// Description: Handles the #while command: repeat a block of
|
||||
// commands while a condition is true (nonempty).
|
||||
// Unlike many of the other block commands, this does
|
||||
// not begin a new scope.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PPCommandFile::
|
||||
handle_while_command() {
|
||||
BlockState state = _in_for ? BS_nested_while : BS_while;
|
||||
string name = trim_blanks(_params);
|
||||
BlockNesting *nest = new BlockNesting(state, name);
|
||||
nest->push(this);
|
||||
|
||||
if (!_in_for) {
|
||||
_in_for = true;
|
||||
_saved_lines.clear();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPCommandFile::handle_for_command
|
||||
// Access: Protected
|
||||
// Description: Handles the #for command: repeat a block of
|
||||
// commands with a loop variable iterating over a range
|
||||
// of numeric values.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PPCommandFile::
|
||||
handle_for_command() {
|
||||
// We get the name of the variable out first.
|
||||
size_t p = _scope->scan_to_whitespace(_params);
|
||||
string name = _params.substr(0, p);
|
||||
|
||||
if (name.empty()) {
|
||||
cerr << "#for without varname\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
// The rest is the comma-delimited range of values.
|
||||
vector<string> words;
|
||||
_scope->tokenize_params(_params.substr(p), words, true);
|
||||
if (words.size() != 2 && words.size() != 3) {
|
||||
cerr << "Invalid numeric range: '" << _params.substr(p)
|
||||
<< "' for #for " << name << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
BlockState state = _in_for ? BS_nested_for : BS_for;
|
||||
BlockNesting *nest = new BlockNesting(state, name);
|
||||
nest->push(this);
|
||||
|
||||
if (!_in_for) {
|
||||
_in_for = true;
|
||||
_saved_lines.clear();
|
||||
|
||||
nest->_words.swap(words);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPCommandFile::handle_forscopes_command
|
||||
// Access: Protected
|
||||
|
|
@ -1034,12 +1112,12 @@ handle_output_command() {
|
|||
return false;
|
||||
}
|
||||
|
||||
string prefix = _scope->expand_variable("DIRPREFIX");
|
||||
if (filename[0] != '/') {
|
||||
string prefix = _scope->expand_variable("DIRPREFIX");
|
||||
filename = prefix + filename;
|
||||
}
|
||||
|
||||
nest->_filename = filename;
|
||||
nest->_params = filename;
|
||||
|
||||
// Generate an in-memory copy of the file first.
|
||||
_write_state = new WriteState(*_write_state);
|
||||
|
|
@ -1083,7 +1161,21 @@ handle_end_command() {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (nest->_state == BS_forscopes) {
|
||||
if (nest->_state == BS_while) {
|
||||
// Now replay all of the saved lines.
|
||||
_in_for = false;
|
||||
if (!replay_while(nest->_name)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
} else if (nest->_state == BS_for) {
|
||||
// Now replay all of the saved lines.
|
||||
_in_for = false;
|
||||
if (!replay_for(nest->_name, nest->_words)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
} else if (nest->_state == BS_forscopes) {
|
||||
// Now replay all of the saved lines.
|
||||
_in_for = false;
|
||||
if (!replay_forscopes(nest->_name)) {
|
||||
|
|
@ -1126,7 +1218,7 @@ handle_end_command() {
|
|||
} else if (nest->_state == BS_output) {
|
||||
if (!_in_for) {
|
||||
if (!nest->_output) {
|
||||
cerr << "Error while writing " << nest->_filename << "\n";
|
||||
cerr << "Error while writing " << nest->_params << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -1135,7 +1227,7 @@ handle_end_command() {
|
|||
|
||||
nest->_output << ends;
|
||||
const char *generated_file = nest->_output.str();
|
||||
if (!compare_output(generated_file, nest->_filename,
|
||||
if (!compare_output(generated_file, nest->_params,
|
||||
(nest->_flags & OF_notouch) != 0)) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1327,6 +1419,34 @@ handle_error_command() {
|
|||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPCommandFile::handle_mkdir_command
|
||||
// Access: Protected
|
||||
// Description: Handles the #mkdir command: create a directory or
|
||||
// directories.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PPCommandFile::
|
||||
handle_mkdir_command() {
|
||||
vector<string> words;
|
||||
tokenize_whitespace(_scope->expand_string(_params), words);
|
||||
|
||||
if (words.empty()) {
|
||||
cerr << "No directory name specifed to #mkdir.\n";
|
||||
} else {
|
||||
vector<string>::const_iterator wi;
|
||||
for (wi = words.begin(); wi != words.end(); ++wi) {
|
||||
Filename dirname(*wi, ".");
|
||||
if (!dirname.make_dir()) {
|
||||
if (!dirname.is_directory()) {
|
||||
cerr << "Unable to create directory " << *wi << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPCommandFile::handle_defer_command
|
||||
// Access: Protected
|
||||
|
|
@ -1572,6 +1692,118 @@ include_file(Filename filename) {
|
|||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPCommandFile::replay_while
|
||||
// Access: Protected
|
||||
// Description: Replays all the lines that were saved during a
|
||||
// previous #while..#end block.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PPCommandFile::
|
||||
replay_while(const string &name) {
|
||||
assert(!_in_for);
|
||||
|
||||
bool okflag = true;
|
||||
|
||||
vector<string> lines;
|
||||
lines.swap(_saved_lines);
|
||||
|
||||
// Remove the #end command. This will fail if someone makes an #end
|
||||
// command that spans multiple lines. Don't do that.
|
||||
assert(!lines.empty());
|
||||
lines.pop_back();
|
||||
|
||||
// Now replay all of the saved lines.
|
||||
BlockNesting *saved_block = _block_nesting;
|
||||
IfNesting *saved_if = _if_nesting;
|
||||
|
||||
while (!_scope->expand_string(name).empty()) {
|
||||
vector<string>::const_iterator li;
|
||||
for (li = lines.begin(); li != lines.end() && okflag; ++li) {
|
||||
okflag = read_line(*li);
|
||||
}
|
||||
}
|
||||
|
||||
if (saved_block != _block_nesting || saved_if != _if_nesting) {
|
||||
cerr << "Misplaced #end or #endif.\n";
|
||||
okflag = false;
|
||||
}
|
||||
|
||||
return okflag;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPCommandFile::replay_for
|
||||
// Access: Protected
|
||||
// Description: Replays all the lines that were saved during a
|
||||
// previous #for..#end block.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PPCommandFile::
|
||||
replay_for(const string &name, const vector<string> &words) {
|
||||
assert(!_in_for);
|
||||
|
||||
bool okflag = true;
|
||||
|
||||
vector<string> lines;
|
||||
lines.swap(_saved_lines);
|
||||
|
||||
// Remove the #end command. This will fail if someone makes an #end
|
||||
// command that spans multiple lines. Don't do that.
|
||||
assert(!lines.empty());
|
||||
lines.pop_back();
|
||||
|
||||
// Expand the variable name.
|
||||
string varname = _scope->expand_string(name);
|
||||
|
||||
// Get out the numeric range.
|
||||
int range[3] = {0, 0, 1};
|
||||
assert(words.size() <= 3);
|
||||
for (int i = 0; i < (int)words.size(); i++) {
|
||||
const char *param = words[i].c_str();
|
||||
char *n;
|
||||
range[i] = strtol(param, &n, 10);
|
||||
if (n == param) {
|
||||
cerr << "Invalid integer in #for: " << param << "\n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (range[2] == 0) {
|
||||
cerr << "Step by zero in #for " << name << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now replay all of the saved lines.
|
||||
BlockNesting *saved_block = _block_nesting;
|
||||
IfNesting *saved_if = _if_nesting;
|
||||
int index_var;
|
||||
|
||||
if (range[2] > 0) {
|
||||
for (index_var = range[0]; index_var <= range[1]; index_var += range[2]) {
|
||||
_scope->define_variable(varname, _scope->format_int(index_var));
|
||||
vector<string>::const_iterator li;
|
||||
for (li = lines.begin(); li != lines.end() && okflag; ++li) {
|
||||
okflag = read_line(*li);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (index_var = range[0]; index_var >= range[1]; index_var += range[2]) {
|
||||
_scope->define_variable(varname, _scope->format_int(index_var));
|
||||
vector<string>::const_iterator li;
|
||||
for (li = lines.begin(); li != lines.end() && okflag; ++li) {
|
||||
okflag = read_line(*li);
|
||||
}
|
||||
}
|
||||
}
|
||||
_scope->define_variable(varname, _scope->format_int(index_var));
|
||||
|
||||
if (saved_block != _block_nesting || saved_if != _if_nesting) {
|
||||
cerr << "Misplaced #end or #endif.\n";
|
||||
okflag = false;
|
||||
}
|
||||
|
||||
return okflag;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PPCommandFile::replay_forscopes
|
||||
// Access: Protected
|
||||
|
|
|
|||
|
|
@ -45,6 +45,8 @@ protected:
|
|||
bool handle_endif_command();
|
||||
|
||||
bool handle_begin_command();
|
||||
bool handle_while_command();
|
||||
bool handle_for_command();
|
||||
bool handle_forscopes_command();
|
||||
bool handle_foreach_command();
|
||||
bool handle_formap_command();
|
||||
|
|
@ -59,6 +61,7 @@ protected:
|
|||
bool handle_sinclude_command();
|
||||
bool handle_call_command();
|
||||
bool handle_error_command();
|
||||
bool handle_mkdir_command();
|
||||
|
||||
bool handle_defer_command();
|
||||
bool handle_define_command();
|
||||
|
|
@ -68,6 +71,8 @@ protected:
|
|||
bool handle_push_command();
|
||||
|
||||
bool include_file(Filename filename);
|
||||
bool replay_while(const string &name);
|
||||
bool replay_for(const string &name, const vector<string> &words);
|
||||
bool replay_forscopes(const string &name);
|
||||
bool replay_foreach(const string &varname, const vector<string> &words);
|
||||
bool replay_formap(const string &varname, const string &mapvar);
|
||||
|
|
@ -111,6 +116,10 @@ private:
|
|||
|
||||
enum BlockState {
|
||||
BS_begin,
|
||||
BS_while,
|
||||
BS_nested_while,
|
||||
BS_for,
|
||||
BS_nested_for,
|
||||
BS_forscopes,
|
||||
BS_nested_forscopes,
|
||||
BS_foreach,
|
||||
|
|
@ -157,7 +166,7 @@ private:
|
|||
IfNesting *_if;
|
||||
WriteState *_write_state;
|
||||
PPScope *_scope;
|
||||
string _filename;
|
||||
string _params;
|
||||
ostrstream _output;
|
||||
vector<string> _words;
|
||||
int _flags;
|
||||
|
|
|
|||
|
|
@ -2601,7 +2601,7 @@ expand_minus(const string ¶ms) {
|
|||
int num_words = words.size();
|
||||
|
||||
if (num_words == 1) {
|
||||
// Simular unary minus by setting the first operand to 0.
|
||||
// Simulate unary minus by setting the first operand to 0.
|
||||
results[0] = 0.0;
|
||||
|
||||
} else if (num_words != 2) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue