Attached is my first work at implementing GUC enums. It's not done yet,
obviously, but I did hit a problem that I need to ask about. So I'll just
send what I have now for comments.

The patch only converts a couple of the potential enum variables to the new
type, mainly as a proof of concept. But already I hit the problem twice -
the variable that holds the value of the guc enum is a C enum itself, which
gives a compiler warning when I pass a pointer to it for
config_enum.variable. (in this case, Log_error_verbosity and log_statement
are enums and have the problem, but client_min_messages, log_min_messages
and log_min_error_statement are already int and don't have it)

On my platform (linux x86) it works fine when I just cast this to (int *),
but I'm unsure if that's going to be safe on other platforms. I had some
indication that it's probably not?

And if not, the only way I know to do it is to change the C level enums to
be an int and use #define:s instead of what's there now. If that's
required, is that an acceptable change in order to implement this? If not,
any better ideas on how to do it?

And finally, please let me know if I seem to be off on a completely wrong
track with this :-)

//Magnus
Index: src/backend/catalog/system_views.sql
===================================================================
RCS file: /cvsroot/pgsql/src/backend/catalog/system_views.sql,v
retrieving revision 1.48
diff -c -r1.48 system_views.sql
*** src/backend/catalog/system_views.sql        1 Jan 2008 19:45:48 -0000       
1.48
--- src/backend/catalog/system_views.sql        3 Mar 2008 20:20:28 -0000
***************
*** 173,179 ****
      SELECT * 
      FROM pg_show_all_settings() AS A 
      (name text, setting text, unit text, category text, short_desc text, 
extra_desc text,
!      context text, vartype text, source text, min_val text, max_val text);
  
  CREATE RULE pg_settings_u AS 
      ON UPDATE TO pg_settings 
--- 173,179 ----
      SELECT * 
      FROM pg_show_all_settings() AS A 
      (name text, setting text, unit text, category text, short_desc text, 
extra_desc text,
!      context text, vartype text, source text, min_val text, max_val text, 
enumvals text);
  
  CREATE RULE pg_settings_u AS 
      ON UPDATE TO pg_settings 
Index: src/backend/utils/misc/guc.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v
retrieving revision 1.432
diff -c -r1.432 guc.c
*** src/backend/utils/misc/guc.c        30 Jan 2008 18:35:55 -0000      1.432
--- src/backend/utils/misc/guc.c        3 Mar 2008 20:20:29 -0000
***************
*** 144,161 ****
                                                   GucSource source);
  static const char *assign_session_replication_role(const char *newval, bool 
doit,
                                                                GucSource 
source);
- static const char *assign_log_min_messages(const char *newval, bool doit,
-                                               GucSource source);
- static const char *assign_client_min_messages(const char *newval,
-                                                  bool doit, GucSource source);
- static const char *assign_min_error_statement(const char *newval, bool doit,
-                                                  GucSource source);
- static const char *assign_msglvl(int *var, const char *newval, bool doit,
-                         GucSource source);
- static const char *assign_log_error_verbosity(const char *newval, bool doit,
-                                                  GucSource source);
- static const char *assign_log_statement(const char *newval, bool doit,
-                                        GucSource source);
  static const char *show_num_temp_buffers(void);
  static bool assign_phony_autocommit(bool newval, bool doit, GucSource source);
  static const char *assign_custom_variable_classes(const char *newval, bool 
doit,
--- 144,149 ----
***************
*** 181,186 ****
--- 169,209 ----
  static bool assign_maxconnections(int newval, bool doit, GucSource source);
  
  /*
+  * Options for enum values exported from this module 
+  */
+ static const struct config_enum_entry config_message_levels[] = {
+       {"debug", DEBUG2},
+       {"debug5", DEBUG5},
+       {"debug4", DEBUG4},
+       {"debug3", DEBUG3},
+       {"debug2", DEBUG2},
+       {"debug1", DEBUG1},
+       {"log", LOG},
+       {"info", INFO},
+       {"notice", NOTICE},
+       {"warning", WARNING},
+       {"error", ERROR},
+     {"fatal", FATAL},
+       {"panic", PANIC},
+       {NULL, 0}
+ };
+ 
+ static const struct config_enum_entry log_error_verbosity_options[] = {
+       {"default", PGERROR_DEFAULT},
+       {"terse", PGERROR_TERSE},
+       {"verbose", PGERROR_VERBOSE},
+       {NULL, 0}
+ };
+ 
+ static const struct config_enum_entry log_statement_options[] = {
+       {"none", LOGSTMT_NONE},
+       {"ddl", LOGSTMT_DDL},
+       {"mod", LOGSTMT_MOD},
+       {"all", LOGSTMT_ALL},
+       {NULL, 0}
+ };
+ 
+ /*
   * GUC option variables that are exported from this module
   */
  #ifdef USE_ASSERT_CHECKING
***************
*** 230,240 ****
   * cases provide the value for SHOW to display.  The real state is elsewhere
   * and is kept in sync by assign_hooks.
   */
- static char *client_min_messages_str;
- static char *log_min_messages_str;
- static char *log_error_verbosity_str;
- static char *log_statement_str;
- static char *log_min_error_statement_str;
  static char *log_destination_string;
  
  #ifdef HAVE_SYSLOG
--- 253,258 ----
***************
*** 400,406 ****
         /* PGC_BOOL */ "bool",
         /* PGC_INT */ "integer",
         /* PGC_REAL */ "real",
!        /* PGC_STRING */ "string"
  };
  
  
