+typedef struct Rejection Rejection;
+struct Rejection {
+ struct Rejection *next;
+ const char *fname;
+ int lno;
+ pcre *re;
+};
+
+Rejection *rejections;
+
+static void load_rejections(const char *which) {
+ char lbuf[1000];
+ char *fname= masprintf("%s/#%s-reject#.txt", get_vardir(), which);
+ int c, lno=0;
+ Rejection *rej;
+
+ if (!dbfile_open(fname)) { free(fname); return; }
+
+ while ((c= fgetc(dbfile))!=EOF) {
+ ungetc(c,dbfile);
+ lno++;
+ dbfile_getsline(lbuf,sizeof(lbuf),fname,lno);
+
+ if (!lbuf[0] || isspace(lbuf[0] || lbuf[0]=='#'))
+ continue;
+
+ rej= mmalloc(sizeof(*rej));
+ rej->next= rejections;
+ rej->fname= fname;
+ rej->lno= lno;
+
+ const char *err;
+ int erroffset;
+ rej->re= pcre_compile(lbuf, PCRE_NO_AUTO_CAPTURE|PCRE_UTF8,
+ &err, &erroffset, 0);
+ if (!rej->re) {
+ char *what= masprintf("invalid regexp at offset %d: %s\n",
+ erroffset, err);
+ dbfile_assertfail(fname, lno, what);
+ }
+ debugf("OCR LOADED REJECTION %s:%d `%s' %p\n", fname,lno, lbuf, rej->re);
+
+ rejections= rej;
+ }
+ sysassert(feof(dbfile));
+ dbfile_close();
+}
+
+static int should_reject(OcrReader *rd) {
+ static int rejections_loaded;
+ int ovector[30];
+
+ if (!rejections_loaded) {
+ fetch_with_rsync("reject");
+ load_rejections("master");
+ load_rejections("local");
+ rejections_loaded=1;
+ }
+
+ debugf("[OCR REJECTION `%s'%d", rd->result, rd->lresult);
+ Rejection *rej;
+ for (rej=rejections; rej; rej=rej->next) {
+ debugf(" (%p)", rej);
+
+ int res= pcre_exec(rej->re, 0, rd->result,rd->lresult, 0,
+ 0, ovector, ARRAYSIZE(ovector));
+ if (res==PCRE_ERROR_NOMATCH) continue;
+ sysassert(res>0);
+
+ debugf(" MATCH]\n");
+ fprintf(stderr,"Rejecting OCR result `%s' (due to %s:%d)\n",
+ rd->result, rej->fname,rej->lno);
+ return 1;
+ }
+ debugf(" OK]");
+ return 0;
+}
+