1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
// #define DEBUG_WHILE
#include <string>
#include <math.h>
#include <stdio.h>
#include "private.hh"
#include "extern.hh"
#include "gr.hh"
bool whileCmd(void);
static bool test_is_true(const std::string& t);
bool
whileCmd(void)
{
std::string test(6 + strstr(_cmdLine, "while"));
if (re_compare(test.c_str(), " *")) {
err("`while .test.|{rpn ...}' missing the test part");
return false;
}
int loop_level = 1;
int lines = 0;
//printf("=============== in while cmd. '%s' test '%s'\n",_cmdLine,test.c_str());
test_is_true(test); // to catch syntax errors on this line
// Store lines until end while into the buffer
std::string buffer;
while (1) {
if (!get_command_line()) {
err("Missing `end while'");
return false;
}
lines++;
// Search for matching end while
if (re_compare(_cmdLine, "\\s*while.*")) {
loop_level++;
} else {
// Search for `end while', but first make a copy
// without the source_indicator
char *copy = (char*)malloc((1 + strlen(_cmdLine)) * sizeof(char));
if (!copy) OUT_OF_MEMORY;
strcpy(copy, _cmdLine);
int len = strlen(copy);
for (int i = 0; i < len; i++) {
if (copy[i] == PASTE_CHAR) {
copy[i] = '\0';
break;
}
}
if (re_compare(copy, "\\s*end\\s+while.*")) {
loop_level--;
if (loop_level < 1) {
break;
}
}
free(copy);
}
buffer.append(_cmdLine);
buffer.append("\n");
}
perform_while_block(buffer.c_str(), test.c_str(), lines);
return true;
}
#define DEBUG 1
const int NOTIFY = 1000;
bool
perform_while_block(const char *buffer, const char *test, int lines)
{
//printf("^^^^^^^^^^^^ perform_while_block(...,%s,...)\n",test);
std::string filename;
int fileline;
int passes = 0;
std::string t(test);
while (test_is_true(t)) {
// Check to see if test is now false
if (block_level() > 0) {
filename.assign(block_source_file());
fileline = block_source_line() + 2;
#ifdef DEBUG_WHILE
printf("Register while AT BLOCKLEVEL = %d at %s:%d lines=%d\n",
block_level(),
block_source_file(),
block_source_line() + 2,
block_line());
#endif
} else {
filename.assign(what_file());
fileline = what_line() - lines + 1;
#ifdef DEBUG_WHILE
printf("Register OUT OF BLOCK while at %s:%d\n",
what_file(),
what_line() - lines + 1);
#endif
}
if (!perform_block(buffer, filename.c_str(), fileline)) {
// got break
break;
}
passes++;
if (_chatty > 0 && !(passes % NOTIFY)) {
char msg[100];
sprintf(msg, "`while' performed %d passes\n", passes);
gr_textput(msg);
}
}
#ifdef DEBUG_WHILE
printf("\nFINISHED WITH LOOP\n");
#endif
return true;
}
static bool
test_is_true(const std::string& t)
{
std::string tt;
substitute_synonyms(t.c_str(), tt, true);
clean_blanks_quotes(tt);
// Catch "! SOMETHING" form
bool negate = false;
if (tt[0] == '!') {
negate = true;
tt.STRINGERASE(0, 1);
clean_blanks_quotes(tt);
}
char res[100]; // BUG: fixed size
substitute_rpn_expressions(tt.c_str(), res);
//printf(" + '%s' -> '%s'\n", t.c_str(),tt.c_str());
double value;
if (is_var(res)) {
getdnum(res, &value);
} else {
sscanf(res, "%lf", &value);
}
if (negate)
return ((value != 0.0) ? false : true);
else
return ((value != 0.0) ? true : false);
}
|