--- 418,425 ----
         /* PGC_BOOL */ "bool",
         /* PGC_INT */ "integer",
         /* PGC_REAL */ "real",
!        /* PGC_STRING */ "string",
!        /* PGC_ENUM */ "enum"
  };
  
  
***************
*** 1922,1977 ****
        },
  
        {
-               {"client_min_messages", PGC_USERSET, LOGGING_WHEN,
-                       gettext_noop("Sets the message levels that are sent to 
the client."),
-                       gettext_noop("Valid values are DEBUG5, DEBUG4, DEBUG3, 
DEBUG2, "
-                                                "DEBUG1, LOG, NOTICE, WARNING, 
and ERROR. Each level includes all the "
-                                                "levels that follow it. The 
later the level, the fewer messages are "
-                                                "sent.")
-               },
-               &client_min_messages_str,
-               "notice", assign_client_min_messages, NULL
-       },
- 
-       {
-               {"log_min_messages", PGC_SUSET, LOGGING_WHEN,
-                       gettext_noop("Sets the message levels that are 
logged."),
-                       gettext_noop("Valid values are DEBUG5, DEBUG4, DEBUG3, 
DEBUG2, DEBUG1, "
-                       "INFO, NOTICE, WARNING, ERROR, LOG, FATAL, and PANIC. 
Each level "
-                                                "includes all the levels that 
follow it.")
-               },
-               &log_min_messages_str,
-               "notice", assign_log_min_messages, NULL
-       },
- 
-       {
-               {"log_error_verbosity", PGC_SUSET, LOGGING_WHEN,
-                       gettext_noop("Sets the verbosity of logged messages."),
-                       gettext_noop("Valid values are \"terse\", \"default\", 
and \"verbose\".")
-               },
-               &log_error_verbosity_str,
-               "default", assign_log_error_verbosity, NULL
-       },
-       {
-               {"log_statement", PGC_SUSET, LOGGING_WHAT,
-                       gettext_noop("Sets the type of statements logged."),
-                       gettext_noop("Valid values are \"none\", \"ddl\", 
\"mod\", and \"all\".")
-               },
-               &log_statement_str,
-               "none", assign_log_statement, NULL
-       },
- 
-       {
-               {"log_min_error_statement", PGC_SUSET, LOGGING_WHEN,
-                       gettext_noop("Causes all statements generating error at 
or above this level to be logged."),
-                       gettext_noop("All SQL statements that cause an error of 
the "
-                                                "specified level or a higher 
level are logged.")
-               },
-               &log_min_error_statement_str,
-               "error", assign_min_error_statement, NULL
-       },
- 
-       {
                {"log_line_prefix", PGC_SIGHUP, LOGGING_WHAT,
                        gettext_noop("Controls information prefixed to each log 
line."),
                        gettext_noop("If blank, no prefix is used.")
--- 1941,1946 ----
***************
*** 2467,2472 ****
--- 2436,2503 ----
  };
  
  
+ static struct config_enum ConfigureNamesEnum[] =
+ {
+       {
+               {"client_min_messages", PGC_USERSET, LOGGING_WHEN,
+                       gettext_noop("Sets the message levels that are sent to 
the client."),
+                       gettext_noop("Valid values are DEBUG5, DEBUG4, DEBUG3, 
DEBUG2, "
+                                                "DEBUG1, LOG, NOTICE, WARNING, 
and ERROR. Each level includes all the "
+                                                "levels that follow it. The 
later the level, the fewer messages are "
+                                                "sent.")
+               },
+               &client_min_messages,
+               NOTICE, config_message_levels,NULL, NULL
+       },
+ 
+       {
+               {"log_error_verbosity", PGC_SUSET, LOGGING_WHEN,
+                       gettext_noop("Sets the verbosity of logged messages."),
+                       gettext_noop("Valid values are \"terse\", \"default\", 
and \"verbose\".")
+               },
+               (int *)&Log_error_verbosity,
+               PGERROR_DEFAULT, log_error_verbosity_options, NULL, NULL
+       },
+ 
+       {
+               {"log_min_messages", PGC_SUSET, LOGGING_WHEN,
+                       gettext_noop("Sets the message levels that are 
logged."),
+                       gettext_noop("Valid values are DEBUG5, DEBUG4, DEBUG3, 
DEBUG2, DEBUG1, "
+                       "INFO, NOTICE, WARNING, ERROR, LOG, FATAL, and PANIC. 
Each level "
+                                                "includes all the levels that 
follow it.")
+               },
+               &log_min_messages,
+               NOTICE, config_message_levels, NULL, NULL
+       },
+ 
+       {
+               {"log_min_error_statement", PGC_SUSET, LOGGING_WHEN,
+                       gettext_noop("Causes all statements generating error at 
or above this level to be logged."),
+                       gettext_noop("All SQL statements that cause an error of 
the "
+                                                "specified level or a higher 
level are logged.")
+               },
+               &log_min_error_statement,
+               ERROR, config_message_levels, NULL, NULL
+       },
+ 
+       {
+               {"log_statement", PGC_SUSET, LOGGING_WHAT,
+                       gettext_noop("Sets the type of statements logged."),
+                       gettext_noop("Valid values are \"none\", \"ddl\", 
\"mod\", and \"all\".")
+               },
+               (int *)&log_statement,
+               LOGSTMT_NONE, log_statement_options, NULL, NULL
+       },
+ 
+ 
+ 
+ 
+       /* End-of-list marker */
+       {
+               {NULL, 0, 0, NULL, NULL}, NULL, 0, NULL, NULL, NULL
+       }
+ };
+ 
  /******** end of options list ********/
  
  
***************
*** 2633,2638 ****
--- 2664,2673 ----
                                                         &(val->stringval),
                                                         *((struct 
config_string *) gconf)->variable);
                        break;
+               case PGC_ENUM:
+                       val->enumval = 
+                               *((struct config_enum *) gconf)->variable;
+                       break;
        }
  }
  
***************
*** 2647,2652 ****
--- 2682,2688 ----
                case PGC_BOOL:
                case PGC_INT:
                case PGC_REAL:
+               case PGC_ENUM:
                        /* no need to do anything */
                        break;
                case PGC_STRING:
***************
*** 2714,2719 ****
--- 2750,2763 ----
                num_vars++;
        }
  
+       for (i = 0; ConfigureNamesEnum[i].gen.name; i++)
+       {
+               struct config_enum *conf = &ConfigureNamesEnum[i];
+ 
+               conf->gen.vartype = PGC_ENUM;
+               num_vars++;
+       }
+ 
        /*
         * Create table with 20% slack
         */
***************
*** 2736,2741 ****
--- 2780,2788 ----
        for (i = 0; ConfigureNamesString[i].gen.name; i++)
                guc_vars[num_vars++] = &ConfigureNamesString[i].gen;
  
+       for (i = 0; ConfigureNamesEnum[i].gen.name; i++)
+               guc_vars[num_vars++] = &ConfigureNamesEnum[i].gen;
+ 
        if (guc_variables)
                free(guc_variables);
        guc_variables = guc_vars;
***************
*** 3086,3091 ****
--- 3133,3150 ----
                                        *conf->variable = str;
                                        break;
                                }
+                       case PGC_ENUM:
+                               {
+                                       struct config_enum *conf = (struct 
config_enum *) gconf;
+ 
+                                       if (conf->assign_hook)
+                                               if (!(*conf->assign_hook) 
(conf->boot_val, true,
+                                                                               
                   PGC_S_DEFAULT))
+                                                       elog(FATAL, "failed to 
initialize %s to %d",
+                                                                
conf->gen.name, conf->boot_val);
+                                       *conf->variable = conf->reset_val = 
conf->boot_val;
+                                       break;
+                               }
                }
        }
  
***************
*** 3385,3390 ****
--- 3444,3461 ----
                                        conf->gen.source = 
conf->gen.reset_source;
                                        break;
                                }
+                       case PGC_ENUM:
+                               {
+                                       struct config_enum *conf = (struct 
config_enum *) gconf;
+ 
+                                       if (conf->assign_hook)
+                                               if (!(*conf->assign_hook) 
(conf->reset_val, true,
+                                                                               
                   PGC_S_SESSION))
+                                                       elog(ERROR, "failed to 
reset %s", conf->gen.name);
+                                       *conf->variable = conf->reset_val;
+                                       conf->gen.source = 
conf->gen.reset_source;
+                                       break;
+                               }
                }
  
                if (gconf->flags & GUC_REPORT)
***************
*** 3734,3739 ****
--- 3805,3827 ----
                                                        set_string_field(conf, 
&stack->masked.stringval, NULL);
                                                        break;
                                                }
+                                       case PGC_ENUM:
+                                               {
+                                                       struct config_enum 
*conf = (struct config_enum *) gconf;
+                                                       int newval = 
newvalue.enumval;
+ 
+                                                       if (*conf->variable != 
newval)
+                                                       {
+                                                               if 
(conf->assign_hook)
+                                                                       if 
(!(*conf->assign_hook) (newval,
+                                                                               
                                           true, PGC_S_OVERRIDE))
+                                                                               
elog(LOG, "failed to commit %s",
+                                                                               
         conf->gen.name);
+                                                               *conf->variable 
= newval;
+                                                               changed = true;
+                                                       }
+                                                       break;
+                                               }
                                }
  
                                gconf->source = newsource;
***************
*** 4147,4152 ****
--- 4235,4312 ----
        return result;
  }
  
+ static const char *
+ config_enum_lookup_value(struct config_enum *record, int val)
+ {
+       const struct config_enum_entry *entry = record->options;
+       while (entry && entry->name)
+       {
+               if (entry->val == val)
+                       return entry->name;
+               entry++;
+       }
+       elog(ERROR, "could not find enum option %d for %s",
+                val, record->gen.name);
+       return NULL; /* silence compiler */
+ }
+ 
+ static bool
+ config_enum_lookup_name(struct config_enum *record, const char *value, int 
*retval)
+ {
+       const struct config_enum_entry *entry = record->options;
+       
+       if (retval)
+               *retval = 0;                    /* suppress compiler warning */
+       
+       while (entry && entry->name)
+       {
+               if (!pg_strcasecmp(value, entry->name))
+               {
+                       *retval = entry->val;
+                       return TRUE;
+               }
+               entry++;
+       }
+       return FALSE;
+ }
+ 
+ static char *
+ config_enum_get_options(struct config_enum *record, const char *prefix, const 
char *suffix)
+ {
+       const struct config_enum_entry *entry = record->options;
+       int             len = 0;
+       char   *hintmsg;
+ 
+       if (!entry || !entry->name)
+               return NULL;                                    /* Should not 
happen */
+       
+       while (entry && entry->name)
+       {
+               len += strlen(entry->name) + 2; /* string and ", " */
+               entry++;
+       }
+ 
+       hintmsg = malloc(len + strlen(prefix) + strlen(suffix) + 2);
+       if (!hintmsg)
+               return NULL;
+ 
+       strcpy(hintmsg, prefix);
+       
+       entry = record->options;
+       while (entry && entry->name)
+       {
+               strcat(hintmsg, entry->name);
+               strcat(hintmsg, ", ");
+               entry++;
+       }
+ 
+       /* Replace final comma/space */
+       hintmsg[strlen(hintmsg)-2] = '\0';
+       strcat(hintmsg, suffix);
+ 
+       return hintmsg;
+ }
+ 
  
  /*
   * Sets option `name' to given value. The value should be a string
***************
*** 4684,4689 ****
--- 4844,4920 ----
                                        free(newval);
                                break;
                        }
+               case PGC_ENUM:
+                       {
+                               struct config_enum *conf = (struct config_enum 
*) record;
+                               int                     newval;
+ 
+                               if (value)
+                               {
+                                       if (!config_enum_lookup_name(conf, 
value, &newval))
+                                       {
+                                               char *hintmsg = 
config_enum_get_options(conf, "Available values: ", ".");
+ 
+                                               ereport(elevel,
+                                                               
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                                                
errmsg("invalid value for parameter \"%s\": \"%s\"",
+                                                                               
name, value),
+                                                                hintmsg ? 
errhint(hintmsg) : 0));
+ 
+                                               if (hintmsg)
+                                                       free(hintmsg);
+                                               return false;
+                                       }
+                               }
+                               else if (source == PGC_S_DEFAULT)
+                                       newval = conf->boot_val;
+                               else
+                               {
+                                       newval = conf->reset_val;
+                                       source = conf->gen.reset_source;
+                               }
+ 
+                               if (conf->assign_hook)
+                                       if (!(*conf->assign_hook) (newval, 
changeVal, source))
+                                       {
+                                               ereport(elevel,
+                                                               
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                                                
errmsg("invalid value for parameter \"%s\": \"%d\"",
+                                                                               
name, newval)));
+                                               return false;
+                                       }
+ 
+                               if (changeVal || makeDefault)
+                               {
+                                       /* Save old value to support 
transaction abort */
+                                       if (!makeDefault)
+                                               push_old_value(&conf->gen, 
action);
+                                       if (changeVal)
+                                       {
+                                               *conf->variable = newval;
+                                               conf->gen.source = source;
+                                       }
+                                       if (makeDefault)
+                                       {
+                                               GucStack   *stack;
+ 
+                                               if (conf->gen.reset_source <= 
source)
+                                               {
+                                                       conf->reset_val = 
newval;
+                                                       conf->gen.reset_source 
= source;
+                                               }
+                                               for (stack = conf->gen.stack; 
stack; stack = stack->prev)
+                                               {
+                                                       if (stack->source <= 
source)
+                                                       {
+                                                               
stack->prior.enumval = newval;
+                                                               stack->source = 
source;
+                                                       }
+                                               }
+                                       }
+                               }
+                               break;
+                       }
        }
  
        if (changeVal && (record->flags & GUC_REPORT))
