diff --git a/contrib/dict_xsyn/dict_xsyn.c b/contrib/dict_xsyn/dict_xsyn.c index d98792aa01..f8430862be 100644 --- a/contrib/dict_xsyn/dict_xsyn.c +++ b/contrib/dict_xsyn/dict_xsyn.c @@ -6,7 +6,7 @@ * Copyright (c) 2007-2008, PostgreSQL Global Development Group * * IDENTIFICATION - * $PostgreSQL: pgsql/contrib/dict_xsyn/dict_xsyn.c,v 1.4 2008/01/01 20:31:21 tgl Exp $ + * $PostgreSQL: pgsql/contrib/dict_xsyn/dict_xsyn.c,v 1.5 2008/06/18 20:55:42 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -16,7 +16,6 @@ #include "commands/defrem.h" #include "fmgr.h" -#include "storage/fd.h" #include "tsearch/ts_locale.h" #include "tsearch/ts_utils.h" @@ -75,17 +74,17 @@ static void read_dictionary(DictSyn *d, char *filename) { char *real_filename = get_tsearch_config_filename(filename, "rules"); - FILE *fin; + tsearch_readline_state trst; char *line; int cur = 0; - if ((fin = AllocateFile(real_filename, "r")) == NULL) + if (!tsearch_readline_begin(&trst, real_filename)) ereport(ERROR, (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("could not open synonym file \"%s\": %m", real_filename))); - while ((line = t_readline(fin)) != NULL) + while ((line = tsearch_readline(&trst)) != NULL) { char *value; char *key; @@ -119,7 +118,7 @@ read_dictionary(DictSyn *d, char *filename) cur++; } - FreeFile(fin); + tsearch_readline_end(&trst); d->len = cur; if (cur > 1) diff --git a/src/backend/tsearch/dict_synonym.c b/src/backend/tsearch/dict_synonym.c index 6f263603d7..8558602ace 100644 --- a/src/backend/tsearch/dict_synonym.c +++ b/src/backend/tsearch/dict_synonym.c @@ -7,14 +7,13 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/tsearch/dict_synonym.c,v 1.8 2008/03/10 03:01:28 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/tsearch/dict_synonym.c,v 1.9 2008/06/18 20:55:42 tgl Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" #include "commands/defrem.h" -#include "storage/fd.h" #include "tsearch/ts_locale.h" #include "tsearch/ts_public.h" #include "tsearch/ts_utils.h" @@ -79,7 +78,7 @@ dsynonym_init(PG_FUNCTION_ARGS) ListCell *l; char *filename = NULL; bool case_sensitive = false; - FILE *fin; + tsearch_readline_state trst; char *starti, *starto, *end = NULL; @@ -108,7 +107,7 @@ dsynonym_init(PG_FUNCTION_ARGS) filename = get_tsearch_config_filename(filename, "syn"); - if ((fin = AllocateFile(filename, "r")) == NULL) + if (!tsearch_readline_begin(&trst, filename)) ereport(ERROR, (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("could not open synonym file \"%s\": %m", @@ -116,7 +115,7 @@ dsynonym_init(PG_FUNCTION_ARGS) d = (DictSyn *) palloc0(sizeof(DictSyn)); - while ((line = t_readline(fin)) != NULL) + while ((line = tsearch_readline(&trst)) != NULL) { starti = findwrd(line, &end); if (!starti) @@ -175,7 +174,7 @@ skipline: pfree(line); } - FreeFile(fin); + tsearch_readline_end(&trst); d->len = cur; qsort(d->syn, d->len, sizeof(Syn), compareSyn); diff --git a/src/backend/tsearch/dict_thesaurus.c b/src/backend/tsearch/dict_thesaurus.c index 6fcffa7457..0f9c133f2e 100644 --- a/src/backend/tsearch/dict_thesaurus.c +++ b/src/backend/tsearch/dict_thesaurus.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/tsearch/dict_thesaurus.c,v 1.11 2008/01/01 19:45:52 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/tsearch/dict_thesaurus.c,v 1.12 2008/06/18 20:55:42 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -15,7 +15,6 @@ #include "catalog/namespace.h" #include "commands/defrem.h" -#include "storage/fd.h" #include "tsearch/ts_cache.h" #include "tsearch/ts_locale.h" #include "tsearch/ts_public.h" @@ -169,21 +168,19 @@ addWrd(DictThesaurus *d, char *b, char *e, uint16 idsubst, uint16 nwrd, uint16 p static void thesaurusRead(char *filename, DictThesaurus *d) { - FILE *fh; - int lineno = 0; + tsearch_readline_state trst; uint16 idsubst = 0; bool useasis = false; char *line; filename = get_tsearch_config_filename(filename, "ths"); - fh = AllocateFile(filename, "r"); - if (!fh) + if (!tsearch_readline_begin(&trst, filename)) ereport(ERROR, (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("could not open thesaurus file \"%s\": %m", filename))); - while ((line = t_readline(fh)) != NULL) + while ((line = tsearch_readline(&trst)) != NULL) { char *ptr; int state = TR_WAITLEX; @@ -191,8 +188,6 @@ thesaurusRead(char *filename, DictThesaurus *d) uint16 posinsubst = 0; uint16 nwrd = 0; - lineno++; - ptr = line; /* is it a comment? */ @@ -213,13 +208,9 @@ thesaurusRead(char *filename, DictThesaurus *d) if (t_iseq(ptr, ':')) { if (posinsubst == 0) - { - FreeFile(fh); ereport(ERROR, (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("unexpected delimiter at line %d of thesaurus file \"%s\"", - lineno, filename))); - } + errmsg("unexpected delimiter"))); state = TR_WAITSUBS; } else if (!t_isspace(ptr)) @@ -269,8 +260,7 @@ thesaurusRead(char *filename, DictThesaurus *d) if (ptr == beginwrd) ereport(ERROR, (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("unexpected end of line or lexeme at line %d of thesaurus file \"%s\"", - lineno, filename))); + errmsg("unexpected end of line or lexeme"))); addWrd(d, beginwrd, ptr, idsubst, nwrd++, posinsubst, useasis); state = TR_WAITSUBS; } @@ -286,28 +276,23 @@ thesaurusRead(char *filename, DictThesaurus *d) if (ptr == beginwrd) ereport(ERROR, (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("unexpected end of line or lexeme at line %d of thesaurus file \"%s\"", - lineno, filename))); + errmsg("unexpected end of line or lexeme"))); addWrd(d, beginwrd, ptr, idsubst, nwrd++, posinsubst, useasis); } idsubst++; if (!(nwrd && posinsubst)) - { - FreeFile(fh); ereport(ERROR, (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("unexpected end of line at line %d of thesaurus file \"%s\"", - lineno, filename))); - } + errmsg("unexpected end of line"))); pfree(line); } d->nsubst = idsubst; - FreeFile(fh); + tsearch_readline_end(&trst); } static TheLexeme * diff --git a/src/backend/tsearch/spell.c b/src/backend/tsearch/spell.c index a2837d1683..d6e3a081b8 100644 --- a/src/backend/tsearch/spell.c +++ b/src/backend/tsearch/spell.c @@ -7,14 +7,13 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/tsearch/spell.c,v 1.11 2008/01/21 02:46:10 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/tsearch/spell.c,v 1.12 2008/06/18 20:55:42 tgl Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" -#include "storage/fd.h" #include "tsearch/dicts/spell.h" #include "tsearch/ts_locale.h" #include "utils/memutils.h" @@ -194,18 +193,18 @@ NIAddSpell(IspellDict *Conf, const char *word, const char *flag) void NIImportDictionary(IspellDict *Conf, const char *filename) { - FILE *dict; + tsearch_readline_state trst; char *line; checkTmpCtx(); - if (!(dict = AllocateFile(filename, "r"))) + if (!tsearch_readline_begin(&trst, filename)) ereport(ERROR, (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("could not open dictionary file \"%s\": %m", filename))); - while ((line = t_readline(dict)) != NULL) + while ((line = tsearch_readline(&trst)) != NULL) { char *s, *pstr; @@ -250,7 +249,7 @@ NIImportDictionary(IspellDict *Conf, const char *filename) pfree(line); } - FreeFile(dict); + tsearch_readline_end(&trst); } @@ -392,8 +391,7 @@ NIAddAffix(IspellDict *Conf, int flag, char flagflags, const char *mask, const c #define PAE_INREPL 5 static bool -parse_affentry(char *str, char *mask, char *find, char *repl, - const char *filename, int lineno) +parse_affentry(char *str, char *mask, char *find, char *repl) { int state = PAE_WAIT_MASK; char *pmask = mask, @@ -443,8 +441,7 @@ parse_affentry(char *str, char *mask, char *find, char *repl, else if (!t_isspace(str)) ereport(ERROR, (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("syntax error at line %d of affix file \"%s\"", - lineno, filename))); + errmsg("syntax error"))); } else if (state == PAE_INFIND) { @@ -461,8 +458,7 @@ parse_affentry(char *str, char *mask, char *find, char *repl, else if (!t_isspace(str)) ereport(ERROR, (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("syntax error at line %d of affix file \"%s\"", - lineno, filename))); + errmsg("syntax error"))); } else if (state == PAE_WAIT_REPL) { @@ -479,8 +475,7 @@ parse_affentry(char *str, char *mask, char *find, char *repl, else if (!t_isspace(str)) ereport(ERROR, (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("syntax error at line %d of affix file \"%s\"", - lineno, filename))); + errmsg("syntax error"))); } else if (state == PAE_INREPL) { @@ -497,8 +492,7 @@ parse_affentry(char *str, char *mask, char *find, char *repl, else if (!t_isspace(str)) ereport(ERROR, (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("syntax error at line %d of affix file \"%s\"", - lineno, filename))); + errmsg("syntax error"))); } else elog(ERROR, "unrecognized state in parse_affentry: %d", state); @@ -512,8 +506,7 @@ parse_affentry(char *str, char *mask, char *find, char *repl, } static void -addFlagValue(IspellDict *Conf, char *s, uint32 val, - const char *filename, int lineno) +addFlagValue(IspellDict *Conf, char *s, uint32 val) { while (*s && t_isspace(s)) s++; @@ -521,14 +514,12 @@ addFlagValue(IspellDict *Conf, char *s, uint32 val, if (!*s) ereport(ERROR, (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("syntax error at line %d of affix file \"%s\"", - lineno, filename))); + errmsg("syntax error"))); if (pg_mblen(s) != 1) ereport(ERROR, (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("multibyte flag character is not allowed at line %d of affix file \"%s\"", - lineno, filename))); + errmsg("multibyte flag character is not allowed"))); Conf->flagval[(unsigned int) *s] = (unsigned char) val; Conf->usecompound = true; @@ -549,8 +540,7 @@ NIImportOOAffixes(IspellDict *Conf, const char *filename) bool isSuffix = false; int flag = 0; char flagflags = 0; - FILE *affix; - int lineno = 0; + tsearch_readline_state trst; int scanread = 0; char scanbuf[BUFSIZ]; char *recoded; @@ -561,16 +551,14 @@ NIImportOOAffixes(IspellDict *Conf, const char *filename) memset(Conf->flagval, 0, sizeof(Conf->flagval)); Conf->usecompound = false; - if (!(affix = AllocateFile(filename, "r"))) + if (!tsearch_readline_begin(&trst, filename)) ereport(ERROR, (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("could not open affix file \"%s\": %m", filename))); - while ((recoded = t_readline(affix)) != NULL) + while ((recoded = tsearch_readline(&trst)) != NULL) { - lineno++; - if (*recoded == '\0' || t_isspace(recoded) || t_iseq(recoded, '#')) { pfree(recoded); @@ -579,29 +567,29 @@ NIImportOOAffixes(IspellDict *Conf, const char *filename) if (STRNCMP(recoded, "COMPOUNDFLAG") == 0) addFlagValue(Conf, recoded + strlen("COMPOUNDFLAG"), - FF_COMPOUNDFLAG, filename, lineno); + FF_COMPOUNDFLAG); else if (STRNCMP(recoded, "COMPOUNDBEGIN") == 0) addFlagValue(Conf, recoded + strlen("COMPOUNDBEGIN"), - FF_COMPOUNDBEGIN, filename, lineno); + FF_COMPOUNDBEGIN); else if (STRNCMP(recoded, "COMPOUNDLAST") == 0) addFlagValue(Conf, recoded + strlen("COMPOUNDLAST"), - FF_COMPOUNDLAST, filename, lineno); + FF_COMPOUNDLAST); /* COMPOUNDLAST and COMPOUNDEND are synonyms */ else if (STRNCMP(recoded, "COMPOUNDEND") == 0) addFlagValue(Conf, recoded + strlen("COMPOUNDEND"), - FF_COMPOUNDLAST, filename, lineno); + FF_COMPOUNDLAST); else if (STRNCMP(recoded, "COMPOUNDMIDDLE") == 0) addFlagValue(Conf, recoded + strlen("COMPOUNDMIDDLE"), - FF_COMPOUNDMIDDLE, filename, lineno); + FF_COMPOUNDMIDDLE); else if (STRNCMP(recoded, "ONLYINCOMPOUND") == 0) addFlagValue(Conf, recoded + strlen("ONLYINCOMPOUND"), - FF_COMPOUNDONLY, filename, lineno); + FF_COMPOUNDONLY); else if (STRNCMP(recoded, "COMPOUNDPERMITFLAG") == 0) addFlagValue(Conf, recoded + strlen("COMPOUNDPERMITFLAG"), - FF_COMPOUNDPERMITFLAG, filename, lineno); + FF_COMPOUNDPERMITFLAG); else if (STRNCMP(recoded, "COMPOUNDFORBIDFLAG") == 0) addFlagValue(Conf, recoded + strlen("COMPOUNDFORBIDFLAG"), - FF_COMPOUNDFORBIDFLAG, filename, lineno); + FF_COMPOUNDFORBIDFLAG); else if (STRNCMP(recoded, "FLAG") == 0) { char *s = recoded + strlen("FLAG"); @@ -612,26 +600,23 @@ NIImportOOAffixes(IspellDict *Conf, const char *filename) if (*s && STRNCMP(s, "default") != 0) ereport(ERROR, (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("Ispell dictionary supports only default flag value at line %d of affix file \"%s\"", - lineno, filename))); + errmsg("Ispell dictionary supports only default flag value"))); } pfree(recoded); } - FreeFile(affix); - lineno = 0; + tsearch_readline_end(&trst); sprintf(scanbuf, "%%6s %%%ds %%%ds %%%ds %%%ds", BUFSIZ / 5, BUFSIZ / 5, BUFSIZ / 5, BUFSIZ / 5); - if (!(affix = AllocateFile(filename, "r"))) + if (!tsearch_readline_begin(&trst, filename)) ereport(ERROR, (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("could not open affix file \"%s\": %m", filename))); - while ((recoded = t_readline(affix)) != NULL) + while ((recoded = tsearch_readline(&trst)) != NULL) { - lineno++; if (*recoded == '\0' || t_isspace(recoded) || t_iseq(recoded, '#')) goto nextline; @@ -691,9 +676,9 @@ nextline: pfree(recoded); } + tsearch_readline_end(&trst); if (ptype) pfree(ptype); - FreeFile(affix); } /* @@ -713,14 +698,13 @@ NIImportAffixes(IspellDict *Conf, const char *filename) bool prefixes = false; int flag = 0; char flagflags = 0; - FILE *affix; - int lineno = 0; + tsearch_readline_state trst; bool oldformat = false; char *recoded = NULL; checkTmpCtx(); - if (!(affix = AllocateFile(filename, "r"))) + if (!tsearch_readline_begin(&trst, filename)) ereport(ERROR, (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("could not open affix file \"%s\": %m", @@ -729,12 +713,10 @@ NIImportAffixes(IspellDict *Conf, const char *filename) memset(Conf->flagval, 0, sizeof(Conf->flagval)); Conf->usecompound = false; - while ((recoded = t_readline(affix)) != NULL) + while ((recoded = tsearch_readline(&trst)) != NULL) { pstr = lowerstr(recoded); - lineno++; - /* Skip comments and empty lines */ if (*pstr == '#' || *pstr == '\n') goto nextline; @@ -787,8 +769,7 @@ NIImportAffixes(IspellDict *Conf, const char *filename) if (pg_mblen(s) != 1) ereport(ERROR, (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("multibyte flag character is not allowed at line %d of affix file \"%s\"", - lineno, filename))); + errmsg("multibyte flag character is not allowed"))); if (*s == '*') { @@ -808,8 +789,7 @@ NIImportAffixes(IspellDict *Conf, const char *filename) if (pg_mblen(s) != 1) ereport(ERROR, (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("multibyte flag character is not allowed at line %d of affix file \"%s\"", - lineno, filename))); + errmsg("multibyte flag character is not allowed"))); flag = (unsigned char) *s; goto nextline; @@ -820,16 +800,15 @@ NIImportAffixes(IspellDict *Conf, const char *filename) if (oldformat) ereport(ERROR, (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("wrong affix file format for flag at line %d of affix file \"%s\"", - lineno, filename))); - FreeFile(affix); + errmsg("wrong affix file format for flag"))); + tsearch_readline_end(&trst); NIImportOOAffixes(Conf, filename); return; } if ((!suffixes) && (!prefixes)) goto nextline; - if (!parse_affentry(pstr, mask, find, repl, filename, lineno)) + if (!parse_affentry(pstr, mask, find, repl)) goto nextline; NIAddAffix(Conf, flag, flagflags, mask, find, repl, suffixes ? FF_SUFFIX : FF_PREFIX); @@ -838,7 +817,7 @@ nextline: pfree(recoded); pfree(pstr); } - FreeFile(affix); + tsearch_readline_end(&trst); } static int diff --git a/src/backend/tsearch/ts_locale.c b/src/backend/tsearch/ts_locale.c index 5ce367a497..53349d7fc0 100644 --- a/src/backend/tsearch/ts_locale.c +++ b/src/backend/tsearch/ts_locale.c @@ -7,15 +7,19 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/tsearch/ts_locale.c,v 1.9 2008/06/18 18:42:54 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/tsearch/ts_locale.c,v 1.10 2008/06/18 20:55:42 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 USE_WIDE_UPPER_LOWER int @@ -76,12 +80,111 @@ t_isprint(const char *ptr) #endif /* USE_WIDE_UPPER_LOWER */ +/* + * 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) { int len; diff --git a/src/backend/tsearch/ts_utils.c b/src/backend/tsearch/ts_utils.c index 3708d02689..0458664789 100644 --- a/src/backend/tsearch/ts_utils.c +++ b/src/backend/tsearch/ts_utils.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/tsearch/ts_utils.c,v 1.10 2008/06/18 18:42:54 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/tsearch/ts_utils.c,v 1.11 2008/06/18 20:55:42 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -17,7 +17,6 @@ #include #include "miscadmin.h" -#include "storage/fd.h" #include "tsearch/ts_locale.h" #include "tsearch/ts_public.h" #include "tsearch/ts_utils.h" @@ -82,17 +81,17 @@ readstoplist(const char *fname, StopList *s, char *(*wordop) (const char *)) if (fname && *fname) { char *filename = get_tsearch_config_filename(fname, "stop"); - FILE *hin; + tsearch_readline_state trst; char *line; int reallen = 0; - if ((hin = AllocateFile(filename, "r")) == NULL) + 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 = t_readline(hin)) != NULL) + while ((line = tsearch_readline(&trst)) != NULL) { char *pbuf = line; @@ -135,7 +134,7 @@ readstoplist(const char *fname, StopList *s, char *(*wordop) (const char *)) (s->len)++; } - FreeFile(hin); + tsearch_readline_end(&trst); pfree(filename); } diff --git a/src/include/tsearch/ts_locale.h b/src/include/tsearch/ts_locale.h index 110efb191c..b05ab7f1b0 100644 --- a/src/include/tsearch/ts_locale.h +++ b/src/include/tsearch/ts_locale.h @@ -5,7 +5,7 @@ * * Copyright (c) 1998-2008, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/include/tsearch/ts_locale.h,v 1.7 2008/06/18 18:42:54 momjian Exp $ + * $PostgreSQL: pgsql/src/include/tsearch/ts_locale.h,v 1.8 2008/06/18 20:55:42 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -29,6 +29,16 @@ #include #endif +/* working state for tsearch_readline (should be a local var in caller) */ +typedef struct +{ + FILE *fp; + const char *filename; + int lineno; + char *curline; + ErrorContextCallback cb; +} tsearch_readline_state; + #define TOUCHAR(x) (*((const unsigned char *) (x))) #ifdef USE_WIDE_UPPER_LOWER @@ -55,6 +65,12 @@ extern int t_isprint(const char *ptr); extern char *lowerstr(const char *str); extern char *lowerstr_with_len(const char *str, int len); + +extern bool tsearch_readline_begin(tsearch_readline_state *stp, + const char *filename); +extern char *tsearch_readline(tsearch_readline_state *stp); +extern void tsearch_readline_end(tsearch_readline_state *stp); + extern char *t_readline(FILE *fp); #endif /* __TSLOCALE_H__ */