summaryrefslogtreecommitdiff
path: root/src/backend/tsearch/ts_locale.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/tsearch/ts_locale.c')
-rw-r--r--src/backend/tsearch/ts_locale.c104
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)