diff options
author | John Naylor | 2022-08-16 03:42:19 +0000 |
---|---|---|
committer | John Naylor | 2022-09-04 03:12:56 +0000 |
commit | 1b188ea7921a7d4f6cc569541e32c980d2221f9d (patch) | |
tree | b800750eb63e7898052eb88a3fec03d2dc707586 /src | |
parent | 73b9d051c6076cf1cf1b90af505c8b379147c8b1 (diff) |
Preparatory refactoring for compiling guc-file.c standalone
Mostly this involves moving ProcessConfigFileInternal() to guc.c
and fixing the shared API to match.
Reviewed by Andres Freund
Discussion: https://www.postgresql.org/message-id/20220810171935.7k5zgnjwqzalzmtm%40awork3.anarazel.de
Discussion: https://www.postgresql.org/message-id/CAFBsxsF8Gc2StS3haXofshHCzqNMRXiSxvQEYGwnFsTmsdwNeg@mail.gmail.com
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/utils/misc/guc-file.l | 360 | ||||
-rw-r--r-- | src/backend/utils/misc/guc.c | 360 | ||||
-rw-r--r-- | src/include/utils/guc.h | 9 |
3 files changed, 364 insertions, 365 deletions
diff --git a/src/backend/utils/misc/guc-file.l b/src/backend/utils/misc/guc-file.l index 88460422dd3..47d4bd18d56 100644 --- a/src/backend/utils/misc/guc-file.l +++ b/src/backend/utils/misc/guc-file.l @@ -49,12 +49,6 @@ static sigjmp_buf *GUC_flex_fatal_jmp; static void FreeConfigVariable(ConfigVariable *item); -static void record_config_file_error(const char *errmsg, - const char *config_file, - int lineno, - ConfigVariable **head_p, - ConfigVariable **tail_p); - static int GUC_flex_fatal(const char *msg); /* LCOV_EXCL_START */ @@ -161,358 +155,6 @@ ProcessConfigFile(GucContext context) } /* - * This function handles both actual config file (re)loads and execution of - * show_all_file_settings() (i.e., the pg_file_settings view). In the latter - * case we don't apply any of the settings, but we make all the usual validity - * checks, and we return the ConfigVariable list so that it can be printed out - * by show_all_file_settings(). - */ -static ConfigVariable * -ProcessConfigFileInternal(GucContext context, bool applySettings, int elevel) -{ - bool error = false; - bool applying = false; - const char *ConfFileWithError; - ConfigVariable *item, - *head, - *tail; - int i; - - /* Parse the main config file into a list of option names and values */ - ConfFileWithError = ConfigFileName; - head = tail = NULL; - - if (!ParseConfigFile(ConfigFileName, true, - NULL, 0, 0, elevel, - &head, &tail)) - { - /* Syntax error(s) detected in the file, so bail out */ - error = true; - goto bail_out; - } - - /* - * Parse the PG_AUTOCONF_FILENAME file, if present, after the main file to - * replace any parameters set by ALTER SYSTEM command. Because this file - * is in the data directory, we can't read it until the DataDir has been - * set. - */ - if (DataDir) - { - if (!ParseConfigFile(PG_AUTOCONF_FILENAME, false, - NULL, 0, 0, elevel, - &head, &tail)) - { - /* Syntax error(s) detected in the file, so bail out */ - error = true; - ConfFileWithError = PG_AUTOCONF_FILENAME; - goto bail_out; - } - } - else - { - /* - * If DataDir is not set, the PG_AUTOCONF_FILENAME file cannot be - * read. In this case, we don't want to accept any settings but - * data_directory from postgresql.conf, because they might be - * overwritten with settings in the PG_AUTOCONF_FILENAME file which - * will be read later. OTOH, since data_directory isn't allowed in the - * PG_AUTOCONF_FILENAME file, it will never be overwritten later. - */ - ConfigVariable *newlist = NULL; - - /* - * Prune all items except the last "data_directory" from the list. - */ - for (item = head; item; item = item->next) - { - if (!item->ignore && - strcmp(item->name, "data_directory") == 0) - newlist = item; - } - - if (newlist) - newlist->next = NULL; - head = tail = newlist; - - /* - * Quick exit if data_directory is not present in file. - * - * We need not do any further processing, in particular we don't set - * PgReloadTime; that will be set soon by subsequent full loading of - * the config file. - */ - if (head == NULL) - goto bail_out; - } - - /* - * Mark all extant GUC variables as not present in the config file. We - * need this so that we can tell below which ones have been removed from - * the file since we last processed it. - */ - for (i = 0; i < num_guc_variables; i++) - { - struct config_generic *gconf = guc_variables[i]; - - gconf->status &= ~GUC_IS_IN_FILE; - } - - /* - * Check if all the supplied option names are valid, as an additional - * quasi-syntactic check on the validity of the config file. It is - * important that the postmaster and all backends agree on the results of - * this phase, else we will have strange inconsistencies about which - * processes accept a config file update and which don't. Hence, unknown - * custom variable names have to be accepted without complaint. For the - * same reason, we don't attempt to validate the options' values here. - * - * In addition, the GUC_IS_IN_FILE flag is set on each existing GUC - * variable mentioned in the file; and we detect duplicate entries in the - * file and mark the earlier occurrences as ignorable. - */ - for (item = head; item; item = item->next) - { - struct config_generic *record; - - /* Ignore anything already marked as ignorable */ - if (item->ignore) - continue; - - /* - * Try to find the variable; but do not create a custom placeholder if - * it's not there already. - */ - record = find_option(item->name, false, true, elevel); - - if (record) - { - /* If it's already marked, then this is a duplicate entry */ - if (record->status & GUC_IS_IN_FILE) - { - /* - * Mark the earlier occurrence(s) as dead/ignorable. We could - * avoid the O(N^2) behavior here with some additional state, - * but it seems unlikely to be worth the trouble. - */ - ConfigVariable *pitem; - - for (pitem = head; pitem != item; pitem = pitem->next) - { - if (!pitem->ignore && - strcmp(pitem->name, item->name) == 0) - pitem->ignore = true; - } - } - /* Now mark it as present in file */ - record->status |= GUC_IS_IN_FILE; - } - else if (!valid_custom_variable_name(item->name)) - { - /* Invalid non-custom variable, so complain */ - ereport(elevel, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("unrecognized configuration parameter \"%s\" in file \"%s\" line %d", - item->name, - item->filename, item->sourceline))); - item->errmsg = pstrdup("unrecognized configuration parameter"); - error = true; - ConfFileWithError = item->filename; - } - } - - /* - * If we've detected any errors so far, we don't want to risk applying any - * changes. - */ - if (error) - goto bail_out; - - /* Otherwise, set flag that we're beginning to apply changes */ - applying = true; - - /* - * Check for variables having been removed from the config file, and - * revert their reset values (and perhaps also effective values) to the - * boot-time defaults. If such a variable can't be changed after startup, - * report that and continue. - */ - for (i = 0; i < num_guc_variables; i++) - { - struct config_generic *gconf = guc_variables[i]; - GucStack *stack; - - if (gconf->reset_source != PGC_S_FILE || - (gconf->status & GUC_IS_IN_FILE)) - continue; - if (gconf->context < PGC_SIGHUP) - { - /* The removal can't be effective without a restart */ - gconf->status |= GUC_PENDING_RESTART; - ereport(elevel, - (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM), - errmsg("parameter \"%s\" cannot be changed without restarting the server", - gconf->name))); - record_config_file_error(psprintf("parameter \"%s\" cannot be changed without restarting the server", - gconf->name), - NULL, 0, - &head, &tail); - error = true; - continue; - } - - /* No more to do if we're just doing show_all_file_settings() */ - if (!applySettings) - continue; - - /* - * Reset any "file" sources to "default", else set_config_option will - * not override those settings. - */ - if (gconf->reset_source == PGC_S_FILE) - gconf->reset_source = PGC_S_DEFAULT; - if (gconf->source == PGC_S_FILE) - gconf->source = PGC_S_DEFAULT; - for (stack = gconf->stack; stack; stack = stack->prev) - { - if (stack->source == PGC_S_FILE) - stack->source = PGC_S_DEFAULT; - } - - /* Now we can re-apply the wired-in default (i.e., the boot_val) */ - if (set_config_option(gconf->name, NULL, - context, PGC_S_DEFAULT, - GUC_ACTION_SET, true, 0, false) > 0) - { - /* Log the change if appropriate */ - if (context == PGC_SIGHUP) - ereport(elevel, - (errmsg("parameter \"%s\" removed from configuration file, reset to default", - gconf->name))); - } - } - - /* - * Restore any variables determined by environment variables or - * dynamically-computed defaults. This is a no-op except in the case - * where one of these had been in the config file and is now removed. - * - * In particular, we *must not* do this during the postmaster's initial - * loading of the file, since the timezone functions in particular should - * be run only after initialization is complete. - * - * XXX this is an unmaintainable crock, because we have to know how to set - * (or at least what to call to set) every non-PGC_INTERNAL variable that - * could potentially have PGC_S_DYNAMIC_DEFAULT or PGC_S_ENV_VAR source. - */ - if (context == PGC_SIGHUP && applySettings) - { - InitializeGUCOptionsFromEnvironment(); - pg_timezone_abbrev_initialize(); - /* this selects SQL_ASCII in processes not connected to a database */ - SetConfigOption("client_encoding", GetDatabaseEncodingName(), - PGC_BACKEND, PGC_S_DYNAMIC_DEFAULT); - } - - /* - * Now apply the values from the config file. - */ - for (item = head; item; item = item->next) - { - char *pre_value = NULL; - int scres; - - /* Ignore anything marked as ignorable */ - if (item->ignore) - continue; - - /* In SIGHUP cases in the postmaster, we want to report changes */ - if (context == PGC_SIGHUP && applySettings && !IsUnderPostmaster) - { - const char *preval = GetConfigOption(item->name, true, false); - - /* If option doesn't exist yet or is NULL, treat as empty string */ - if (!preval) - preval = ""; - /* must dup, else might have dangling pointer below */ - pre_value = pstrdup(preval); - } - - scres = set_config_option(item->name, item->value, - context, PGC_S_FILE, - GUC_ACTION_SET, applySettings, 0, false); - if (scres > 0) - { - /* variable was updated, so log the change if appropriate */ - if (pre_value) - { - const char *post_value = GetConfigOption(item->name, true, false); - - if (!post_value) - post_value = ""; - if (strcmp(pre_value, post_value) != 0) - ereport(elevel, - (errmsg("parameter \"%s\" changed to \"%s\"", - item->name, item->value))); - } - item->applied = true; - } - else if (scres == 0) - { - error = true; - item->errmsg = pstrdup("setting could not be applied"); - ConfFileWithError = item->filename; - } - else - { - /* no error, but variable's active value was not changed */ - item->applied = true; - } - - /* - * We should update source location unless there was an error, since - * even if the active value didn't change, the reset value might have. - * (In the postmaster, there won't be a difference, but it does matter - * in backends.) - */ - if (scres != 0 && applySettings) - set_config_sourcefile(item->name, item->filename, - item->sourceline); - - if (pre_value) - pfree(pre_value); - } - - /* Remember when we last successfully loaded the config file. */ - if (applySettings) - PgReloadTime = GetCurrentTimestamp(); - -bail_out: - if (error && applySettings) - { - /* During postmaster startup, any error is fatal */ - if (context == PGC_POSTMASTER) - ereport(ERROR, - (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("configuration file \"%s\" contains errors", - ConfFileWithError))); - else if (applying) - ereport(elevel, - (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("configuration file \"%s\" contains errors; unaffected changes were applied", - ConfFileWithError))); - else - ereport(elevel, - (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("configuration file \"%s\" contains errors; no changes were applied", - ConfFileWithError))); - } - - /* Successful or otherwise, return the collected data list */ - return head; -} - -/* * Given a configuration file or directory location that may be a relative * path, return an absolute one. We consider the location to be relative to * the directory holding the calling file, or to DataDir if no calling file. @@ -660,7 +302,7 @@ cleanup: * Capture an error message in the ConfigVariable list returned by * config file parsing. */ -static void +void record_config_file_error(const char *errmsg, const char *config_file, int lineno, diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 9fbbfb1be54..66ab3912a0e 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -243,10 +243,6 @@ static void assign_recovery_target_lsn(const char *newval, void *extra); static bool check_primary_slot_name(char **newval, void **extra, GucSource source); static bool check_default_with_oids(bool *newval, void **extra, GucSource source); -/* Private functions in guc-file.l that need to be called from guc.c */ -static ConfigVariable *ProcessConfigFileInternal(GucContext context, - bool applySettings, int elevel); - /* * Track whether there were any deferred checks for custom resource managers * specified in wal_consistency_checking. @@ -5160,8 +5156,8 @@ static bool report_needed; /* true if any GUC_REPORT reports are needed */ static int GUCNestLevel = 0; /* 1 when in main transaction */ +static struct config_generic *find_option(const char *name, bool create_placeholders, bool skip_errors, int elevel); static int guc_var_compare(const void *a, const void *b); -static int guc_name_compare(const char *namea, const char *nameb); static void InitializeGUCOptionsFromEnvironment(void); static void InitializeOneGUCOption(struct config_generic *gconf); static void push_old_value(struct config_generic *gconf, GucAction action); @@ -5180,7 +5176,359 @@ static bool validate_option_array_item(const char *name, const char *value, static void write_auto_conf_file(int fd, const char *filename, ConfigVariable *head_p); static void replace_auto_config_value(ConfigVariable **head_p, ConfigVariable **tail_p, const char *name, const char *value); +static bool valid_custom_variable_name(const char *name); + +/* + * This function handles both actual config file (re)loads and execution of + * show_all_file_settings() (i.e., the pg_file_settings view). In the latter + * case we don't apply any of the settings, but we make all the usual validity + * checks, and we return the ConfigVariable list so that it can be printed out + * by show_all_file_settings(). + */ +ConfigVariable * +ProcessConfigFileInternal(GucContext context, bool applySettings, int elevel) +{ + bool error = false; + bool applying = false; + const char *ConfFileWithError; + ConfigVariable *item, + *head, + *tail; + int i; + + /* Parse the main config file into a list of option names and values */ + ConfFileWithError = ConfigFileName; + head = tail = NULL; + + if (!ParseConfigFile(ConfigFileName, true, + NULL, 0, 0, elevel, + &head, &tail)) + { + /* Syntax error(s) detected in the file, so bail out */ + error = true; + goto bail_out; + } + + /* + * Parse the PG_AUTOCONF_FILENAME file, if present, after the main file to + * replace any parameters set by ALTER SYSTEM command. Because this file + * is in the data directory, we can't read it until the DataDir has been + * set. + */ + if (DataDir) + { + if (!ParseConfigFile(PG_AUTOCONF_FILENAME, false, + NULL, 0, 0, elevel, + &head, &tail)) + { + /* Syntax error(s) detected in the file, so bail out */ + error = true; + ConfFileWithError = PG_AUTOCONF_FILENAME; + goto bail_out; + } + } + else + { + /* + * If DataDir is not set, the PG_AUTOCONF_FILENAME file cannot be + * read. In this case, we don't want to accept any settings but + * data_directory from postgresql.conf, because they might be + * overwritten with settings in the PG_AUTOCONF_FILENAME file which + * will be read later. OTOH, since data_directory isn't allowed in the + * PG_AUTOCONF_FILENAME file, it will never be overwritten later. + */ + ConfigVariable *newlist = NULL; + + /* + * Prune all items except the last "data_directory" from the list. + */ + for (item = head; item; item = item->next) + { + if (!item->ignore && + strcmp(item->name, "data_directory") == 0) + newlist = item; + } + if (newlist) + newlist->next = NULL; + head = tail = newlist; + + /* + * Quick exit if data_directory is not present in file. + * + * We need not do any further processing, in particular we don't set + * PgReloadTime; that will be set soon by subsequent full loading of + * the config file. + */ + if (head == NULL) + goto bail_out; + } + + /* + * Mark all extant GUC variables as not present in the config file. We + * need this so that we can tell below which ones have been removed from + * the file since we last processed it. + */ + for (i = 0; i < num_guc_variables; i++) + { + struct config_generic *gconf = guc_variables[i]; + + gconf->status &= ~GUC_IS_IN_FILE; + } + + /* + * Check if all the supplied option names are valid, as an additional + * quasi-syntactic check on the validity of the config file. It is + * important that the postmaster and all backends agree on the results of + * this phase, else we will have strange inconsistencies about which + * processes accept a config file update and which don't. Hence, unknown + * custom variable names have to be accepted without complaint. For the + * same reason, we don't attempt to validate the options' values here. + * + * In addition, the GUC_IS_IN_FILE flag is set on each existing GUC + * variable mentioned in the file; and we detect duplicate entries in the + * file and mark the earlier occurrences as ignorable. + */ + for (item = head; item; item = item->next) + { + struct config_generic *record; + + /* Ignore anything already marked as ignorable */ + if (item->ignore) + continue; + + /* + * Try to find the variable; but do not create a custom placeholder if + * it's not there already. + */ + record = find_option(item->name, false, true, elevel); + + if (record) + { + /* If it's already marked, then this is a duplicate entry */ + if (record->status & GUC_IS_IN_FILE) + { + /* + * Mark the earlier occurrence(s) as dead/ignorable. We could + * avoid the O(N^2) behavior here with some additional state, + * but it seems unlikely to be worth the trouble. + */ + ConfigVariable *pitem; + + for (pitem = head; pitem != item; pitem = pitem->next) + { + if (!pitem->ignore && + strcmp(pitem->name, item->name) == 0) + pitem->ignore = true; + } + } + /* Now mark it as present in file */ + record->status |= GUC_IS_IN_FILE; + } + else if (!valid_custom_variable_name(item->name)) + { + /* Invalid non-custom variable, so complain */ + ereport(elevel, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("unrecognized configuration parameter \"%s\" in file \"%s\" line %d", + item->name, + item->filename, item->sourceline))); + item->errmsg = pstrdup("unrecognized configuration parameter"); + error = true; + ConfFileWithError = item->filename; + } + } + + /* + * If we've detected any errors so far, we don't want to risk applying any + * changes. + */ + if (error) + goto bail_out; + + /* Otherwise, set flag that we're beginning to apply changes */ + applying = true; + + /* + * Check for variables having been removed from the config file, and + * revert their reset values (and perhaps also effective values) to the + * boot-time defaults. If such a variable can't be changed after startup, + * report that and continue. + */ + for (i = 0; i < num_guc_variables; i++) + { + struct config_generic *gconf = guc_variables[i]; + GucStack *stack; + + if (gconf->reset_source != PGC_S_FILE || + (gconf->status & GUC_IS_IN_FILE)) + continue; + if (gconf->context < PGC_SIGHUP) + { + /* The removal can't be effective without a restart */ + gconf->status |= GUC_PENDING_RESTART; + ereport(elevel, + (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM), + errmsg("parameter \"%s\" cannot be changed without restarting the server", + gconf->name))); + record_config_file_error(psprintf("parameter \"%s\" cannot be changed without restarting the server", + gconf->name), + NULL, 0, + &head, &tail); + error = true; + continue; + } + + /* No more to do if we're just doing show_all_file_settings() */ + if (!applySettings) + continue; + + /* + * Reset any "file" sources to "default", else set_config_option will + * not override those settings. + */ + if (gconf->reset_source == PGC_S_FILE) + gconf->reset_source = PGC_S_DEFAULT; + if (gconf->source == PGC_S_FILE) + gconf->source = PGC_S_DEFAULT; + for (stack = gconf->stack; stack; stack = stack->prev) + { + if (stack->source == PGC_S_FILE) + stack->source = PGC_S_DEFAULT; + } + + /* Now we can re-apply the wired-in default (i.e., the boot_val) */ + if (set_config_option(gconf->name, NULL, + context, PGC_S_DEFAULT, + GUC_ACTION_SET, true, 0, false) > 0) + { + /* Log the change if appropriate */ + if (context == PGC_SIGHUP) + ereport(elevel, + (errmsg("parameter \"%s\" removed from configuration file, reset to default", + gconf->name))); + } + } + + /* + * Restore any variables determined by environment variables or + * dynamically-computed defaults. This is a no-op except in the case + * where one of these had been in the config file and is now removed. + * + * In particular, we *must not* do this during the postmaster's initial + * loading of the file, since the timezone functions in particular should + * be run only after initialization is complete. + * + * XXX this is an unmaintainable crock, because we have to know how to set + * (or at least what to call to set) every non-PGC_INTERNAL variable that + * could potentially have PGC_S_DYNAMIC_DEFAULT or PGC_S_ENV_VAR source. + */ + if (context == PGC_SIGHUP && applySettings) + { + InitializeGUCOptionsFromEnvironment(); + pg_timezone_abbrev_initialize(); + /* this selects SQL_ASCII in processes not connected to a database */ + SetConfigOption("client_encoding", GetDatabaseEncodingName(), + PGC_BACKEND, PGC_S_DYNAMIC_DEFAULT); + } + + /* + * Now apply the values from the config file. + */ + for (item = head; item; item = item->next) + { + char *pre_value = NULL; + int scres; + + /* Ignore anything marked as ignorable */ + if (item->ignore) + continue; + + /* In SIGHUP cases in the postmaster, we want to report changes */ + if (context == PGC_SIGHUP && applySettings && !IsUnderPostmaster) + { + const char *preval = GetConfigOption(item->name, true, false); + + /* If option doesn't exist yet or is NULL, treat as empty string */ + if (!preval) + preval = ""; + /* must dup, else might have dangling pointer below */ + pre_value = pstrdup(preval); + } + + scres = set_config_option(item->name, item->value, + context, PGC_S_FILE, + GUC_ACTION_SET, applySettings, 0, false); + if (scres > 0) + { + /* variable was updated, so log the change if appropriate */ + if (pre_value) + { + const char *post_value = GetConfigOption(item->name, true, false); + + if (!post_value) + post_value = ""; + if (strcmp(pre_value, post_value) != 0) + ereport(elevel, + (errmsg("parameter \"%s\" changed to \"%s\"", + item->name, item->value))); + } + item->applied = true; + } + else if (scres == 0) + { + error = true; + item->errmsg = pstrdup("setting could not be applied"); + ConfFileWithError = item->filename; + } + else + { + /* no error, but variable's active value was not changed */ + item->applied = true; + } + + /* + * We should update source location unless there was an error, since + * even if the active value didn't change, the reset value might have. + * (In the postmaster, there won't be a difference, but it does matter + * in backends.) + */ + if (scres != 0 && applySettings) + set_config_sourcefile(item->name, item->filename, + item->sourceline); + + if (pre_value) + pfree(pre_value); + } + + /* Remember when we last successfully loaded the config file. */ + if (applySettings) + PgReloadTime = GetCurrentTimestamp(); + +bail_out: + if (error && applySettings) + { + /* During postmaster startup, any error is fatal */ + if (context == PGC_POSTMASTER) + ereport(ERROR, + (errcode(ERRCODE_CONFIG_FILE_ERROR), + errmsg("configuration file \"%s\" contains errors", + ConfFileWithError))); + else if (applying) + ereport(elevel, + (errcode(ERRCODE_CONFIG_FILE_ERROR), + errmsg("configuration file \"%s\" contains errors; unaffected changes were applied", + ConfFileWithError))); + else + ereport(elevel, + (errcode(ERRCODE_CONFIG_FILE_ERROR), + errmsg("configuration file \"%s\" contains errors; no changes were applied", + ConfFileWithError))); + } + + /* Successful or otherwise, return the collected data list */ + return head; +} /* * Some infrastructure for checking malloc/strdup/realloc calls @@ -5737,7 +6085,7 @@ guc_var_compare(const void *a, const void *b) /* * the bare comparison function for GUC names */ -static int +int guc_name_compare(const char *namea, const char *nameb) { /* diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h index e734493a484..aae071cd825 100644 --- a/src/include/utils/guc.h +++ b/src/include/utils/guc.h @@ -442,6 +442,15 @@ extern void GUC_check_errcode(int sqlerrcode); pre_format_elog_string(errno, TEXTDOMAIN), \ GUC_check_errhint_string = format_elog_string +/* functions shared between guc.c and guc-file.l */ +extern int guc_name_compare(const char *namea, const char *nameb); +extern ConfigVariable *ProcessConfigFileInternal(GucContext context, + bool applySettings, int elevel); +extern void record_config_file_error(const char *errmsg, + const char *config_file, + int lineno, + ConfigVariable **head_p, + ConfigVariable **tail_p); /* * The following functions are not in guc.c, but are declared here to avoid |