diff options
Diffstat (limited to 'src/bin/psql/mainloop.c')
-rw-r--r-- | src/bin/psql/mainloop.c | 414 |
1 files changed, 216 insertions, 198 deletions
diff --git a/src/bin/psql/mainloop.c b/src/bin/psql/mainloop.c index b27d344a781..a6f9d90c842 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.27 2000/03/27 21:11:37 petere Exp $ + * $Header: /cvsroot/pgsql/src/bin/psql/mainloop.c,v 1.28 2000/04/12 17:16:22 momjian Exp $ */ #include "postgres.h" #include "mainloop.h" @@ -19,7 +19,8 @@ #ifndef WIN32 #include <setjmp.h> -sigjmp_buf main_loop_jmp; +sigjmp_buf main_loop_jmp; + #endif @@ -36,8 +37,8 @@ int MainLoop(FILE *source) { PQExpBuffer query_buf; /* buffer for query being accumulated */ - PQExpBuffer previous_buf; /* if there isn't anything in the new buffer - yet, use this one for \e, etc. */ + PQExpBuffer previous_buf; /* if there isn't anything in the new + * buffer yet, use this one for \e, etc. */ char *line; /* current line of input */ int len; /* length of the line */ volatile int successResult = EXIT_SUCCESS; @@ -48,9 +49,9 @@ MainLoop(FILE *source) volatile bool xcomment; /* in extended comment */ volatile int paren_level; unsigned int query_start; - volatile int count_eof = 0; - const char *var; - volatile unsigned int bslash_count = 0; + volatile int count_eof = 0; + const char *var; + volatile unsigned int bslash_count = 0; int i, prevlen, @@ -60,7 +61,7 @@ MainLoop(FILE *source) FILE *prev_cmd_source; bool prev_cmd_interactive; - unsigned int prev_lineno; + unsigned int prev_lineno; volatile bool die_on_error = false; @@ -74,10 +75,10 @@ MainLoop(FILE *source) query_buf = createPQExpBuffer(); - previous_buf = createPQExpBuffer(); + previous_buf = createPQExpBuffer(); if (!query_buf || !previous_buf) { - psql_error("out of memory\n"); + psql_error("out of memory\n"); exit(EXIT_FAILURE); } @@ -85,59 +86,62 @@ MainLoop(FILE *source) in_quote = 0; paren_level = 0; slashCmdStatus = CMD_UNKNOWN; /* set default */ - prev_lineno = pset.lineno; - pset.lineno = 0; + prev_lineno = pset.lineno; + pset.lineno = 0; /* main loop to get queries and execute them */ while (1) { #ifndef WIN32 - /* - * Welcome code for Control-C - */ - if (cancel_pressed) - { - if (!pset.cur_cmd_interactive) - { - /* - * You get here if you stopped a script with Ctrl-C and a query - * cancel was issued. In that case we don't do the longjmp, so - * the query routine can finish nicely. - */ - successResult = EXIT_USER; - break; - } - - cancel_pressed = false; - } - - if (sigsetjmp(main_loop_jmp, 1) != 0) - { - /* got here with longjmp */ - - if (pset.cur_cmd_interactive) - { - fputc('\n', stdout); - resetPQExpBuffer(query_buf); - - /* reset parsing state */ - xcomment = false; - in_quote = 0; - paren_level = 0; - count_eof = 0; - slashCmdStatus = CMD_UNKNOWN; - } - else - { - successResult = EXIT_USER; - break; - } - } -#endif /* not WIN32 */ + + /* + * Welcome code for Control-C + */ + if (cancel_pressed) + { + if (!pset.cur_cmd_interactive) + { + + /* + * You get here if you stopped a script with Ctrl-C and a + * query cancel was issued. In that case we don't do the + * longjmp, so the query routine can finish nicely. + */ + successResult = EXIT_USER; + break; + } + + cancel_pressed = false; + } + + if (sigsetjmp(main_loop_jmp, 1) != 0) + { + /* got here with longjmp */ + + if (pset.cur_cmd_interactive) + { + fputc('\n', stdout); + resetPQExpBuffer(query_buf); + + /* reset parsing state */ + xcomment = false; + in_quote = 0; + paren_level = 0; + count_eof = 0; + slashCmdStatus = CMD_UNKNOWN; + } + else + { + successResult = EXIT_USER; + break; + } + } +#endif /* not WIN32 */ if (slashCmdStatus == CMD_NEWEDIT) { + /* * just returned from editing the line? then just copy to the * input buffer @@ -148,11 +152,12 @@ MainLoop(FILE *source) xcomment = false; in_quote = 0; paren_level = 0; - slashCmdStatus = CMD_UNKNOWN; + slashCmdStatus = CMD_UNKNOWN; } else { - fflush(stdout); + fflush(stdout); + /* * otherwise, set interactive prompt if necessary and get * another line @@ -167,8 +172,8 @@ MainLoop(FILE *source) prompt_status = PROMPT_DOUBLEQUOTE; else if (xcomment) prompt_status = PROMPT_COMMENT; - else if (paren_level) - prompt_status = PROMPT_PAREN; + else if (paren_level) + prompt_status = PROMPT_PAREN; else if (query_buf->len > 0) prompt_status = PROMPT_CONTINUE; else @@ -195,51 +200,54 @@ MainLoop(FILE *source) if (line == NULL) { 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("Use \"\\q\" to leave %s.\n", pset.progname); - continue; - } - } - else /* not interactive */ - break; + { + 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("Use \"\\q\" to leave %s.\n", pset.progname); + continue; + } + } + else +/* not interactive */ + break; } - else - count_eof = 0; + else + count_eof = 0; - pset.lineno++; + pset.lineno++; /* strip trailing backslashes, they don't have a clear meaning */ while (1) @@ -260,10 +268,10 @@ MainLoop(FILE *source) } /* 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); + var = GetVariable(pset.vars, "ECHO"); + if (!pset.cur_cmd_interactive && var && strcmp(var, "all") == 0) + puts(line); + fflush(stdout); len = strlen(line); query_start = 0; @@ -278,15 +286,16 @@ MainLoop(FILE *source) success = true; for (i = 0, prevlen = 0, thislen = (len > 0) ? PQmblen(line, pset.encoding) : 0; - i < len; - ADVANCE_1) + 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; + bool was_bslash = (i > 0 && line[i - prevlen] == '\\'); + + if (was_bslash) + bslash_count++; + else + bslash_count = 0; /* in quote? */ if (in_quote) @@ -331,53 +340,57 @@ MainLoop(FILE *source) else if (line[i] == ')' && paren_level > 0) paren_level--; - /* 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] == ':') - ) - { + /* 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] == ':') + ) + { size_t in_length, out_length; const char *value; char *new; - char after; /* the character after the variable name - will be temporarily overwritten */ + char after; /* the character after the + * variable name will be + * temporarily overwritten */ in_length = strspn(&line[i + thislen], VALID_VARIABLE_CHARS); after = line[i + thislen + in_length]; line[i + thislen + in_length] = '\0'; - /* if the variable doesn't exist we'll leave the string as is */ + /* + * if the variable doesn't exist we'll leave the string as + * is + */ value = GetVariable(pset.vars, &line[i + thislen]); - if (value) - { - out_length = strlen(value); - - new = malloc(len + out_length - (1 + in_length) + 1); - if (!new) - { - psql_error("out of memory\n"); - exit(EXIT_FAILURE); - } - - sprintf(new, "%.*s%s%c", i, line, value, after); - if (after) - strcat(new, line + i + 1 + in_length + 1); - - free(line); - line = new; - len = strlen(new); - continue; /* reparse the just substituted */ - } - else - { - /* restore overwritten character */ - line[i + thislen + in_length] = after; - /* move on ... */ - } - } + if (value) + { + out_length = strlen(value); + + new = malloc(len + out_length - (1 + in_length) + 1); + if (!new) + { + psql_error("out of memory\n"); + exit(EXIT_FAILURE); + } + + sprintf(new, "%.*s%s%c", i, line, value, after); + if (after) + strcat(new, line + i + 1 + in_length + 1); + + free(line); + line = new; + len = strlen(new); + continue; /* reparse the just substituted */ + } + else + { + /* restore overwritten character */ + line[i + thislen + in_length] = after; + /* move on ... */ + } + } /* semicolon? then send query */ else if (line[i] == ';' && !was_bslash && !paren_level) @@ -386,6 +399,7 @@ MainLoop(FILE *source) /* is there anything else on the line? */ if (line[query_start + strspn(line + query_start, " \t")] != '\0') { + /* * insert a cosmetic newline, if this is not the first * line in the buffer @@ -394,27 +408,29 @@ MainLoop(FILE *source) appendPQExpBufferChar(query_buf, '\n'); /* append the line to the query buffer */ appendPQExpBufferStr(query_buf, line + query_start); - appendPQExpBufferChar(query_buf, ';'); + appendPQExpBufferChar(query_buf, ';'); } /* execute query */ 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); + resetPQExpBuffer(previous_buf); + appendPQExpBufferStr(previous_buf, query_buf->data); + resetPQExpBuffer(query_buf); query_start = i + thislen; } - /* 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); - len--; - } + /* + * 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); + len--; + } /* backslash command */ else if (was_bslash) @@ -427,6 +443,7 @@ MainLoop(FILE *source) /* is there anything else on the line for the command? */ if (line[query_start + strspn(line + query_start, " \t")] != '\0') { + /* * insert a cosmetic newline, if this is not the first * line in the buffer @@ -437,40 +454,41 @@ MainLoop(FILE *source) appendPQExpBufferStr(query_buf, line + query_start); } - /* handle backslash command */ - slashCmdStatus = HandleSlashCmds(&line[i], - query_buf->len>0 ? query_buf : previous_buf, - &end_of_cmd); + /* handle backslash command */ + slashCmdStatus = HandleSlashCmds(&line[i], + query_buf->len > 0 ? query_buf : previous_buf, + &end_of_cmd); success = slashCmdStatus != CMD_ERROR; - if ((slashCmdStatus == CMD_SEND || slashCmdStatus == CMD_NEWEDIT) && - query_buf->len == 0) { - /* copy previous buffer to current for for handling */ - appendPQExpBufferStr(query_buf, previous_buf->data); - } + if ((slashCmdStatus == CMD_SEND || slashCmdStatus == CMD_NEWEDIT) && + query_buf->len == 0) + { + /* copy previous buffer to current for for handling */ + appendPQExpBufferStr(query_buf, previous_buf->data); + } if (slashCmdStatus == CMD_SEND) { success = SendQuery(query_buf->data); query_start = i + thislen; - resetPQExpBuffer(previous_buf); - appendPQExpBufferStr(previous_buf, query_buf->data); - resetPQExpBuffer(query_buf); + resetPQExpBuffer(previous_buf); + appendPQExpBufferStr(previous_buf, query_buf->data); + resetPQExpBuffer(query_buf); } /* process anything left after the backslash command */ - i += end_of_cmd - &line[i]; - query_start = i; + i += end_of_cmd - &line[i]; + query_start = i; } - /* stop the script after error */ + /* stop the script after error */ if (!success && die_on_error) break; - } /* for (line) */ + } /* for (line) */ if (slashCmdStatus == CMD_TERMINATE) @@ -495,10 +513,10 @@ MainLoop(FILE *source) 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); + slashCmdStatus = success ? CMD_SEND : CMD_ERROR; + resetPQExpBuffer(previous_buf); + appendPQExpBufferStr(previous_buf, query_buf->data); + resetPQExpBuffer(query_buf); } @@ -515,27 +533,27 @@ MainLoop(FILE *source) successResult = EXIT_BADCONN; break; } - } /* while !endoffile/session */ - - /* - * Process query at the end of file without a semicolon - */ - if (query_buf->len > 0 && !pset.cur_cmd_interactive) - { - success = SendQuery(query_buf->data); - - if (!success && die_on_error) - successResult = EXIT_USER; - else if (pset.db == NULL) - successResult = EXIT_BADCONN; - } - + } /* while !endoffile/session */ + + /* + * Process query at the end of file without a semicolon + */ + if (query_buf->len > 0 && !pset.cur_cmd_interactive) + { + success = SendQuery(query_buf->data); + + if (!success && die_on_error) + successResult = EXIT_USER; + else if (pset.db == NULL) + successResult = EXIT_BADCONN; + } + destroyPQExpBuffer(query_buf); destroyPQExpBuffer(previous_buf); pset.cur_cmd_source = prev_cmd_source; pset.cur_cmd_interactive = prev_cmd_interactive; - pset.lineno = prev_lineno; + pset.lineno = prev_lineno; return successResult; } /* MainLoop() */ |