Index: src/bin/psql/command.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/psql/command.c,v
retrieving revision 1.93
diff -c -c -r1.93 command.c
*** src/bin/psql/command.c	19 Mar 2003 22:49:43 -0000	1.93
--- src/bin/psql/command.c	20 Mar 2003 06:42:19 -0000
***************
*** 669,683 ****
  		if (!opt0)
  		{
  			/* list all variables */
! 
! 			/*
! 			 * XXX This is in utter violation of the GetVariable
! 			 * abstraction, but I have not bothered to do it better.
! 			 */
! 			struct _variable *ptr;
! 
! 			for (ptr = pset.vars; ptr->next; ptr = ptr->next)
! 				fprintf(stdout, "%s = '%s'\n", ptr->next->name, ptr->next->value);
  			success = true;
  		}
  		else
--- 669,675 ----
  		if (!opt0)
  		{
  			/* list all variables */
! 			PrintVariables(pset.vars);
  			success = true;
  		}
  		else
***************
*** 1073,1081 ****
  				save_char = options_string[pos + token_end + 1];
  				options_string[pos + token_end + 1] = '\0';
  				value = GetVariable(pset.vars, options_string + pos + 1);
! 				if (!value)
! 					value = "";
! 				return_val = xstrdup(value);
  				options_string[pos + token_end + 1] = save_char;
  				*string = &options_string[pos + token_end + 1];
  				/* XXX should we set *quote to ':' here? */
--- 1065,1071 ----
  				save_char = options_string[pos + token_end + 1];
  				options_string[pos + token_end + 1] = '\0';
  				value = GetVariable(pset.vars, options_string + pos + 1);
! 				return_val = xstrdup(value ? value : "");
  				options_string[pos + token_end + 1] = save_char;
  				*string = &options_string[pos + token_end + 1];
  				/* XXX should we set *quote to ':' here? */
***************
*** 1287,1301 ****
  				case '7':
  				case '8':
  				case '9':
! 					{
! 						long int	l;
! 						char	   *end;
! 
! 						l = strtol(p, &end, 0);
! 						c = (char) l;
! 						p = end - 1;
  						break;
! 					}
  				default:
  					c = *p;
  			}
--- 1277,1285 ----
  				case '7':
  				case '8':
  				case '9':
! 					c = parse_char((char **)&p);
  						break;
! 
  				default:
  					c = *p;
  			}
Index: src/bin/psql/common.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/psql/common.c,v
retrieving revision 1.59
diff -c -c -r1.59 common.c
*** src/bin/psql/common.c	20 Mar 2003 06:00:12 -0000	1.59
--- src/bin/psql/common.c	20 Mar 2003 06:42:19 -0000
***************
*** 368,374 ****
  {
  	PGresult   *res = NULL;
  	PGresult   *newres;
! 	const char *var;
  	ExecStatusType rstatus;
  
  	if (!pset.db)
--- 368,374 ----
  {
  	PGresult   *res = NULL;
  	PGresult   *newres;
! 	int	echo_hidden;
  	ExecStatusType rstatus;
  
  	if (!pset.db)
***************
*** 377,393 ****
  		return NULL;
  	}
  
! 	var = GetVariable(pset.vars, "ECHO_HIDDEN");
! 	if (var)
  	{
  		printf("********* QUERY **********\n"
  			   "%s\n"
  			   "**************************\n\n", query);
  		fflush(stdout);
- 	}
  
! 	if (var && strcmp(var, "noexec") == 0)
  		return NULL;
  
  	/* discard any uneaten results of past queries */
  	while ((newres = PQgetResult(pset.db)) != NULL)
--- 377,393 ----
  		return NULL;
  	}
  
! 	echo_hidden = SwitchVariable(pset.vars, "ECHO_HIDDEN", "noexec", NULL);
! 	if (echo_hidden != var_notset)
  	{
  		printf("********* QUERY **********\n"
  			   "%s\n"
  			   "**************************\n\n", query);
  		fflush(stdout);
  
! 		if (echo_hidden == 1)
  		return NULL;
+ 	}
  
  	/* discard any uneaten results of past queries */
  	while ((newres = PQgetResult(pset.db)) != NULL)
***************
*** 579,591 ****
  	bool OK;
  
  	if (!pset.db)
! 			{
  		psql_error("You are currently not connected to a database.\n");
  		return false;
! 			}
  
  	if (GetVariableBool(pset.vars, "SINGLESTEP"))
