Browse Source

Good error reporting. Fix some ugly output.

git-svn-id: https://klish.googlecode.com/svn/trunk@520 0eaa4687-2ee9-07dd-09d9-bcdd2d2dd5fb
Serj Kalichev 12 years ago
parent
commit
51afca2c7b
4 changed files with 76 additions and 54 deletions
  1. 3 1
      clish/shell/private.h
  2. 35 20
      clish/shell/shell_file.c
  3. 28 11
      clish/shell/shell_tinyrl.c
  4. 10 22
      tinyrl/tinyrl.c

+ 3 - 1
clish/shell/private.h

@@ -27,7 +27,9 @@ typedef struct clish_shell_file_s clish_shell_file_t;
 struct clish_shell_file_s {
 	clish_shell_file_t *next;
 	FILE *file;
-	bool_t stop_on_error;	/* stop on error for file input  */
+	char *fname;
+	unsigned int line;
+	bool_t stop_on_error; /* stop on error for file input  */
 };
 
 typedef struct {

+ 35 - 20
clish/shell/shell_file.c

@@ -1,8 +1,38 @@
 #include <stdlib.h>
 #include <assert.h>
 
+#include "lub/string.h"
 #include "private.h"
 
+/*----------------------------------------------------------- */
+static int clish_shell_push(clish_shell_t * this, FILE * file,
+	const char *fname, bool_t stop_on_error)
+{
+	/* Allocate a control node */
+	clish_shell_file_t *node = malloc(sizeof(clish_shell_file_t));
+
+	assert(this);
+	assert(node);
+
+	/* intialise the node */
+	node->file = file;
+	if (fname)
+		node->fname = lub_string_dup(fname);
+	else
+		node->fname = NULL;
+	node->line = 0;
+	node->stop_on_error = stop_on_error;
+	node->next = this->current_file;
+
+	/* put the node at the top of the file stack */
+	this->current_file = node;
+
+	/* now switch the terminal's input stream */
+	tinyrl__set_istream(this->tinyrl, file);
+
+	return 0;
+}
+
 /*----------------------------------------------------------- */
 int clish_shell_push_file(clish_shell_t * this, const char * fname,
 	bool_t stop_on_error)
@@ -16,7 +46,7 @@ int clish_shell_push_file(clish_shell_t * this, const char * fname,
 	file = fopen(fname, "r");
 	if (!file)
 		return -1;
-	res = clish_shell_push_fd(this, file, stop_on_error);
+	res = clish_shell_push(this, file, fname, stop_on_error);
 	if (res)
 		fclose(file);
 
@@ -24,27 +54,10 @@ int clish_shell_push_file(clish_shell_t * this, const char * fname,
 }
 
 /*----------------------------------------------------------- */
-int clish_shell_push_fd(clish_shell_t * this, FILE * file,
+int clish_shell_push_fd(clish_shell_t *this, FILE *file,
 	bool_t stop_on_error)
 {
-	/* Allocate a control node */
-	clish_shell_file_t *node = malloc(sizeof(clish_shell_file_t));
-
-	assert(this);
-	assert(node);
-
-	/* intialise the node */
-	node->file = file;
-	node->stop_on_error = stop_on_error;
-	node->next = this->current_file;
-
-	/* put the node at the top of the file stack */
-	this->current_file = node;
-
-	/* now switch the terminal's input stream */
-	tinyrl__set_istream(this->tinyrl, file);
-
-	return 0;
+	return clish_shell_push(this, file, NULL, stop_on_error);
 }
 
 /*----------------------------------------------------------- */
@@ -66,6 +79,8 @@ int clish_shell_pop_file(clish_shell_t *this)
 		result = 0;
 	}
 	/* and free up the memory */
+	if (node->fname)
+		lub_string_free(node->fname);
 	free(node);
 
 	return result;

+ 28 - 11
clish/shell/shell_tinyrl.c

@@ -211,6 +211,10 @@ static bool_t clish_shell_tinyrl_key_enter(tinyrl_t *this, int key)
 	const clish_command_t *cmd = NULL;
 	const char *line = tinyrl__get_line(this);
 	bool_t result = BOOL_FALSE;
+	char *errmsg = NULL;
+
+	/* Inc line counter */
+	context->shell->current_file->line++;
 
 	/* Renew prompt */
 	clish_shell_renew_prompt(this);
@@ -218,7 +222,7 @@ static bool_t clish_shell_tinyrl_key_enter(tinyrl_t *this, int key)
 	/* nothing to pass simply move down the screen */
 	if (!*line) {
 		tinyrl_crlf(this);
-		tinyrl_reset_line_state(this);
+		tinyrl_done(this);
 		return BOOL_TRUE;
 	}
 
@@ -245,6 +249,11 @@ static bool_t clish_shell_tinyrl_key_enter(tinyrl_t *this, int key)
 			break;
 		default:
 			/* failed to get a unique match... */
+			if (!tinyrl__get_isatty(this)) {
+				/* batch mode */
+				tinyrl_crlf(this);
+				errmsg = "Unknown command";
+			}
 			break;
 		}
 	}
