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 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
|
#include <stdio.h>
#include <string.h>
#include "extern.hh"
#include "private.hh"
#include "gr.hh"
extern char _grTempString[];
static bool find_hint_and_def(char *hint, char *def);
static void show_valid_choices(char *hint, char *def_word[], int def_words);
// `query \synonym|.variable ["\prompt" [(DEFAULT[s])]'
#define NCHAR 256
bool
queryCmd()
{
char hint[NCHAR];
char answer[NCHAR];
char def[NCHAR], *def_word[NCHAR];
unsigned int def_words = 0;
bool user_replied = true;
if (_nword < 2) {
demonstrate_command_usage();
err("`query' what?");
return false;
}
// Check that target synonym or variable is well-formed.
if (!is_syn(_word[1]) && !is_var(_word[1])) {
demonstrate_command_usage();
err("Can't interpret `\\",
_word[1],
"' as a synonym or variable name.",
"\\");
return false;
}
answer[0] = '\0'; // prevent problems later
if (!find_hint_and_def(hint, def)) {
return false;
}
def_word[0] = '\0';
chop_into_words(def, def_word, &def_words, NCHAR);
// Strip off double-quotes form list of defaults
for (unsigned int i = 0; i < def_words; i++) {
if (*def_word[i] == '"') {
def_word[i] = 1 + def_word[i];
if (*(def_word[i] + strlen(def_word[i]) - 1) == '"') {
*(def_word[i] + strlen(def_word[i]) - 1) = '\0';
}
}
}
if (_use_default_for_query) {
strcpy(answer, def_word[0]);
} else {
// In non-batch mode, print prompt and default
if (!batch()) {
if (hint[0] != '\0') {
switch (def_words) {
case 0:
sprintf(_grTempString, "%s : ", hint);
gr_textput(_grTempString);
break;
default:
show_valid_choices(hint, def_word, def_words);
break;
}
} else {
sprintf(_grTempString, "Please give value of %s ", _word[1]);
gr_textput(_grTempString);
}
beep_terminal();
}
// Get the answer
gr_textget(answer, NCHAR);
answer[strlen(answer) - 1] = '\0';
// If no string supplied, use default if have one
if (strlen(answer) < 1) {
if (def[0] != '\0') {
strcpy(answer, def_word[0]);
} else {
err("No response and no default, so I won't define the synonym");
return false;
}
user_replied = false;
} else {
// They gave a string. If there was a list of acceptable
// choices, check that string was in list.
if (def_words > 1) {
bool acceptable = false;
while (!acceptable) {
for (unsigned int i = 0; i < def_words; i++) {
if (!strcmp(def_word[i], answer)) {
acceptable = true;
break;
}
}
if (acceptable)
break;
gr_textput(" Sorry, this is an invalid answer. Try again.\n");
show_valid_choices(hint, def_word, def_words);
gr_textget(answer, LineLength_1);
answer[strlen(answer) - 1] = '\0';
if (strlen(answer) < 1) {
strcpy(answer, def_word[0]);
break;
}
}
}
}
}
// Store result into the target variable or synonym
if (is_syn(_word[1])) {
if (!put_syn(_word[1], answer, true)) {
sprintf(_grTempString,
"Sorry, synonym stack exhausted; no space for `%s'",
_word[1]);
fatal_err(_grTempString);
return false;
}
} else if (is_var(_word[1])) {
double value;
bool old = _ignore_error;
_ignore_error = true;
if (getdnum(answer, &value)) {
PUT_VAR(_word[1], value);
} else {
if (user_replied) {
if (!_cmdFILE.back().get_interactive()) {
fatal_err("`query' cannot understand number in reply `\\",
answer,
"'.",
"\\");
} else {
err("`query' cannot understand number in reply `\\",
answer,
"'.",
"\\");
}
} else {
if (!_cmdFILE.back().get_interactive()) {
fatal_err("`query' cannot understand number in default `\\",
answer,
"'.",
"\\");
} else {
err("`query' cannot understand number in default `\\",
answer,
"'.",
"\\");
}
}
_ignore_error = old;
}
} else {
// Actually, this code is a repeat of code above, and this line can
// never be reached in present version. But I'll keep it here for
// safety upon changes.
demonstrate_command_usage();
err("Can't interpret `\\",
_word[1],
"' as a synonym or variable name.",
"\\");
return false;
}
return true;
}
static void
show_valid_choices(char *hint, char *def_word[], int def_words)
{
if (def_words == 1) {
sprintf(_grTempString, "%s (default = `%s'): ", hint, def_word[0]);
gr_textput(_grTempString);
} else {
int i;
sprintf(_grTempString, "%s (default = `%s'; choices are", hint, def_word[0]);
gr_textput(_grTempString);
for (i = 0; i < def_words; i++) {
gr_textput(" `");
gr_textput(def_word[i]);
gr_textput("'");
}
gr_textput(") : ");
}
}
// find_hint_and_def -- find hint and default. (make def="" if no default)
// return true if ok, NO if deformed commandline
static bool
find_hint_and_def(char *hint, char *def)
{
int i;
int len = strlen(_cmdLine);
char lastc = '\0';
hint[0] = '\0';
def[0] = '\0';
// Find and extract hint, as first quoted string.
for (i = 0; i < len; i++) {
if (*(_cmdLine + i) == '\"') {
bool valid = false;
i++;
for (int ii = 0; ii < len - i; ii++) {
if (_cmdLine[i + ii] == '"' && lastc != '\\') {
hint[ii] = '\0';
valid = true;
break;
} else {
hint[ii] = _cmdLine[i + ii];
}
lastc = _cmdLine[i + ii];
}
if (valid) {
break;
}
}
}
// Extract default, as last string enclosed in parentheses
int def_start = -1, def_end = -1;
int level = 0;
for (i = len - 1; i > 0; i--) {
if (_cmdLine[i] == ')') {
if (level++ == 0)
def_end = i - 1;
} else if (_cmdLine[i] == '(') {
if (--level == 0) {
def_start = i + 1;
break;
}
}
}
if (def_start && !def_end) {
err("Default is malformed; have `(' but no `)'");
return false;
}
if (def_end && !def_start) {
err("Default is malformed; have `)' but no `('");
return false;
}
if (def_start > def_end) {
err("No default value found inside parentheses");
return false;
}
if (def_start > -1 && def_end > -1) {
for (i = def_start; i <= def_end; i++)
def[i - def_start] = _cmdLine[i];
def[1 + def_end - def_start] = '\0';
}
return true;
}
|