static uns ends_by_brace; // the line is ended by "{"
static int
-get_line(void)
+get_line(byte **msg)
{
- if (!bgets(parse_fb, line_buf, MAX_LINE))
- return 0;
+ int err = bgets_nodie(parse_fb, line_buf, MAX_LINE);
line_num++;
+ if (err <= 0) {
+ *msg = err < 0 ? "Line too long" : NULL;
+ return 0;
+ }
line = line_buf;
while (Cblank(*line))
line++;
copy_buf.ptr[copied-1] = 0;
}
-#define CONTROL_CHAR(x) (x == '{' || x == '}' || x == ';')
- // these characters separate words like blanks
-
static byte *
get_word(uns is_command_name)
{
+ byte *msg;
if (*line == '\'') {
line++;
while (1) {
if (*line)
break;
copy_buf.ptr[copied-1] = '\n';
- if (!get_line())
- return "Unterminated apostrophe word at the end";
+ if (!get_line(&msg))
+ return msg ? : (byte*) "Unterminated apostrophe word at the end";
}
line++;
copy_buf.ptr[copied-1] = '\n';
else // merge two lines
copied -= 2;
- if (!get_line())
- return "Unterminated quoted word at the end";
+ if (!get_line(&msg))
+ return msg ? : (byte*) "Unterminated quoted word at the end";
}
line++;
} else {
// promised that *line is non-null and non-blank
byte *start = line;
- while (*line && !Cblank(*line) && !CONTROL_CHAR(*line)
+ while (*line && !Cblank(*line)
+ && *line != '{' && *line != '}' && *line != ';'
&& (*line != '=' || !is_command_name))
line++;
if (*line == '=') { // nice for setting from a command-line
*msg = NULL;
while (1) {
if (!*line || *line == '#') {
- if (!is_command_name || !get_line())
+ if (!is_command_name || !get_line(msg))
return NULL;
} else if (*line == ';') {
*msg = get_word(0);
if (!is_command_name || *msg)
return NULL;
} else if (*line == '\\' && !line[1]) {
- if (!get_line()) {
- *msg = "Last line ends by a backslash";
+ if (!get_line(msg)) {
+ if (!*msg)
+ *msg = "Last line ends by a backslash";
return NULL;
}
if (!*line || *line == '#')
switch (Clocase(*c)) {
case 's': op = OP_SET; break;
case 'c': op = Clocase(c[1]) == 'l' ? OP_CLEAR: OP_COPY; break;
- case 'a': op = Clocase(c[1]) == 'p' ? OP_APPEND : OP_AFTER; break;
+ case 'a': switch (Clocase(c[1])) {
+ case 'p': op = OP_APPEND; break;
+ case 'f': op = OP_AFTER; break;
+ default: op = OP_ALL;
+ }; break;
case 'p': op = OP_PREPEND; break;
case 'r': op = OP_REMOVE; break;
case 'e': op = OP_EDIT; break;