search-fltp.c (3956B)
1 #include <u.h> 2 #include <libc.h> 3 #include <bio.h> 4 #include <regexp.h> 5 6 Biobuf *bout; 7 8 #include "../fltp/fltp.h" 9 10 #define AFTER(X) ( (char *)X + sizeof(*X) ) 11 12 enum{ 13 MaxTags = 256, 14 BufSize = 4096, 15 ListSize = 256, 16 }; 17 18 int tagsqn, typeqn; 19 char *buf, *tagsquery[MaxTags + 1], *typequery[MaxTags + 1], *tagslist[MaxTags]; 20 FLTNode *uuid, *name, *tags, *type; 21 Reprog *re; 22 23 FLTP *wdb; 24 25 void 26 node2buf(FLTNode *p) 27 { 28 snprint(buf, BufSize, "%.*s", (int)p->nbytes, AFTER(p)); 29 } 30 31 int 32 _testtag(char **tags, int n, char *test){ 33 char **p; 34 for(p = tags; p < tags + n; p++){ 35 if (strcmp(test, *p) == 0) return 1; 36 } 37 return 0; 38 } 39 40 int 41 _testtags(FLTNode *p){ 42 int n, i, t; 43 node2buf(p); 44 t = tokenize(buf, tagslist, MaxTags); 45 n = 0; 46 for(i = 0; i < t; i++){ 47 if (_testtag(tagsquery, tagsqn, tagslist[i]) != 0) n++; 48 } 49 return n; 50 } 51 52 int 53 _testtype(FLTNode *p){ 54 int n, i, t; 55 node2buf(p); 56 t = tokenize(buf, tagslist, MaxTags); 57 n = 0; 58 for(i = 0; i < t; i++){ 59 if (_testtag(typequery, typeqn, tagslist[i]) != 0) n++; 60 } 61 return n; 62 } 63 64 int 65 _iselem(FLTNode *p){ 66 fprint(2, "elem %.*s\n", (int)p->nbytes, AFTER(p)); 67 return 0; 68 } 69 70 int 71 _islist(FLTNode *p){ 72 fprint(2, "list %.*s\n", (int)p->nbytes, AFTER(p)); 73 return 0; 74 } 75 76 int 77 _testnameelem(FLTNode *p) 78 { 79 node2buf(p); 80 return regexec(re, buf, nil, 0); 81 } 82 83 int 84 _testnamelist(FLTNode *) 85 { 86 node2buf(uuid); 87 fprint(2, "sublist in name field: %s\n", buf); 88 return 0; 89 } 90 91 int 92 testlist(FLTNode *lp, int (*elemfp)(FLTNode *), int (*listfp)(FLTNode *)){ 93 FLTNode *p, *root; 94 int r; 95 r = 0; 96 root = lp->parent; 97 for(p = lp->prev; p->prev != root; p = p->prev){ 98 if(p->parent != root) continue; 99 if(p->next->parent == p) r += (listfp == nil) ? 0 : listfp(p); 100 else r += (elemfp == nil) ? 0 : elemfp(p); 101 } 102 return r; 103 } 104 105 int 106 testname(FLTP *){ 107 if (re == nil) return 1; 108 if(name == nil) sysfatal("name == nil"); 109 return testlist(name, _testnameelem, _testnamelist); 110 } 111 112 int 113 testtags(FLTP *){ 114 int n; 115 if (tagsquery[0] == nil) return 1; 116 if(tags == nil) sysfatal("tags == nil"); 117 n = testlist(tags, _testtags, nil); 118 return n >= tagsqn; 119 } 120 121 int 122 testtype(FLTP *){ 123 if (typequery[0] == nil) return 1; 124 if(type == nil) sysfatal("type == nil"); 125 return testlist(type, _testtype, nil); 126 } 127 128 void 129 runtests(FLTP *fltp){ 130 if (testname(fltp) == 0) return; 131 if (testtags(fltp) == 0) return; 132 if (testtype(fltp) == 0) return; 133 print("%.*s\n", (int)(uuid->parent->next->nbytes), AFTER(uuid->parent->next)); 134 } 135 136 void 137 fltpnewendlist(FLTP *fltp){ 138 char *s; 139 FLTNode *ls; 140 fltpendlist(fltp); 141 ls = fltp->np->parent->next; 142 s = (char *)(ls) + sizeof(FLTNode); 143 snprint(buf, BufSize, "%.*s", (int)ls->nbytes, s); 144 if(ls->prev->parent == nil){ 145 uuid = fltp->np; 146 runtests(fltp); 147 name = nil; 148 tags = nil; 149 type = nil; 150 return; 151 } else if(strcmp(buf, "name") == 0) name = fltp->np; 152 else if(strcmp(buf, "tags") == 0) tags = fltp->np; 153 else if(strcmp(buf, "type") == 0)type = fltp->np; 154 } 155 156 void 157 fltpnewgetline(FLTP *fltp){ 158 FLTNode *old, *new; 159 old = fltp->np; 160 fltpgetline(fltp); 161 new = fltp->np; 162 163 new->prev = old->prev; 164 new->parent = old->parent; 165 if(old->prev != nil) old->prev->next = new; 166 167 free(old); 168 } 169 170 void 171 loadindex(void){ 172 Biobuf *bfd; 173 char *bp, *path = "/usr/rpa/lib/wdb/index/fltp"; 174 wdb = initfltp(); 175 FLTWord nw[] = { 176 { &nw[1], "}", fltpnewendlist }, 177 { wdb->wp, ".n", fltpnewgetline }, 178 }; 179 wdb->wp = nw; 180 bfd = Bopen(path, OREAD); 181 while((bp = Brdline(bfd, '\n')) != nil){ 182 evalfltp(wdb, bp, Blinelen(bfd)); 183 } 184 Bterm(bfd); 185 } 186 187 void 188 usage(void){ 189 fprint(2, "usage: %s [-t tags] [-T type] [query]\n", argv0); 190 exits("usage"); 191 } 192 193 void 194 main(int argc, char *argv[]){ 195 char *t; 196 ARGBEGIN{ 197 case 't': 198 t = EARGF(usage()); 199 tagsqn = tokenize(t, tagsquery, MaxTags); 200 break; 201 case 'T': 202 t = EARGF(usage()); 203 typeqn = tokenize(t, typequery, MaxTags); 204 break; 205 default: 206 usage(); 207 } ARGEND 208 if(argc > 1) usage(); 209 if(argc == 1) re = regcomp(argv[0]); 210 else re = nil; 211 buf = malloc(BufSize); 212 bout = Bfdopen(1, OWRITE); 213 loadindex(); 214 }