From add932ee91b9ca78c1a0647487cd6d2a680c4f12 Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Thu, 20 Mar 2003 06:43:35 +0000 Subject: [PATCH] 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 --- src/bin/psql/command.c | 26 ++----- src/bin/psql/common.c | 39 ++++++----- src/bin/psql/common.h | 8 ++- src/bin/psql/input.c | 10 +-- src/bin/psql/large_obj.c | 36 +++++----- src/bin/psql/mainloop.c | 146 ++++++++++++--------------------------- src/bin/psql/prompt.c | 52 +++++++------- src/bin/psql/startup.c | 12 ++-- src/bin/psql/variables.c | 70 ++++++++++++++++++- src/bin/psql/variables.h | 35 ++++++++-- 10 files changed, 233 insertions(+), 201 deletions(-) diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index 9f393024b6..57aaad0655 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -3,7 +3,7 @@ * * Copyright 2000-2002 by PostgreSQL Global Development Group * - * $Header: /cvsroot/pgsql/src/bin/psql/command.c,v 1.93 2003/03/19 22:49:43 momjian Exp $ + * $Header: /cvsroot/pgsql/src/bin/psql/command.c,v 1.94 2003/03/20 06:43:35 momjian Exp $ */ #include "postgres_fe.h" #include "command.h" @@ -669,15 +669,7 @@ exec_command(const char *cmd, 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); + PrintVariables(pset.vars); success = true; } else @@ -1073,9 +1065,7 @@ scan_option(char **string, enum option_type type, char *quote, bool semicolon) 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); + 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,15 +1277,9 @@ unescape(const unsigned char *source, size_t len) case '7': case '8': case '9': - { - long int l; - char *end; - - l = strtol(p, &end, 0); - c = (char) l; - p = end - 1; + c = parse_char((char **)&p); break; - } + default: c = *p; } diff --git a/src/bin/psql/common.c b/src/bin/psql/common.c index f3f7e80997..48405f9149 100644 --- a/src/bin/psql/common.c +++ b/src/bin/psql/common.c @@ -3,7 +3,7 @@ * * Copyright 2000 by PostgreSQL Global Development Group * - * $Header: /cvsroot/pgsql/src/bin/psql/common.c,v 1.59 2003/03/20 06:00:12 momjian Exp $ + * $Header: /cvsroot/pgsql/src/bin/psql/common.c,v 1.60 2003/03/20 06:43:35 momjian Exp $ */ #include "postgres_fe.h" #include "common.h" @@ -368,7 +368,7 @@ PSQLexec(const char *query, bool ignore_command_ok) { PGresult *res = NULL; PGresult *newres; - const char *var; + int echo_hidden; ExecStatusType rstatus; if (!pset.db) @@ -377,17 +377,17 @@ PSQLexec(const char *query, bool ignore_command_ok) return NULL; } - var = GetVariable(pset.vars, "ECHO_HIDDEN"); - if (var) + 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 (var && strcmp(var, "noexec") == 0) + if (echo_hidden == 1) return NULL; + } /* discard any uneaten results of past queries */ while ((newres = PQgetResult(pset.db)) != NULL) @@ -579,13 +579,13 @@ SendQuery(const char *query) 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,14 +596,9 @@ SendQuery(const char *query) 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); } + else if (VariableEquals(pset.vars, "ECHO", "queries")) + puts(query); SetCancelConn(); @@ -619,3 +614,15 @@ SendQuery(const char *query) PrintNotifications(); return OK; } + + +char parse_char(char **buf) +{ + long l; + + l = strtol(*buf, buf, 0); + (*buf)--; + return (char)l; +} + + diff --git a/src/bin/psql/common.h b/src/bin/psql/common.h index b15cdc6c79..2296e62193 100644 --- a/src/bin/psql/common.h +++ b/src/bin/psql/common.h @@ -3,7 +3,7 @@ * * Copyright 2000 by PostgreSQL Global Development Group * - * $Header: /cvsroot/pgsql/src/bin/psql/common.h,v 1.23 2003/03/20 06:00:12 momjian Exp $ + * $Header: /cvsroot/pgsql/src/bin/psql/common.h,v 1.24 2003/03/20 06:43:35 momjian Exp $ */ #ifndef COMMON_H #define COMMON_H @@ -42,6 +42,12 @@ extern bool SendQuery(const char *query); /* 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) diff --git a/src/bin/psql/input.c b/src/bin/psql/input.c index 24f6a9b40b..f592546fd5 100644 --- a/src/bin/psql/input.c +++ b/src/bin/psql/input.c @@ -3,7 +3,7 @@ * * Copyright 2000 by PostgreSQL Global Development Group * - * $Header: /cvsroot/pgsql/src/bin/psql/input.c,v 1.22 2003/03/20 06:00:12 momjian Exp $ + * $Header: /cvsroot/pgsql/src/bin/psql/input.c,v 1.23 2003/03/20 06:43:35 momjian Exp $ */ #include "postgres_fe.h" #include "input.h" @@ -233,10 +233,12 @@ finishInput(int exitstatus, void *arg) strlen(PSQLHISTORY) + 1); if (psql_history) { - const char *var = GetVariable(pset.vars, "HISTSIZE"); + int hist_size; + hist_size = GetVariableNum(pset.vars,"HISTSIZE",-1,-1,true); + + if (hist_size >= 0) + stifle_history(hist_size); - if (var) - stifle_history(atoi(var)); sprintf(psql_history, "%s/%s", home, PSQLHISTORY); write_history(psql_history); free(psql_history); diff --git a/src/bin/psql/large_obj.c b/src/bin/psql/large_obj.c index fbe8a32a18..f76f8dea5b 100644 --- a/src/bin/psql/large_obj.c +++ b/src/bin/psql/large_obj.c @@ -3,7 +3,7 @@ * * Copyright 2000-2002 by PostgreSQL Global Development Group * - * $Header: /cvsroot/pgsql/src/bin/psql/large_obj.c,v 1.23 2002/10/15 02:24:16 tgl Exp $ + * $Header: /cvsroot/pgsql/src/bin/psql/large_obj.c,v 1.24 2003/03/20 06:43:35 momjian Exp $ */ #include "postgres_fe.h" #include "large_obj.h" @@ -40,15 +40,20 @@ _my_notice_handler(void *arg, const char *message) static bool handle_transaction(void) { - const char *var = GetVariable(pset.vars, "LO_TRANSACTION"); PGresult *res; - bool commit; + bool commit = false; PQnoticeProcessor old_notice_hook; - if (var && strcmp(var, "nothing") == 0) + switch (SwitchVariable(pset.vars, "LO_TRANSACTION", + "nothing", + "commit", + NULL)) + { + case 1: return true; - - commit = (var && strcmp(var, "commit") == 0); + case 2: + commit = true; + } notice[0] = '\0'; old_notice_hook = PQsetNoticeProcessor(pset.db, _my_notice_handler, NULL); @@ -87,11 +92,9 @@ do_lo_export(const char *loid_arg, const char *filename_arg) { PGresult *res; int status; - bool own_transaction = true; - const char *var = GetVariable(pset.vars, "LO_TRANSACTION"); + bool own_transaction; - if (var && strcmp(var, "nothing") == 0) - own_transaction = false; + own_transaction = VariableEquals(pset.vars, "LO_TRANSACTION", "nothing"); if (!pset.db) { @@ -154,11 +157,9 @@ do_lo_import(const char *filename_arg, const char *comment_arg) Oid loid; char oidbuf[32]; unsigned int i; - bool own_transaction = true; - const char *var = GetVariable(pset.vars, "LO_TRANSACTION"); + bool own_transaction; - if (var && strcmp(var, "nothing") == 0) - own_transaction = false; + own_transaction = VariableEquals(pset.vars, "LO_TRANSACTION", "nothing"); if (!pset.db) { @@ -271,11 +272,10 @@ do_lo_unlink(const char *loid_arg) 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; + bool own_transaction; + + own_transaction = VariableEquals(pset.vars, "LO_TRANSACTION", "nothing"); if (!pset.db) { diff --git a/src/bin/psql/mainloop.c b/src/bin/psql/mainloop.c index e9ed1a621e..27b5a560d5 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 */ diff --git a/src/bin/psql/prompt.c b/src/bin/psql/prompt.c index f01a55b569..194c6ef0f6 100644 --- a/src/bin/psql/prompt.c +++ b/src/bin/psql/prompt.c @@ -3,7 +3,7 @@ * * Copyright 2000 by PostgreSQL Global Development Group * - * $Header: /cvsroot/pgsql/src/bin/psql/prompt.c,v 1.22 2001/10/25 05:49:54 momjian Exp $ + * $Header: /cvsroot/pgsql/src/bin/psql/prompt.c,v 1.23 2003/03/20 06:43:35 momjian Exp $ */ #include "postgres_fe.h" #include "prompt.h" @@ -69,17 +69,30 @@ get_prompt(promptStatus_t status) char buf[MAX_PROMPT_SIZE + 1]; bool esc = false; const char *p; - const char *prompt_string; + const char *prompt_string = "? "; + const char *prompt_name = NULL; - 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 = "? "; + 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,21 +105,15 @@ get_prompt(promptStatus_t status) { 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) { + const char *var; if (strcmp(PQdb(pset.db), PQuser(pset.db)) == 0 || ((var = getenv("PGDATABASE")) && strcmp(var, PQdb(pset.db)) == 0)) strcpy(buf, "~"); @@ -114,7 +121,7 @@ get_prompt(promptStatus_t status) strncpy(buf, PQdb(pset.db), MAX_PROMPT_SIZE); } break; - } + /* DB server hostname (long/short) */ case 'M': case 'm': @@ -164,15 +171,8 @@ get_prompt(promptStatus_t status) 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; + *buf = parse_char(&p); break; - } case 'R': switch (status) diff --git a/src/bin/psql/startup.c b/src/bin/psql/startup.c index 39c22dfc69..47e17e3535 100644 --- a/src/bin/psql/startup.c +++ b/src/bin/psql/startup.c @@ -3,7 +3,7 @@ * * Copyright 2000 by PostgreSQL Global Development Group * - * $Header: /cvsroot/pgsql/src/bin/psql/startup.c,v 1.71 2003/03/18 22:15:44 petere Exp $ + * $Header: /cvsroot/pgsql/src/bin/psql/startup.c,v 1.72 2003/03/20 06:43:35 momjian Exp $ */ #include "postgres_fe.h" @@ -253,10 +253,9 @@ main(int argc, char *argv[]) */ else if (options.action == ACT_SINGLE_SLASH) { - const char *value; - - if ((value = GetVariable(pset.vars, "ECHO")) && strcmp(value, "all") == 0) + 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,10 +265,9 @@ main(int argc, char *argv[]) */ else if (options.action == ACT_SINGLE_QUERY) { - const char *value; - - if ((value = GetVariable(pset.vars, "ECHO")) && strcmp(value, "all") == 0) + if (VariableEquals(pset.vars, "ECHO", "all")) puts(options.action_string); + successResult = SendQuery(options.action_string) ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/src/bin/psql/variables.c b/src/bin/psql/variables.c index b65ce38bd6..35f84aefdc 100644 --- a/src/bin/psql/variables.c +++ b/src/bin/psql/variables.c @@ -3,7 +3,7 @@ * * Copyright 2000 by PostgreSQL Global Development Group * - * $Header: /cvsroot/pgsql/src/bin/psql/variables.c,v 1.9 2001/02/10 02:31:28 tgl Exp $ + * $Header: /cvsroot/pgsql/src/bin/psql/variables.c,v 1.10 2003/03/20 06:43:35 momjian Exp $ */ #include "postgres_fe.h" #include "variables.h" @@ -68,6 +68,74 @@ GetVariableBool(VariableSpace space, const char *name) } +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) diff --git a/src/bin/psql/variables.h b/src/bin/psql/variables.h index a3e79b7621..d297b5a4ef 100644 --- a/src/bin/psql/variables.h +++ b/src/bin/psql/variables.h @@ -3,7 +3,7 @@ * * Copyright 2000 by PostgreSQL Global Development Group * - * $Header: /cvsroot/pgsql/src/bin/psql/variables.h,v 1.10 2001/11/05 17:46:31 momjian Exp $ + * $Header: /cvsroot/pgsql/src/bin/psql/variables.h,v 1.11 2003/03/20 06:43:35 momjian Exp $ */ /* @@ -30,10 +30,33 @@ typedef struct _variable *VariableSpace; 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); +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 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 */ -- 2.40.0