search.c (4052B)
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 linecount, 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 char buf[256]; 131 if (testname(fltp) == 0) return; 132 if (testtags(fltp) == 0) return; 133 if (testtype(fltp) == 0) return; 134 sprint(buf, "%.*s\n", (int)(uuid->parent->next->nbytes), AFTER(uuid->parent->next)); 135 if(buf[0] == '{') sysfatal("parser lost the plot :%d", linecount); 136 print(buf); 137 138 } 139 140 void 141 fltpnewendlist(FLTP *fltp){ 142 char *s; 143 FLTNode *ls; 144 fltpendlist(fltp); 145 ls = fltp->np->parent->next; 146 s = (char *)(ls) + sizeof(FLTNode); 147 snprint(buf, BufSize, "%.*s", (int)ls->nbytes, s); 148 if(ls->prev->parent == nil){ 149 uuid = fltp->np; 150 runtests(fltp); 151 name = nil; 152 tags = nil; 153 type = nil; 154 return; 155 } else if(strcmp(buf, "name") == 0) name = fltp->np; 156 else if(strcmp(buf, "tags") == 0) tags = fltp->np; 157 else if(strcmp(buf, "type") == 0)type = fltp->np; 158 } 159 160 void 161 fltpnewgetline(FLTP *fltp){ 162 FLTNode *old, *new; 163 old = fltp->np; 164 fltpgetline(fltp); 165 new = fltp->np; 166 167 new->prev = old->prev; 168 new->parent = old->parent; 169 if(old->prev != nil) old->prev->next = new; 170 171 free(old); 172 } 173 174 void 175 loadindex(void){ 176 Biobuf *bfd; 177 char *bp; 178 wdb = initfltp(); 179 FLTWord nw[] = { 180 { &nw[1], "}", fltpnewendlist }, 181 { wdb->wp, ".n", fltpnewgetline }, 182 }; 183 wdb->wp = nw; 184 bfd = Bfdopen(0, OREAD); 185 while((bp = Brdline(bfd, '\n')) != nil){ 186 linecount++; 187 evalfltp(wdb, bp, Blinelen(bfd)); 188 } 189 Bterm(bfd); 190 } 191 192 void 193 usage(void){ 194 fprint(2, "usage: %s [-t tags] [-T type] [name query]\n", argv0); 195 exits("usage"); 196 } 197 198 void 199 main(int argc, char *argv[]){ 200 char *t; 201 ARGBEGIN{ 202 case 't': 203 t = EARGF(usage()); 204 tagsqn = tokenize(t, tagsquery, MaxTags); 205 break; 206 case 'T': 207 t = EARGF(usage()); 208 typeqn = tokenize(t, typequery, MaxTags); 209 break; 210 default: 211 usage(); 212 } ARGEND 213 if(argc > 1) usage(); 214 if(argc == 1) re = regcomp(argv[0]); 215 else re = nil; 216 buf = malloc(BufSize); 217 bout = Bfdopen(1, OWRITE); 218 loadindex(); 219 }