aboutsummaryrefslogtreecommitdiff
path: root/src/bin/psql/mainloop.c
diff options
context:
space:
mode:
authorBruce Momjian <bruce@momjian.us>2003-03-20 06:43:35 +0000
committerBruce Momjian <bruce@momjian.us>2003-03-20 06:43:35 +0000
commitadd932ee91b9ca78c1a0647487cd6d2a680c4f12 (patch)
treeabb208bec97099a408ead6d6c5b0f0929c459a2d /src/bin/psql/mainloop.c
parent1b3d4cefe8e025a40e3a795f311d4711178366e9 (diff)
downloadpostgresql-add932ee91b9ca78c1a0647487cd6d2a680c4f12.tar.gz
postgresql-add932ee91b9ca78c1a0647487cd6d2a680c4f12.zip
I'm continuing to work on cleaning up code in psql. As things appear
now, my changes seem to work. Some possible minor bugs got squished on the way but I can't be sure without more feedback from people who really put the code to the test. The new patch mostly simplifies variable handling and reduces code duplication. Changes in the command parser eliminate some redundant variables (boolean state + depth counter), replaces some "else if" constructs with switches, and so on. It is meant to be applied together with my previous patch, although I hope they don't conflict; I went back to the CVS version for this one. One more thing I thought should perhaps be changed: an IGNOREEOF value of n will ignore only n-1 EOFs. I didn't want to touch this for fear of breaking existing applications, but it does seem a tad illogical. Jeroen T. Vermeulen
Diffstat (limited to 'src/bin/psql/mainloop.c')
-rw-r--r--src/bin/psql/mainloop.c146
1 files changed, 45 insertions, 101 deletions
diff --git a/src/bin/psql/mainloop.c b/src/bin/psql/mainloop.c
index e9ed1a621e5..27b5a560d5f 100644
--- a/src/bin/psql/mainloop.c
+++ b/src/bin/psql/mainloop.c
@@ -3,7 +3,7 @@
*
* Copyright 2000 by PostgreSQL Global Development Group
*
- * $Header: /cvsroot/pgsql/src/bin/psql/mainloop.c,v 1.52 2003/03/20 06:00:12 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/mainloop.c,v 1.53 2003/03/20 06:43:35 momjian Exp $
*/
#include "postgres_fe.h"
#include "mainloop.h"
@@ -40,16 +40,14 @@ MainLoop(FILE *source)
char *line; /* current line of input */
int len; /* length of the line */
volatile int successResult = EXIT_SUCCESS;
- volatile backslashResult slashCmdStatus;
+ volatile backslashResult slashCmdStatus = CMD_UNKNOWN;
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;
+ 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;
- const char *var;
volatile unsigned int bslash_count = 0;
int i,
@@ -81,16 +79,12 @@ MainLoop(FILE *source)
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)
+ while (successResult == EXIT_SUCCESS)
{
/*
* Welcome code for Control-C
@@ -109,6 +103,7 @@ MainLoop(FILE *source)
}
cancel_pressed = false;
+ fflush(stdout);
}
#ifndef WIN32
@@ -118,15 +113,16 @@ MainLoop(FILE *source)
if (pset.cur_cmd_interactive)
{
- fputc('\n', stdout);
+ putc('\n', stdout);
resetPQExpBuffer(query_buf);
/* reset parsing state */
- in_xcomment = false;
+ in_xcomment = 0;
in_quote = 0;
paren_level = 0;
count_eof = 0;
slashCmdStatus = CMD_UNKNOWN;
+ fflush(stdout);
}
else
{
@@ -151,23 +147,21 @@ MainLoop(FILE *source)
line = xstrdup(query_buf->data);
resetPQExpBuffer(query_buf);
/* reset parsing state since we are rescanning whole line */
- in_xcomment = false;
+ in_xcomment = 0;
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)
+ 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,7 +179,6 @@ MainLoop(FILE *source)
}
else
line = gets_fromFile(source);
- }
/* Setting this will not have effect until next line. */
@@ -203,50 +196,21 @@ MainLoop(FILE *source)
{
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 */
- }
+ count_eof++;
- if (getout)
- {
- if (QUIET())
- putc('\n', stdout);
- else
- puts("\\q");
- break;
- }
- else
+ 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");
}
- else
-/* not interactive */
break;
}
- else
+
count_eof = 0;
pset.lineno++;
@@ -259,8 +223,7 @@ MainLoop(FILE *source)
}
/* echo back if flag is set */
- var = GetVariable(pset.vars, "ECHO");
- if (!pset.cur_cmd_interactive && var && strcmp(var, "all") == 0)
+ if (!pset.cur_cmd_interactive && VariableEquals(pset.vars, "ECHO", "all"))
puts(line);
fflush(stdout);
@@ -276,14 +239,13 @@ MainLoop(FILE *source)
#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)
+ 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? */
- bool was_bslash = (i > 0 && line[i - prevlen] == '\\');
-
- if (was_bslash)
+ if (i > 0 && line[i - prevlen] == '\\')
bslash_count++;
else
bslash_count = 0;
@@ -308,30 +270,24 @@ MainLoop(FILE *source)
in_quote = 0;
}
- /* in extended comment? */
- else if (in_xcomment)
- {
- if (line[i] == '*' && line[i + thislen] == '/')
- {
- if (xcdepth > 0)
- xcdepth--;
- else
+ /* start of extended comment? */
+ else if (line[i] == '/' && line[i + thislen] == '*')
{
- in_xcomment = false;
+ in_xcomment++;
+ if (in_xcomment == 1)
ADVANCE_1;
}
- }
- else if (line[i] == '/' && line[i + thislen] == '*')
- xcdepth++;
- }
- /* start of extended comment? */
- else if (line[i] == '/' && line[i + thislen] == '*')
+ /* end of extended comment? */
+ else if (line[i] == '*' && line[i + thislen] == '/')
{
- xcdepth = 0;
- in_xcomment = true;
+ in_xcomment--;
+ if (in_xcomment <= 0)
+ {
+ in_xcomment = 0;
ADVANCE_1;
}
+ }
/* start of quote? */
else if (line[i] == '\'' || line[i] == '"')
@@ -353,7 +309,7 @@ MainLoop(FILE *source)
/* colon -> substitute variable */
/* we need to be on the watch for the '::' operator */
- else if (line[i] == ':' && !was_bslash
+ else if (line[i] == ':' && !bslash_count
&& strspn(line + i + thislen, VALID_VARIABLE_CHARS) > 0
&& !(prevlen > 0 && line[i - prevlen] == ':')
)
@@ -411,7 +367,7 @@ MainLoop(FILE *source)
}
/* semicolon? then send query */
- else if (line[i] == ';' && !was_bslash && !paren_level)
+ else if (line[i] == ';' && !bslash_count && !paren_level)
{
line[i] = '\0';
/* is there anything else on the line? */
@@ -442,7 +398,7 @@ MainLoop(FILE *source)
* if you have a burning need to send a semicolon or colon to
* the backend ...
*/
- else if (was_bslash && (line[i] == ';' || line[i] == ':'))
+ else if (bslash_count && (line[i] == ';' || line[i] == ':'))
{
/* remove the backslash */
memmove(line + i - prevlen, line + i, len - i + 1);
@@ -451,7 +407,7 @@ MainLoop(FILE *source)
}
/* backslash command */
- else if (was_bslash)
+ else if (bslash_count)
{
const char *end_of_cmd = NULL;
@@ -499,15 +455,9 @@ MainLoop(FILE *source)
paren_level = 0;
/* process anything left after the backslash command */
- i += end_of_cmd - &line[i];
+ i = end_of_cmd - line;
query_start = i;
}
-
-
- /* stop the script after error */
- if (!success && die_on_error)
- break;
-
} /* for (line) */
@@ -533,25 +483,19 @@ MainLoop(FILE *source)
if (query_buf->data[0] != '\0' && GetVariableBool(pset.vars, "SINGLELINE"))
{
success = SendQuery(query_buf->data);
- slashCmdStatus = success ? CMD_SEND : CMD_ERROR;
+ 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)
+ if (!pset.cur_cmd_interactive)
{
+ if (!success && die_on_error)
successResult = EXIT_USER;
- break;
- }
-
-
/* Have we lost the db connection? */
- if (pset.db == NULL && !pset.cur_cmd_interactive)
- {
+ else if (!pset.db)
successResult = EXIT_BADCONN;
- break;
}
} /* while !endoffile/session */