***************
*** 4748,4753 ****
--- 4979,4988 ----
  
                case PGC_STRING:
                        return *((struct config_string *) record)->variable;
+ 
+               case PGC_ENUM:
+                       return config_enum_lookup_value((struct config_enum *) 
record,
+                                                                               
        *((struct config_enum *) record)->variable);
        }
        return NULL;
  }
***************
*** 4792,4797 ****
--- 5027,5036 ----
  
                case PGC_STRING:
                        return ((struct config_string *) record)->reset_val;
+ 
+               case PGC_ENUM:
+                       return config_enum_lookup_value((struct config_enum *) 
record,
+                                                                               
    ((struct config_enum *) record)->reset_val);
        }
        return NULL;
  }
***************
*** 5603,5608 ****
--- 5842,5850 ----
  
                                /* max_val */
                                values[10] = NULL;
+ 
+                               /* enumvals */
+                               values[11] = NULL;
                        }
                        break;
  
***************
*** 5617,5622 ****
--- 5859,5867 ----
                                /* max_val */
                                snprintf(buffer, sizeof(buffer), "%d", 
lconf->max);
                                values[10] = pstrdup(buffer);
+ 
+                               /* enumvals */
+                               values[11] = NULL;
                        }
                        break;
  
***************
*** 5631,5636 ****
--- 5876,5884 ----
                                /* max_val */
                                snprintf(buffer, sizeof(buffer), "%g", 
lconf->max);
                                values[10] = pstrdup(buffer);
