#include #include "dat.h" #include "fn.h" static char* readline(Biobuf *b, char *path) { char *line; errno = 0; line = Brdstr(b, '\n', 1); if(errno != 0) die("can't read %s: %s", path, strerror(errno)); return line; } void dictlookup(Dictreq *req, Dictres *res) { Lang *l; Hmap *dict; Hnode *n; char *p, *e, *sp; Str tmp; res->key = req->pre; res->nkouho = 0; res->lang = req->lang; res->seq = req->seq; if(req->key.n == 0) return; l = getlang(req->lang); dict = l ? l->dict : nil; if(dict == nil) return; n = hmapget(dict, &req->key); if(n == nil || n->vlen == 0) return; p = n->val; e = p + n->vlen; while(res->nkouho < Maxkouho && p < e){ while(p < e && *p == ' ') p++; if(p == e) break; sp = p; while(p < e && *p != ' ') p++; if(!sinit(&tmp, sp, p - sp)){ res->nkouho = 0; return; } if(req->lang == LangEMOJI || scmp(&tmp, &req->key) != 0) res->kouho[res->nkouho++] = tmp; if(p < e) p++; } } void dictthread(void*) { Dictreq req; static Dictres res; threadsetname("dict"); for(;;){ if(chanrecv(dictreqc, &req) < 0) break; while(channbrecv(dictreqc, &req) > 0) ; dictlookup(&req, &res); chansend(dictresc, &res); } } static Hmap* dictopen(char *path) { Hmap *h; Biobuf *b; Str key, tmp; char *line, *tab, *p, *e; int len, lineno; b = Bopen(path, OREAD); if(b == nil) die("can't open %s: %s", path, strerror(errno)); h = hmapalloc(4096); lineno = 0; while((line = readline(b, path)) != nil){ lineno++; len = Blinelen(b); if(memchr(line, '\0', len) != nil) die("NUL in dictionary: %s:%d", path, lineno); if(len > 0 && line[len-1] == '\r') line[--len] = '\0'; if(len == 0 || line[0] == ';'){ free(line); continue; } tab = memchr(line, '\t', len); if(tab == nil || tab == line || tab >= line + len - 1 || memchr(tab+1, '\t', line+len-(tab+1)) != nil) die("malformed dictionary: %s:%d", path, lineno); *tab = '\0'; if(!sinit(&key, line, tab-line)) die("invalid or oversized dictionary key: %s:%d", path, lineno); for(p = tab+1; p < line+len; p = e+1){ e = memchr(p, ' ', line+len-p); if(e == nil) e = line+len; if(!sinit(&tmp, p, e-p)) die("invalid or oversized dictionary candidate: %s:%d", path, lineno); if(e == line+len) break; } hmapset(&h, &key, tab+1, len - (tab - line) - 1); free(line); } if(Bterm(b) < 0) die("can't close %s: %s", path, strerror(errno)); return h; } void dictinit(char *dir) { char *path; int i; for(i = 0; i < nlang; i++){ if(langs[i].dictname == nil) continue; path = smprint("%s/%s.dict", dir, langs[i].dictname); if(path == nil) die("out of memory"); langs[i].dict = dictopen(path); free(path); } }