diff options
Diffstat (limited to 'src/backend/tsearch/ts_locale.c')
-rw-r--r-- | src/backend/tsearch/ts_locale.c | 104 |
1 files changed, 103 insertions, 1 deletions
diff --git a/src/backend/tsearch/ts_locale.c b/src/backend/tsearch/ts_locale.c index dacf7325c6e..73d8ed51de7 100644 --- a/src/backend/tsearch/ts_locale.c +++ b/src/backend/tsearch/ts_locale.c @@ -7,15 +7,18 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/tsearch/ts_locale.c,v 1.7 2008/01/01 19:45:52 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/tsearch/ts_locale.c,v 1.7.2.1 2008/06/18 20:55:49 tgl Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" +#include "storage/fd.h" #include "tsearch/ts_locale.h" #include "tsearch/ts_public.h" +static void tsearch_readline_callback(void *arg); + #ifdef TS_USE_WIDE @@ -194,9 +197,108 @@ t_isprint(const char *ptr) /* + * Set up to read a file using tsearch_readline(). This facility is + * better than just reading the file directly because it provides error + * context pointing to the specific line where a problem is detected. + * + * Expected usage is: + * + * tsearch_readline_state trst; + * + * if (!tsearch_readline_begin(&trst, filename)) + * ereport(ERROR, + * (errcode(ERRCODE_CONFIG_FILE_ERROR), + * errmsg("could not open stop-word file \"%s\": %m", + * filename))); + * while ((line = tsearch_readline(&trst)) != NULL) + * process line; + * tsearch_readline_end(&trst); + * + * Note that the caller supplies the ereport() for file open failure; + * this is so that a custom message can be provided. The filename string + * passed to tsearch_readline_begin() must remain valid through + * tsearch_readline_end(). + */ +bool +tsearch_readline_begin(tsearch_readline_state *stp, + const char *filename) +{ + if ((stp->fp = AllocateFile(filename, "r")) == NULL) + return false; + stp->filename = filename; + stp->lineno = 0; + stp->curline = NULL; + /* Setup error traceback support for ereport() */ + stp->cb.callback = tsearch_readline_callback; + stp->cb.arg = (void *) stp; + stp->cb.previous = error_context_stack; + error_context_stack = &stp->cb; + return true; +} + +/* + * Read the next line from a tsearch data file (expected to be in UTF-8), and + * convert it to database encoding if needed. The returned string is palloc'd. + * NULL return means EOF. + */ +char * +tsearch_readline(tsearch_readline_state *stp) +{ + char *result; + + stp->lineno++; + stp->curline = NULL; + result = t_readline(stp->fp); + stp->curline = result; + return result; +} + +/* + * Close down after reading a file with tsearch_readline() + */ +void +tsearch_readline_end(tsearch_readline_state *stp) +{ + FreeFile(stp->fp); + /* Pop the error context stack */ + error_context_stack = stp->cb.previous; +} + +/* + * Error context callback for errors occurring while reading a tsearch + * configuration file. + */ +static void +tsearch_readline_callback(void *arg) +{ + tsearch_readline_state *stp = (tsearch_readline_state *) arg; + + /* + * We can't include the text of the config line for errors that occur + * during t_readline() itself. This is only partly a consequence of + * our arms-length use of that routine: the major cause of such + * errors is encoding violations, and we daren't try to print error + * messages containing badly-encoded data. + */ + if (stp->curline) + errcontext("line %d of configuration file \"%s\": \"%s\"", + stp->lineno, + stp->filename, + stp->curline); + else + errcontext("line %d of configuration file \"%s\"", + stp->lineno, + stp->filename); +} + + +/* * Read the next line from a tsearch data file (expected to be in UTF-8), and * convert it to database encoding if needed. The returned string is palloc'd. * NULL return means EOF. + * + * Note: direct use of this function is now deprecated. Go through + * tsearch_readline() to provide better error reporting. */ char * t_readline(FILE *fp) |