+ 
+                               /* enumvals */
+                               values[11] = NULL;
                        }
                        break;
  
***************
*** 5641,5646 ****
--- 5889,5910 ----
  
                                /* max_val */
                                values[10] = NULL;
+ 
+                               /* enumvals */
+                               values[11] = NULL;
+                       }
+                       break;
+ 
+               case PGC_ENUM:
+                       {
+                               /* min_val */
+                               values[9] = NULL;
+ 
+                               /* max_val */
+                               values[10] = NULL;
+ 
+                               /* enumvals */
+                               values[11] = config_enum_get_options((struct 
config_enum *) conf, "", "");
                        }
                        break;
  
***************
*** 5655,5660 ****
--- 5919,5927 ----
  
                                /* max_val */
                                values[10] = NULL;
+ 
+                               /* enumvals */
+                               values[11] = NULL;
                        }
                        break;
        }
***************
*** 5697,5703 ****
   * show_all_settings - equiv to SHOW ALL command but implemented as
   * a Table Function.
   */
! #define NUM_PG_SETTINGS_ATTS  11
  
  Datum
  show_all_settings(PG_FUNCTION_ARGS)
--- 5964,5970 ----
   * show_all_settings - equiv to SHOW ALL command but implemented as
   * a Table Function.
   */
! #define NUM_PG_SETTINGS_ATTS  12
  
  Datum
  show_all_settings(PG_FUNCTION_ARGS)
