/* * ISpell interface * Teodor Sigaev */ #include #include #include #include #include "postgres.h" #include "dict.h" #include "common.h" #define SYNBUFLEN 4096 typedef struct { char *in; char *out; } Syn; typedef struct { int len; Syn *syn; } DictSyn; PG_FUNCTION_INFO_V1(syn_init); Datum syn_init(PG_FUNCTION_ARGS); PG_FUNCTION_INFO_V1(syn_lexize); Datum syn_lexize(PG_FUNCTION_ARGS); static char * findwrd(char *in, char **end) { char *start; *end=NULL; while(*in && isspace(*in)) in++; if ( !in ) return NULL; start=in; while(*in && !isspace(*in)) in++; *end=in; return start; } static int compareSyn(const void *a, const void *b) { return strcmp( ((Syn*)a)->in, ((Syn*)b)->in ); } Datum syn_init(PG_FUNCTION_ARGS) { text *in; DictSyn *d; int cur=0; FILE *fin; char *filename; char buf[SYNBUFLEN]; char *starti,*starto,*end=NULL; int slen; if ( PG_ARGISNULL(0) || PG_GETARG_POINTER(0)==NULL ) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("NULL config"))); in = PG_GETARG_TEXT_P(0); if ( VARSIZE(in) - VARHDRSZ == 0 ) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("VOID config"))); filename=text2char(in); PG_FREE_IF_COPY(in, 0); if ( (fin=fopen(filename,"r")) == NULL ) ereport(ERROR, (errcode_for_file_access(), errmsg("could not open file \"%s\": %m", filename))); d = (DictSyn*)malloc( sizeof(DictSyn) ); if ( !d ) { fclose(fin); ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"))); } memset(d,0,sizeof(DictSyn)); while( fgets(buf,SYNBUFLEN,fin) ) { slen = strlen(buf)-1; buf[slen] = '\0'; if ( *buf=='\0' ) continue; if (cur==d->len) { d->len = (d->len) ? 2*d->len : 16; d->syn=(Syn*)realloc( d->syn, sizeof(Syn)*d->len ); if ( !d->syn ) { fclose(fin); ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"))); } } starti=findwrd(buf,&end); if ( !starti ) continue; *end='\0'; if ( end >= buf+slen ) continue; starto= findwrd(end+1, &end); if ( !starto ) continue; *end='\0'; d->syn[cur].in=strdup(lowerstr(starti)); d->syn[cur].out=strdup(lowerstr(starto)); if ( !(d->syn[cur].in && d->syn[cur].out) ) { fclose(fin); ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"))); } cur++; } fclose(fin); d->len=cur; if ( cur>1 ) qsort(d->syn, d->len, sizeof(Syn), compareSyn); pfree(filename); PG_RETURN_POINTER(d); } Datum syn_lexize(PG_FUNCTION_ARGS) { DictSyn *d = (DictSyn*)PG_GETARG_POINTER(0); char *in = (char*)PG_GETARG_POINTER(1); Syn key,*found; char **res=NULL; if ( !PG_GETARG_INT32(2) ) PG_RETURN_POINTER(NULL); key.out=NULL; key.in=lowerstr(pnstrdup(in, PG_GETARG_INT32(2))); found=(Syn*)bsearch(&key, d->syn, d->len, sizeof(Syn), compareSyn); pfree(key.in); if ( !found ) PG_RETURN_POINTER(NULL); res=palloc(sizeof(char*)*2); res[0]=pstrdup(found->out); res[1]=NULL; PG_RETURN_POINTER(res); }