! 			{
  		char		buf[3];
  
  		printf(gettext("***(Single step mode: Verify query)*********************************************\n"
--- 579,591 ----
  	bool OK;
  
  	if (!pset.db)
! 	{
  		psql_error("You are currently not connected to a database.\n");
  		return false;
! 	}
  
  	if (GetVariableBool(pset.vars, "SINGLESTEP"))
! 	{
  		char		buf[3];
  
  		printf(gettext("***(Single step mode: Verify query)*********************************************\n"
***************
*** 596,609 ****
  		if (fgets(buf, sizeof(buf), stdin) != NULL)
  			if (buf[0] == 'x')
  				return false;
- 			}
- 			else
- 		{
- 		const char *var = GetVariable(pset.vars, "ECHO");
- 
- 		if (var && strncmp(var, "queries", strlen(var)) == 0)
- 			puts(query);
  	}
  
  	SetCancelConn();
  
--- 596,604 ----
  		if (fgets(buf, sizeof(buf), stdin) != NULL)
  			if (buf[0] == 'x')
  				return false;
  	}
+ 	else if (VariableEquals(pset.vars, "ECHO", "queries"))
+ 		puts(query);
  
  	SetCancelConn();
  
***************
*** 619,621 ****
--- 614,628 ----
  	PrintNotifications();
  	return OK;
  }
+ 
+ 
+ char parse_char(char **buf)
+ {
+   long l;
+ 
+   l = strtol(*buf, buf, 0);
+   (*buf)--;
+   return (char)l;
+ }
+ 
+ 
Index: src/bin/psql/common.h
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/psql/common.h,v
retrieving revision 1.23
diff -c -c -r1.23 common.h
*** src/bin/psql/common.h	20 Mar 2003 06:00:12 -0000	1.23
--- src/bin/psql/common.h	20 Mar 2003 06:42:19 -0000
***************
*** 42,47 ****
--- 42,53 ----
  /* sprompt.h */
  extern char *simple_prompt(const char *prompt, int maxlen, bool echo);
  
+ /* Parse a numeric character code from the string pointed at by *buf, e.g.
+  * one written as 0x0c (hexadecimal) or 015 (octal); advance *buf to the last
+  * character of the numeric character code.
+  */
+ extern char parse_char(char **buf);
+ 
  /* Used for all Win32 popen/pclose calls */
  #ifdef WIN32
  #define popen(x,y) _popen(x,y)
Index: src/bin/psql/input.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/psql/input.c,v
retrieving revision 1.22
diff -c -c -r1.22 input.c
*** src/bin/psql/input.c	20 Mar 2003 06:00:12 -0000	1.22
--- src/bin/psql/input.c	20 Mar 2003 06:42:19 -0000
***************
*** 233,242 ****
  									strlen(PSQLHISTORY) + 1);
  			if (psql_history)
  			{
! 				const char *var = GetVariable(pset.vars, "HISTSIZE");
  
- 				if (var)
- 					stifle_history(atoi(var));
  				sprintf(psql_history, "%s/%s", home, PSQLHISTORY);
  				write_history(psql_history);
  				free(psql_history);
--- 233,244 ----
  									strlen(PSQLHISTORY) + 1);
  			if (psql_history)
  			{
! 				int hist_size;
! 				hist_size = GetVariableNum(pset.vars,"HISTSIZE",-1,-1,true);
! 
! 				if (hist_size >= 0)
! 					stifle_history(hist_size);
  
  				sprintf(psql_history, "%s/%s", home, PSQLHISTORY);
  				write_history(psql_history);
  				free(psql_history);
Index: src/bin/psql/large_obj.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/psql/large_obj.c,v
retrieving revision 1.23
diff -c -c -r1.23 large_obj.c
*** src/bin/psql/large_obj.c	15 Oct 2002 02:24:16 -0000	1.23
--- src/bin/psql/large_obj.c	20 Mar 2003 06:42:19 -0000
***************
*** 40,54 ****
  static bool
  handle_transaction(void)
  {
- 	const char *var = GetVariable(pset.vars, "LO_TRANSACTION");
  	PGresult   *res;
! 	bool		commit;
  	PQnoticeProcessor old_notice_hook;
  
! 	if (var && strcmp(var, "nothing") == 0)
  		return true;
! 
! 	commit = (var && strcmp(var, "commit") == 0);
  
  	notice[0] = '\0';
  	old_notice_hook = PQsetNoticeProcessor(pset.db, _my_notice_handler, NULL);
--- 40,59 ----
  static bool
  handle_transaction(void)
  {
  	PGresult   *res;
! 	bool		commit = false;
  	PQnoticeProcessor old_notice_hook;
  
! 	switch (SwitchVariable(pset.vars, "LO_TRANSACTION", 
! 									"nothing", 
! 									"commit", 
! 									NULL))
! 	{
! 	  case 1:
  		return true;
! 	  case 2:
! 		 commit = true;
! 	}
  
  	notice[0] = '\0';
  	old_notice_hook = PQsetNoticeProcessor(pset.db, _my_notice_handler, NULL);
***************
*** 87,97 ****
  {
  	PGresult   *res;
  	int			status;
! 	bool		own_transaction = true;
! 	const char *var = GetVariable(pset.vars, "LO_TRANSACTION");
  
! 	if (var && strcmp(var, "nothing") == 0)
! 		own_transaction = false;
  
  	if (!pset.db)
  	{
--- 92,100 ----
  {
  	PGresult   *res;
  	int			status;
! 	bool		own_transaction;
  
! 	own_transaction = VariableEquals(pset.vars, "LO_TRANSACTION", "nothing");
  
  	if (!pset.db)
  	{
***************
*** 154,164 ****
  	Oid			loid;
  	char		oidbuf[32];
  	unsigned int i;
! 	bool		own_transaction = true;
! 	const char *var = GetVariable(pset.vars, "LO_TRANSACTION");
  
! 	if (var && strcmp(var, "nothing") == 0)
! 		own_transaction = false;
  
  	if (!pset.db)
  	{
--- 157,165 ----
  	Oid			loid;
  	char		oidbuf[32];
  	unsigned int i;
! 	bool		own_transaction;
  
! 	own_transaction = VariableEquals(pset.vars, "LO_TRANSACTION", "nothing");
  
  	if (!pset.db)
  	{
***************
*** 271,281 ****
  	int			status;
  	Oid			loid = atooid(loid_arg);
  	char		buf[256];
- 	bool		own_transaction = true;
- 	const char *var = GetVariable(pset.vars, "LO_TRANSACTION");
  
! 	if (var && strcmp(var, "nothing") == 0)
! 		own_transaction = false;
  
  	if (!pset.db)
  	{
--- 272,281 ----
  	int			status;
  	Oid			loid = atooid(loid_arg);
  	char		buf[256];
  
! 	bool		own_transaction;
! 
! 	own_transaction = VariableEquals(pset.vars, "LO_TRANSACTION", "nothing");
  
  	if (!pset.db)
  	{
Index: src/bin/psql/mainloop.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/psql/mainloop.c,v
retrieving revision 1.52
diff -c -c -r1.52 mainloop.c
*** src/bin/psql/mainloop.c	20 Mar 2003 06:00:12 -0000	1.52
--- src/bin/psql/mainloop.c	20 Mar 2003 06:42:25 -0000
***************
*** 40,55 ****
  	char	   *line;			/* current line of input */
  	int			len;			/* length of the line */
  	volatile int successResult = EXIT_SUCCESS;
! 	volatile backslashResult slashCmdStatus;
  
  	bool		success;
! 	volatile char in_quote;		/* == 0 for no in_quote */
! 	volatile bool in_xcomment;	/* in extended comment */
! 	volatile int xcdepth;
! 	volatile int paren_level;
  	unsigned int query_start;
  	volatile int count_eof = 0;
- 	const char *var;
  	volatile unsigned int bslash_count = 0;
  
  	int			i,
--- 40,53 ----
  	char	   *line;			/* current line of input */
  	int			len;			/* length of the line */
  	volatile int successResult = EXIT_SUCCESS;
! 	volatile backslashResult slashCmdStatus = CMD_UNKNOWN;
  
  	bool		success;
! 	volatile char in_quote = 0;		/* == 0 for no in_quote */
! 	volatile int in_xcomment = 0;	/* in extended comment */
! 	volatile int paren_level = 0;
  	unsigned int query_start;
  	volatile int count_eof = 0;
  	volatile unsigned int bslash_count = 0;
  
  	int			i,
***************
*** 81,96 ****
  		exit(EXIT_FAILURE);
  	}
  
- 	in_xcomment = false;
- 	in_quote = 0;
- 	paren_level = 0;
- 	slashCmdStatus = CMD_UNKNOWN;		/* set default */
  	prev_lineno = pset.lineno;
  	pset.lineno = 0;
  
  
  	/* main loop to get queries and execute them */
! 	while (1)
  	{
  		/*
  		 * Welcome code for Control-C
--- 79,90 ----
  		exit(EXIT_FAILURE);
  	}
  
  	prev_lineno = pset.lineno;
  	pset.lineno = 0;
  
  
  	/* main loop to get queries and execute them */
! 	while (successResult == EXIT_SUCCESS)
  	{
  		/*
  		 * Welcome code for Control-C
***************
*** 109,114 ****
--- 103,109 ----
  			}
  
  			cancel_pressed = false;
+ 			fflush(stdout);
  		}
  
  #ifndef WIN32
***************
*** 118,132 ****
  
  			if (pset.cur_cmd_interactive)
  			{
! 				fputc('\n', stdout);
  				resetPQExpBuffer(query_buf);
  
  				/* reset parsing state */
! 				in_xcomment = false;
  				in_quote = 0;
  				paren_level = 0;
  				count_eof = 0;
  				slashCmdStatus = CMD_UNKNOWN;
  			}
  			else
  			{
--- 113,128 ----
  
  			if (pset.cur_cmd_interactive)
  			{
! 				putc('\n', stdout);
  				resetPQExpBuffer(query_buf);
  
  				/* reset parsing state */
! 				in_xcomment = 0;
  				in_quote = 0;
  				paren_level = 0;
  				count_eof = 0;
  				slashCmdStatus = CMD_UNKNOWN;
+ 				fflush(stdout);
  			}
  			else
  			{
***************
*** 151,173 ****
  			line = xstrdup(query_buf->data);
  			resetPQExpBuffer(query_buf);
  			/* reset parsing state since we are rescanning whole line */
! 			in_xcomment = false;
  			in_quote = 0;
  			paren_level = 0;
  			slashCmdStatus = CMD_UNKNOWN;
  		}
- 		else
- 		{
- 			fflush(stdout);
- 
  			/*
  			 * otherwise, set interactive prompt if necessary and get
  			 * another line
  			 */
! 			if (pset.cur_cmd_interactive)
  			{
  				int			prompt_status;
  
  				if (in_quote && in_quote == '\'')
  					prompt_status = PROMPT_SINGLEQUOTE;
  				else if (in_quote && in_quote == '"')
--- 147,167 ----
  			line = xstrdup(query_buf->data);
  			resetPQExpBuffer(query_buf);
  			/* reset parsing state since we are rescanning whole line */
! 			in_xcomment = 0;
  			in_quote = 0;
  			paren_level = 0;
  			slashCmdStatus = CMD_UNKNOWN;
  		}
  			/*
  			 * otherwise, set interactive prompt if necessary and get
  			 * another line
  			 */
! 		else if (pset.cur_cmd_interactive)
  			{
  				int			prompt_status;
  
+ 			fflush(stdout);
+ 
  				if (in_quote && in_quote == '\'')
  					prompt_status = PROMPT_SINGLEQUOTE;
  				else if (in_quote && in_quote == '"')
***************
*** 185,191 ****
  			}
  			else
  				line = gets_fromFile(source);
- 		}
  
  
  		/* Setting this will not have effect until next line. */
--- 179,184 ----
***************
*** 203,252 ****
  		{
  			if (pset.cur_cmd_interactive)
  			{
- 				bool		getout = true;
- 
  				/* This tries to mimic bash's IGNOREEOF feature. */
! 				const char *val = GetVariable(pset.vars, "IGNOREEOF");
! 
! 				if (val)
! 				{
! 					long int	maxeof;
! 					char	   *endptr;
! 
! 					if (*val == '\0')
! 						maxeof = 10;
! 					else
! 					{
! 						maxeof = strtol(val, &endptr, 0);
! 						if (*endptr != '\0')	/* string not valid as a
! 												 * number */
! 							maxeof = 10;
! 					}
! 
! 					if (count_eof++ != maxeof)
! 						getout = false; /* not quite there yet */
! 				}
  
! 				if (getout)
! 				{
! 					if (QUIET())
! 						putc('\n', stdout);
! 					else
! 						puts("\\q");
! 					break;
! 				}
! 				else
  				{
  					if (!QUIET())
  						printf(gettext("Use \"\\q\" to leave %s.\n"), pset.progname);
  					continue;
  				}
  			}
- 			else
- /* not interactive */
  				break;
  		}
! 		else
  			count_eof = 0;
  
  		pset.lineno++;
--- 196,216 ----
  		{
  			if (pset.cur_cmd_interactive)
  			{
  				/* This tries to mimic bash's IGNOREEOF feature. */
! 				count_eof++;
  
! 				if (count_eof < GetVariableNum(pset.vars,"IGNOREEOF",0,10,false))
  				{
  					if (!QUIET())
  						printf(gettext("Use \"\\q\" to leave %s.\n"), pset.progname);
  					continue;
  				}
+ 
+ 				puts(QUIET() ? "" : "\\q");
  			}
  				break;
  		}
! 
  			count_eof = 0;
  
  		pset.lineno++;
***************
*** 259,266 ****
  		}
  
  		/* echo back if flag is set */
! 		var = GetVariable(pset.vars, "ECHO");
! 		if (!pset.cur_cmd_interactive && var && strcmp(var, "all") == 0)
  			puts(line);
  		fflush(stdout);
  
--- 223,229 ----
  		}
  
  		/* echo back if flag is set */
! 		if (!pset.cur_cmd_interactive && VariableEquals(pset.vars, "ECHO", "all"))
  			puts(line);
  		fflush(stdout);
  
***************
*** 276,289 ****
  #define ADVANCE_1 (prevlen = thislen, i += thislen, thislen = PQmblen(line+i, pset.encoding))
  
  		success = true;
! 		for (i = 0, prevlen = 0, thislen = (len > 0) ? PQmblen(line, pset.encoding) : 0;
! 			 i < len;
! 			 ADVANCE_1)
  		{
  			/* was the previous character a backslash? */
! 			bool		was_bslash = (i > 0 && line[i - prevlen] == '\\');
! 
! 			if (was_bslash)
  				bslash_count++;
  			else
  				bslash_count = 0;
--- 239,251 ----
  #define ADVANCE_1 (prevlen = thislen, i += thislen, thislen = PQmblen(line+i, pset.encoding))
  
  		success = true;
! 		prevlen = 0;
! 		thislen = ((len > 0) ? PQmblen(line, pset.encoding) : 0);
! 
! 		for (i = 0; (i < len) && (success || !die_on_error); ADVANCE_1)
  		{
  			/* was the previous character a backslash? */
! 			if (i > 0 && line[i - prevlen] == '\\')
  				bslash_count++;
  			else
  				bslash_count = 0;
***************
*** 308,337 ****
  					in_quote = 0;
  			}
  
! 			/* in extended comment? */
! 			else if (in_xcomment)
! 			{
! 				if (line[i] == '*' && line[i + thislen] == '/')
! 				{
! 					if (xcdepth > 0)
! 						xcdepth--;
! 					else
  					{
! 						in_xcomment = false;
  						ADVANCE_1;
  					}
- 				}
- 				else if (line[i] == '/' && line[i + thislen] == '*')
- 					xcdepth++;
- 			}
  
! 			/* start of extended comment? */
! 			else if (line[i] == '/' && line[i + thislen] == '*')
  			{
! 				xcdepth = 0;
! 				in_xcomment = true;
  				ADVANCE_1;
  			}
  
  			/* start of quote? */
  			else if (line[i] == '\'' || line[i] == '"')
--- 270,293 ----
  					in_quote = 0;
  			}
  
! 			/* start of extended comment? */
! 			else if (line[i] == '/' && line[i + thislen] == '*')
  					{
! 				in_xcomment++;
! 				if (in_xcomment == 1) 
  						ADVANCE_1;
  					}
  
! 			/* end of extended comment? */
! 			else if (line[i] == '*' && line[i + thislen] == '/')
  			{
! 				in_xcomment--;
! 				if (in_xcomment <= 0)
! 				{
! 					in_xcomment = 0;
  				ADVANCE_1;
  			}
+ 			}
  
  			/* start of quote? */
  			else if (line[i] == '\'' || line[i] == '"')
***************
*** 353,359 ****
  
  			/* colon -> substitute variable */
  			/* we need to be on the watch for the '::' operator */
! 			else if (line[i] == ':' && !was_bslash
  				  && strspn(line + i + thislen, VALID_VARIABLE_CHARS) > 0
  					 && !(prevlen > 0 && line[i - prevlen] == ':')
  				)
--- 309,315 ----
  
  			/* colon -> substitute variable */
  			/* we need to be on the watch for the '::' operator */
! 			else if (line[i] == ':' && !bslash_count
  				  && strspn(line + i + thislen, VALID_VARIABLE_CHARS) > 0
  					 && !(prevlen > 0 && line[i - prevlen] == ':')
  				)
***************
*** 411,417 ****
  			}
  
  			/* semicolon? then send query */
! 			else if (line[i] == ';' && !was_bslash && !paren_level)
  			{
  				line[i] = '\0';
  				/* is there anything else on the line? */
--- 367,373 ----
  			}
  
  			/* semicolon? then send query */
! 			else if (line[i] == ';' && !bslash_count && !paren_level)
  			{
  				line[i] = '\0';
  				/* is there anything else on the line? */
***************
*** 442,448 ****
  			 * if you have a burning need to send a semicolon or colon to
  			 * the backend ...
  			 */
! 			else if (was_bslash && (line[i] == ';' || line[i] == ':'))
  			{
  				/* remove the backslash */
  				memmove(line + i - prevlen, line + i, len - i + 1);
--- 398,404 ----
  			 * if you have a burning need to send a semicolon or colon to
  			 * the backend ...
  			 */
! 			else if (bslash_count && (line[i] == ';' || line[i] == ':'))
  			{
  				/* remove the backslash */
  				memmove(line + i - prevlen, line + i, len - i + 1);
***************
*** 451,457 ****
  			}
  
  			/* backslash command */
! 			else if (was_bslash)
  			{
  				const char *end_of_cmd = NULL;
  
--- 407,413 ----
  			}
  
  			/* backslash command */
! 			else if (bslash_count)
  			{
  				const char *end_of_cmd = NULL;
  
***************
*** 499,513 ****
  					paren_level = 0;
  
  				/* process anything left after the backslash command */
! 				i += end_of_cmd - &line[i];
  				query_start = i;
  			}
- 
- 
- 			/* stop the script after error */
- 			if (!success && die_on_error)
- 				break;
- 
  		}						/* for (line) */
  
  
--- 455,463 ----
  					paren_level = 0;
  
  				/* process anything left after the backslash command */
! 				i = end_of_cmd - line;
  				query_start = i;
  			}
  		}						/* for (line) */
  
  
***************
*** 533,557 ****
  		if (query_buf->data[0] != '\0' && GetVariableBool(pset.vars, "SINGLELINE"))
  		{
  			success = SendQuery(query_buf->data);
! 			slashCmdStatus = success ? CMD_SEND : CMD_ERROR;
  			resetPQExpBuffer(previous_buf);
  			appendPQExpBufferStr(previous_buf, query_buf->data);
  			resetPQExpBuffer(query_buf);
  		}
  
! 
! 		if (!success && die_on_error && !pset.cur_cmd_interactive)
  		{
  			successResult = EXIT_USER;
- 			break;
- 		}
- 
- 
  		/* Have we lost the db connection? */
! 		if (pset.db == NULL && !pset.cur_cmd_interactive)
! 		{
  			successResult = EXIT_BADCONN;
- 			break;
  		}
  	}							/* while !endoffile/session */
  
--- 483,501 ----
  		if (query_buf->data[0] != '\0' && GetVariableBool(pset.vars, "SINGLELINE"))
  		{
  			success = SendQuery(query_buf->data);
! 			slashCmdStatus = (success ? CMD_SEND : CMD_ERROR);
  			resetPQExpBuffer(previous_buf);
  			appendPQExpBufferStr(previous_buf, query_buf->data);
  			resetPQExpBuffer(query_buf);
  		}
  
! 		if (!pset.cur_cmd_interactive)
  		{
+ 			if (!success && die_on_error)
  			successResult = EXIT_USER;
  		/* Have we lost the db connection? */
! 			else if (!pset.db)
  			successResult = EXIT_BADCONN;
  		}
  	}							/* while !endoffile/session */
  
Index: src/bin/psql/prompt.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/psql/prompt.c,v
retrieving revision 1.22
diff -c -c -r1.22 prompt.c
*** src/bin/psql/prompt.c	25 Oct 2001 05:49:54 -0000	1.22
--- src/bin/psql/prompt.c	20 Mar 2003 06:42:26 -0000
***************
*** 69,85 ****
  	char		buf[MAX_PROMPT_SIZE + 1];
  	bool		esc = false;
  	const char *p;
! 	const char *prompt_string;
  
! 	if (status == PROMPT_READY)
! 		prompt_string = GetVariable(pset.vars, "PROMPT1");
! 	else if (status == PROMPT_CONTINUE || status == PROMPT_SINGLEQUOTE || status == PROMPT_DOUBLEQUOTE || status == PROMPT_COMMENT || status == PROMPT_PAREN)
! 		prompt_string = GetVariable(pset.vars, "PROMPT2");
! 	else if (status == PROMPT_COPY)
! 		prompt_string = GetVariable(pset.vars, "PROMPT3");
! 	else
! 		prompt_string = "? ";
  
  
  	destination[0] = '\0';
  
--- 69,98 ----
  	char		buf[MAX_PROMPT_SIZE + 1];
  	bool		esc = false;
  	const char *p;
! 	const char *prompt_string = "? ";
! 	const char *prompt_name = NULL;
  
! 	switch (status)
! 	{
! 		case PROMPT_READY:
! 			prompt_name = "PROMPT1";
! 			break;
! 
! 		case PROMPT_CONTINUE:
! 		case PROMPT_SINGLEQUOTE:
! 		case PROMPT_DOUBLEQUOTE:
! 		case PROMPT_COMMENT:
! 		case PROMPT_PAREN:
! 			prompt_name = "PROMPT2";
! 			break;
! 		
! 		case PROMPT_COPY:
! 			prompt_name = "PROMPT3";
! 			break;
! 	}
  
+ 	if (prompt_name)
+ 	  prompt_string = GetVariable(pset.vars, prompt_name);
  
  	destination[0] = '\0';
  
***************
*** 92,112 ****
  		{
  			switch (*p)
  			{
- 				case '%':
- 					strcpy(buf, "%");
- 					break;
- 
  					/* Current database */
  				case '/':
  					if (pset.db)
  						strncpy(buf, PQdb(pset.db), MAX_PROMPT_SIZE);
  					break;
  				case '~':
- 					{
- 						const char *var;
- 
  						if (pset.db)
  						{
  							if (strcmp(PQdb(pset.db), PQuser(pset.db)) == 0 ||
  								((var = getenv("PGDATABASE")) && strcmp(var, PQdb(pset.db)) == 0))
  								strcpy(buf, "~");
--- 105,119 ----
  		{
  			switch (*p)
  			{
  					/* Current database */
  				case '/':
  					if (pset.db)
  						strncpy(buf, PQdb(pset.db), MAX_PROMPT_SIZE);
  					break;
  				case '~':
  						if (pset.db)
  						{
+ 						const char *var;
  							if (strcmp(PQdb(pset.db), PQuser(pset.db)) == 0 ||
  								((var = getenv("PGDATABASE")) && strcmp(var, PQdb(pset.db)) == 0))
  								strcpy(buf, "~");
***************
*** 114,120 ****
  								strncpy(buf, PQdb(pset.db), MAX_PROMPT_SIZE);
  						}
  						break;
! 					}
  					/* DB server hostname (long/short) */
  				case 'M':
  				case 'm':
--- 121,127 ----
  								strncpy(buf, PQdb(pset.db), MAX_PROMPT_SIZE);
  						}
  						break;
! 
  					/* DB server hostname (long/short) */
  				case 'M':
  				case 'm':
***************
*** 164,178 ****
  				case '7':
  				case '8':
  				case '9':
! 					{
! 						long int	l;
! 						char	   *end;
! 
! 						l = strtol(p, &end, 0);
! 						sprintf(buf, "%c", (unsigned char) l);
! 						p = end - 1;
  						break;
- 					}
  
  				case 'R':
  					switch (status)
--- 171,178 ----
  				case '7':
  				case '8':
  				case '9':
! 					*buf = parse_char(&p);
  						break;
  
  				case 'R':
  					switch (status)
Index: src/bin/psql/startup.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/psql/startup.c,v
retrieving revision 1.71
diff -c -c -r1.71 startup.c
*** src/bin/psql/startup.c	18 Mar 2003 22:15:44 -0000	1.71
--- src/bin/psql/startup.c	20 Mar 2003 06:42:26 -0000
***************
*** 253,262 ****
  	 */
  	else if (options.action == ACT_SINGLE_SLASH)
  	{
! 		const char *value;
! 
! 		if ((value = GetVariable(pset.vars, "ECHO")) && strcmp(value, "all") == 0)
  			puts(options.action_string);
  		successResult = HandleSlashCmds(options.action_string, NULL, NULL, NULL) != CMD_ERROR
  			? EXIT_SUCCESS : EXIT_FAILURE;
  	}
--- 253,261 ----
  	 */
  	else if (options.action == ACT_SINGLE_SLASH)
  	{
! 		if (VariableEquals(pset.vars, "ECHO", "all"))
  			puts(options.action_string);
+ 
  		successResult = HandleSlashCmds(options.action_string, NULL, NULL, NULL) != CMD_ERROR
  			? EXIT_SUCCESS : EXIT_FAILURE;
  	}
***************
*** 266,275 ****
  	 */
  	else if (options.action == ACT_SINGLE_QUERY)
  	{
! 		const char *value;
! 
! 		if ((value = GetVariable(pset.vars, "ECHO")) && strcmp(value, "all") == 0)
  			puts(options.action_string);
  		successResult = SendQuery(options.action_string)
  			? EXIT_SUCCESS : EXIT_FAILURE;
  	}
--- 265,273 ----
  	 */
  	else if (options.action == ACT_SINGLE_QUERY)
  	{
! 		if (VariableEquals(pset.vars, "ECHO", "all"))
  			puts(options.action_string);
+ 
  		successResult = SendQuery(options.action_string)
  			? EXIT_SUCCESS : EXIT_FAILURE;
  	}
Index: src/bin/psql/variables.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/psql/variables.c,v
retrieving revision 1.9
diff -c -c -r1.9 variables.c
*** src/bin/psql/variables.c	10 Feb 2001 02:31:28 -0000	1.9
--- src/bin/psql/variables.c	20 Mar 2003 06:42:26 -0000
***************
*** 68,73 ****
--- 68,141 ----
  }
  
  
+ bool
+ VariableEquals(VariableSpace space, const char name[], const char value[])
+ {
+ 	const char *var;
+ 	var = GetVariable(space, name);
+ 	return var && (strcmp(var, value) == 0);
+ }
+ 
+ 
+ int 
+ GetVariableNum(VariableSpace space, 
+ 	 				const char name[], 
+ 					int defaultval,
+ 					int faultval,
+ 					bool allowtrail)
+ {
+ 	const char *var;
+ 	int result;
+ 
+ 	var = GetVariable(space, name);
+ 	if (!var)
+ 	  result = defaultval;
+ 	else if (!var[0])
+ 	  result = faultval;
+ 	else
+ 	{
+ 		char *end;
+ 		result = strtol(var, &end, 0);
+ 		if (!allowtrail && *end)
+ 		  result = faultval;
+ 	}
+ 
+ 	return result;
+ }
+ 
+ 
+ int
+ SwitchVariable(VariableSpace space, const char name[], const char *opt, ...)
+ {
+ 	int result;
+ 	const char *var;
+ 
+ 	var = GetVariable(space, name);
+ 	if (var) 
+ 	{
+ 		va_list args;
+ 		va_start(args, opt);
+ 		for (result=1; opt && (strcmp(var, opt) != 0); result++)
+ 			opt = va_arg(args,const char *);
+ 
+ 		if (!opt) result = var_notfound;
+ 		va_end(args);
+ 	}
+ 	else
+ 	  result = var_notset;
+ 
+ 	return result;
+ }
+ 
+ 
+ void 
+ PrintVariables(VariableSpace space)
+ {
+   struct _variable *ptr;
+   for (ptr = space->next; ptr; ptr = ptr->next)
+ 	 printf("%s = '%s'\n", ptr->name, ptr->value);
+ }
+ 
  
  bool
  SetVariable(VariableSpace space, const char *name, const char *value)
Index: src/bin/psql/variables.h
===================================================================
RCS file: /cvsroot/pgsql-server/src/bin/psql/variables.h,v
retrieving revision 1.10
diff -c -c -r1.10 variables.h
*** src/bin/psql/variables.h	5 Nov 2001 17:46:31 -0000	1.10
--- src/bin/psql/variables.h	20 Mar 2003 06:42:26 -0000
***************
*** 30,39 ****
  
  VariableSpace CreateVariableSpace(void);
  const char *GetVariable(VariableSpace space, const char *name);
! bool		GetVariableBool(VariableSpace space, const char *name);
! bool		SetVariable(VariableSpace space, const char *name, const char *value);
! bool		SetVariableBool(VariableSpace space, const char *name);
! bool		DeleteVariable(VariableSpace space, const char *name);
! void		DestroyVariableSpace(VariableSpace space);
  
  #endif   /* VARIABLES_H */
--- 30,62 ----
  
  VariableSpace CreateVariableSpace(void);
  const char *GetVariable(VariableSpace space, const char *name);
! bool	GetVariableBool(VariableSpace space, const char *name);
! bool	VariableEquals(VariableSpace space, const char name[], const char *opt);
! 
! /* Read numeric variable, or defaultval if it is not set, or faultval if its
!  * value is not a valid numeric string.  If allowtrail is false, this will 
!  * include the case where there are trailing characters after the number.
!  */
! int GetVariableNum(VariableSpace space, 
! 	 					const char name[], 
! 						int defaultval, 
! 						int faultval,
! 						bool allowtrail);
! 
! 
! /* Find value of variable <name> among NULL-terminated list of alternative 
!  * options.  Returns var_notset if the variable was not set, var_notfound if its
!  * value did not occur in the list of options, or the number of the matching
!  * option.  The first option is 1, the second is 2 and so on.
!  */
! enum { var_notset = 0, var_notfound = -1 };
! int 	SwitchVariable(VariableSpace space, const char name[], const char *opt,...);
! 
! void 	PrintVariables(VariableSpace space);
! 
! bool	SetVariable(VariableSpace space, const char *name, const char *value);
! bool	SetVariableBool(VariableSpace space, const char *name);
! bool	DeleteVariable(VariableSpace space, const char *name);
! void	DestroyVariableSpace(VariableSpace space);
  
  #endif   /* VARIABLES_H */