***************
*** 5747,5752 ****
--- 6014,6021 ----
                                                   TEXTOID, -1, 0);
                TupleDescInitEntry(tupdesc, (AttrNumber) 11, "max_val",
                                                   TEXTOID, -1, 0);
+               TupleDescInitEntry(tupdesc, (AttrNumber) 12, "enumvals",
+                                                  TEXTOID, -1, 0);
  
                /*
                 * Generate attribute metadata needed later to produce tuples 
from raw
***************
*** 5939,5944 ****
--- 6208,6224 ----
                        }
                        break;
  
+               case PGC_ENUM:
+                       {
+                               struct config_enum *conf = (struct config_enum 
*) record;
+ 
+                               if(conf->show_hook)
+                                       val = (*conf->show_hook) ();
+                               else
+                                       val = config_enum_lookup_value(conf, 
*conf->variable);
+                       }
+                       break;
+ 
                default:
                        /* just to keep compiler quiet */
                        val = "???";
***************
*** 5995,6000 ****
--- 6275,6289 ----
                                return *conf->variable != NULL &&
                                        strcmp(*conf->variable, newvalue) == 0;
                        }
+ 
+               case PGC_ENUM:
+                       {
+                               struct config_enum *conf = (struct config_enum 
*) record;
+                               int                     newval;
+ 
+                               return config_enum_lookup_name(conf, newvalue, 
&newval)
+                                       && *conf->variable == newval;
+                       }
        }
  
        return false;