@@ -254,33 +263,41 @@ static bool_t clish_shell_tinyrl_key_enter(tinyrl_t *this, int key)
 		/* we've got a command so check the syntax */
 		arg_status = clish_shell_parse(context->shell,
 			line, &context->cmd, &context->pargv);
-		if (CLISH_LINE_OK != arg_status) {
-			fprintf(stderr, "Syntax error on line \"%s\":\n",
-				line);
-		}
 		switch (arg_status) {
 		case CLISH_LINE_OK:
 			tinyrl_done(this);
 			result = BOOL_TRUE;
 			break;
 		case CLISH_BAD_HISTORY:
-			fprintf(stderr, "Bad history entry.\n");
+			errmsg = "Bad history entry";
 			break;
 		case CLISH_BAD_CMD:
-			fprintf(stderr, "Illegal command line.\n");
+			errmsg = "Illegal command line";
 			break;
 		case CLISH_BAD_PARAM:
-			fprintf(stderr, "Illegal parameter.\n");
+			errmsg = "Illegal parameter";
 			break;
 		case CLISH_LINE_PARTIAL:
-			fprintf(stderr, "The command is not completed.\n");
+			errmsg = "The command is not completed";
 			break;
 		default:
-			fprintf(stderr, "Unknown problem.\n");
+			errmsg = "Unknown problem";
 			break;
 		}
-		if (CLISH_LINE_OK != arg_status)
+	}
+	/* If error then print message */
+	if (errmsg) {
+		if (tinyrl__get_isatty(this)) {
+			fprintf(stderr, "Syntax error: %s\n", errmsg);
 			tinyrl_reset_line_state(this);
+		} else {
+			char *fname = "stdin";
+			if (context->shell->current_file->fname)
+				fname = context->shell->current_file->fname;
+			fprintf(stderr, "Syntax error on line %s:%u \"%s\": "
+			"%s\n", fname, context->shell->current_file->line,
+			line, errmsg);
+		}
 	}
 	/* keep the compiler happy */
 	key = key;

+ 10 - 22
tinyrl/tinyrl.c

@@ -622,10 +622,9 @@ static char *internal_insertline(tinyrl_t * this, char *buffer)
 	char *s = buffer;
 
 	/* strip any spurious '\r' or '\n' */
-	p = strchr(buffer, '\r');
-	if (!p)
-		p = strchr(buffer, '\n');
-	if (p)
+	if ((p = strchr(buffer, '\r')))
+		*p = '\0';
+	if ((p = strchr(buffer, '\n')))
 		*p = '\0';
 	/* skip any whitespace at the beginning of the line */
 	if (0 == this->point) {
@@ -635,9 +634,9 @@ static char *internal_insertline(tinyrl_t * this, char *buffer)
 	if (*s) {
 		/* append this string to the input buffer */
 		(void)tinyrl_insert_text(this, s);
-		/* echo the command to the output stream */
-		tinyrl_redisplay(this);
 	}
+	/* echo the command to the output stream */
+	tinyrl_redisplay(this);
 
 	return s;
 }
@@ -647,7 +646,6 @@ static char *internal_readline(tinyrl_t * this,
 	const char *prompt, void *context, const char *str)
 {
 	FILE *istream = tinyrl_vt100__get_istream(this->term);
-	int crlf = 1; /* Enable crlf if result is NULL */
 	char *result = NULL;
 	int lerrno = 0;
 
@@ -726,9 +724,8 @@ static char *internal_readline(tinyrl_t * this,
 				s = internal_insertline(this, buffer);
 				len = strlen(buffer) + 1; /* account for the '\0' */
 			}
-			if (!s || (this->line[0] == '\0' && feof(istream))) {
+			if (!s || ((this->line[0] == '\0') && feof(istream))) {
 				/* time to finish the session */
-				crlf = 0;
 				this->line = NULL;
 				lerrno = ENOENT;
 			}
@@ -739,15 +736,10 @@ static char *internal_readline(tinyrl_t * this,
 		 * This is a measure to stop potential task spin on encountering an
 		 * error from fgets.
 		 */
-		if (this->line) {
-			if (this->line[0] == '\0') {
-				tinyrl_reset_line_state(this);
-			} else if (!this->handlers[KEY_LF](this, KEY_LF)) {
-				/* an issue has occured */
-				tinyrl_ding(this);
-				this->line = NULL;
-				lerrno = EBADMSG;
-			}
+		if (this->line && !this->handlers[KEY_LF](this, KEY_LF)) {
+			/* an issue has occured */
+			this->line = NULL;
+			lerrno = EBADMSG;
 		}
 		if (str)
 			lub_string_free(tmp);
@@ -763,10 +755,6 @@ static char *internal_readline(tinyrl_t * this,
 	free(this->buffer);
 	this->buffer = NULL;
 
-	/* make sure we're not left on a prompt line */
-	if (crlf && (!result || ('\0' == *result)))
-		tinyrl_crlf(this);
-
 	if (!result)
 		errno = lerrno; /* get saved errno */
 	return result;