***************
*** 6081,6086 ****
--- 6370,6383 ----
                                                fprintf(fp, "%s", 
*conf->variable);
                                        }
                                        break;
+ 
+                               case PGC_ENUM:
+                                       {
+                                               struct config_enum *conf = 
(struct config_enum *) gconf;
+                                               
+                                               fprintf(fp, "%s", 
config_enum_lookup_value(gconf, *gconf->variable));
+                                       }
+                                       break;
                        }
  
                        fputc(0, fp);
***************
*** 6607,6760 ****
  }
  
  static const char *
- assign_log_min_messages(const char *newval, bool doit, GucSource source)
- {
-       return (assign_msglvl(&log_min_messages, newval, doit, source));
- }
- 
- static const char *
- assign_client_min_messages(const char *newval, bool doit, GucSource source)
- {
-       return (assign_msglvl(&client_min_messages, newval, doit, source));
- }
- 
- static const char *
- assign_min_error_statement(const char *newval, bool doit, GucSource source)
- {
-       return (assign_msglvl(&log_min_error_statement, newval, doit, source));
- }
- 
- static const char *
- assign_msglvl(int *var, const char *newval, bool doit, GucSource source)
- {
-       if (pg_strcasecmp(newval, "debug") == 0)
-       {
-               if (doit)
-                       (*var) = DEBUG2;
-       }
-       else if (pg_strcasecmp(newval, "debug5") == 0)
-       {
-               if (doit)
-                       (*var) = DEBUG5;
-       }
-       else if (pg_strcasecmp(newval, "debug4") == 0)
-       {
-               if (doit)
-                       (*var) = DEBUG4;
-       }
-       else if (pg_strcasecmp(newval, "debug3") == 0)
-       {
-               if (doit)
-                       (*var) = DEBUG3;
-       }
-       else if (pg_strcasecmp(newval, "debug2") == 0)
-       {
-               if (doit)
-                       (*var) = DEBUG2;
-       }
-       else if (pg_strcasecmp(newval, "debug1") == 0)
-       {
-               if (doit)
-                       (*var) = DEBUG1;
-       }
-       else if (pg_strcasecmp(newval, "log") == 0)
-       {
-               if (doit)
-                       (*var) = LOG;
-       }
- 
-       /*
-        * Client_min_messages always prints 'info', but we allow it as a value
-        * anyway.
-        */
-       else if (pg_strcasecmp(newval, "info") == 0)
-       {
-               if (doit)
-                       (*var) = INFO;
-       }
-       else if (pg_strcasecmp(newval, "notice") == 0)
-       {
-               if (doit)
-                       (*var) = NOTICE;
-       }
-       else if (pg_strcasecmp(newval, "warning") == 0)
-       {
-               if (doit)
-                       (*var) = WARNING;
-       }
-       else if (pg_strcasecmp(newval, "error") == 0)
-       {
-               if (doit)
-                       (*var) = ERROR;
-       }
-       /* We allow FATAL/PANIC for client-side messages too. */
-       else if (pg_strcasecmp(newval, "fatal") == 0)
-       {
-               if (doit)
-                       (*var) = FATAL;
-       }
-       else if (pg_strcasecmp(newval, "panic") == 0)
-       {
-               if (doit)
-                       (*var) = PANIC;
-       }
-       else
-               return NULL;                    /* fail */
-       return newval;                          /* OK */
- }
- 
- static const char *
- assign_log_error_verbosity(const char *newval, bool doit, GucSource source)
- {
-       if (pg_strcasecmp(newval, "terse") == 0)
-       {
-               if (doit)
-                       Log_error_verbosity = PGERROR_TERSE;
-       }
-       else if (pg_strcasecmp(newval, "default") == 0)
-       {
-               if (doit)
-                       Log_error_verbosity = PGERROR_DEFAULT;
-       }
-       else if (pg_strcasecmp(newval, "verbose") == 0)
-       {
-               if (doit)
-                       Log_error_verbosity = PGERROR_VERBOSE;
-       }
-       else
-               return NULL;                    /* fail */
-       return newval;                          /* OK */
- }
- 
- static const char *
- assign_log_statement(const char *newval, bool doit, GucSource source)
- {
-       if (pg_strcasecmp(newval, "none") == 0)
-       {
-               if (doit)
-                       log_statement = LOGSTMT_NONE;
-       }
-       else if (pg_strcasecmp(newval, "ddl") == 0)
-       {
-               if (doit)
-                       log_statement = LOGSTMT_DDL;
-       }
-       else if (pg_strcasecmp(newval, "mod") == 0)
-       {
-               if (doit)
-                       log_statement = LOGSTMT_MOD;
-       }
-       else if (pg_strcasecmp(newval, "all") == 0)
-       {
-               if (doit)
-                       log_statement = LOGSTMT_ALL;
-       }
-       else
-               return NULL;                    /* fail */
-       return newval;                          /* OK */
- }
- 
- static const char *
  show_num_temp_buffers(void)
  {
        /*
--- 6904,6909 ----
Index: src/include/utils/guc.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/utils/guc.h,v
retrieving revision 1.90
diff -c -r1.90 guc.h
*** src/include/utils/guc.h     1 Jan 2008 19:45:59 -0000       1.90
--- src/include/utils/guc.h     3 Mar 2008 20:20:29 -0000
***************
*** 97,102 ****
--- 97,103 ----
  typedef bool (*GucBoolAssignHook) (bool newval, bool doit, GucSource source);
  typedef bool (*GucIntAssignHook) (int newval, bool doit, GucSource source);
  typedef bool (*GucRealAssignHook) (double newval, bool doit, GucSource 
source);
+ typedef bool (*GucEnumAssignHook) (int newval, bool doit, GucSource source);
  
  typedef const char *(*GucShowHook) (void);
  
Index: src/include/utils/guc_tables.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/utils/guc_tables.h,v
retrieving revision 1.38
diff -c -r1.38 guc_tables.h
*** src/include/utils/guc_tables.h      1 Jan 2008 19:45:59 -0000       1.38
--- src/include/utils/guc_tables.h      3 Mar 2008 20:20:29 -0000
***************
*** 24,30 ****
        PGC_BOOL,
        PGC_INT,
        PGC_REAL,
!       PGC_STRING
  };
  
  union config_var_value
--- 24,31 ----
        PGC_BOOL,
        PGC_INT,
        PGC_REAL,
!       PGC_STRING,
!       PGC_ENUM
  };
  
  union config_var_value
***************
*** 33,38 ****
--- 34,49 ----
        int                     intval;
        double          realval;
        char       *stringval;
+       int                     enumval;
+ };
+ 
+ /*
+  * Enum values are made up of an array of name-value pairs
+  */
+ struct config_enum_entry
+ {
+       const char *name;
+       int                     val;
  };
  
  /*
***************
*** 210,215 ****
--- 221,239 ----
        char       *reset_val;
  };
  
+ struct config_enum
+ {
+       struct config_generic gen;
+       /* constant fields, must be set correctly in initial value: */
+       int                *variable;
+       int                     boot_val;
+       const struct config_enum_entry *options;
+       GucEnumAssignHook assign_hook;
+       GucShowHook show_hook;
+       /* variable fields, initialized at runtime: */
+       int                     reset_val;
+ };
+ 
  /* constant tables corresponding to enums above and in guc.h */
  extern const char *const config_group_names[];
  extern const char *const config_type_names[];
--
Sent via pgsql-patches mailing list (pgsql-patches@postgresql.org)
To make changes to your Subscription:
http://mail.postgresql.org/mj/mj_wwwusr?domain=postgresql.org&extra=pgsql-patches

Reply via email to