56 |
#include "global.h" |
#include "global.h" |
57 |
#include "const.h" |
#include "const.h" |
58 |
|
|
59 |
|
struct dup_entry { |
60 |
|
int offset; |
61 |
|
SPLIT ptable; |
62 |
|
int lineno; |
63 |
|
int skip; |
64 |
|
}; |
65 |
|
|
66 |
static void usage(void); |
static void usage(void); |
67 |
static void help(void); |
static void help(void); |
68 |
void signal_setup(void); |
void signal_setup(void); |
69 |
void onintr(int); |
void onintr(int); |
70 |
int match(const char *, const char *); |
static int compare_dup_entry(const void *, const void *); |
71 |
|
static void put_lines(char *, struct dup_entry *, int); |
72 |
int main(int, char **); |
int main(int, char **); |
73 |
int incremental(const char *, const char *); |
int incremental(const char *, const char *); |
74 |
void updatetags(const char *, const char *, IDSET *, STRBUF *, int, int); |
void updatetags(const char *, const char *, IDSET *, STRBUF *, int, int); |
180 |
#endif |
#endif |
181 |
} |
} |
182 |
|
|
183 |
int |
/* |
184 |
match(curtag, line) |
* compare_dup_entry: compare function for sorting. |
185 |
const char *curtag; |
*/ |
186 |
const char *line; |
static int |
187 |
|
compare_dup_entry(v1, v2) |
188 |
|
const void *v1; |
189 |
|
const void *v2; |
190 |
|
{ |
191 |
|
const struct dup_entry *e1 = v1, *e2 = v2; |
192 |
|
int ret; |
193 |
|
|
194 |
|
if ((ret = strcmp(e1->ptable.part[PART_PATH].start, |
195 |
|
e2->ptable.part[PART_PATH].start)) != 0) |
196 |
|
return ret; |
197 |
|
return e1->lineno - e2->lineno; |
198 |
|
} |
199 |
|
/* |
200 |
|
* put_lines: sort and print duplicate lines |
201 |
|
*/ |
202 |
|
static void |
203 |
|
put_lines(lines, entries, entry_count) |
204 |
|
char *lines; |
205 |
|
struct dup_entry *entries; |
206 |
|
int entry_count; |
207 |
{ |
{ |
208 |
const char *p, *q = line; |
int i; |
209 |
|
|
210 |
for (p = curtag; *p; p++) |
for (i = 0; i < entry_count; i++) { |
211 |
if (*p != *q++) |
char *ctags_x = lines + entries[i].offset; |
212 |
return 0; |
SPLIT *ptable = &entries[i].ptable; |
213 |
if (!isspace((unsigned char)*q)) |
|
214 |
return 0; |
if (split(ctags_x, 4, ptable) < 4) { |
215 |
return 1; |
recover(ptable); |
216 |
|
die("too small number of parts.\n'%s'", ctags_x); |
217 |
|
} |
218 |
|
entries[i].lineno = atoi(ptable->part[PART_LNO].start); |
219 |
|
entries[i].skip = 0; |
220 |
|
} |
221 |
|
qsort(entries, entry_count, sizeof(struct dup_entry), compare_dup_entry); |
222 |
|
for (i = 1; i < entry_count; i++) { |
223 |
|
if (entries[i].lineno == entries[i - 1].lineno |
224 |
|
&& strcmp(entries[i].ptable.part[PART_PATH].start, |
225 |
|
entries[i - 1].ptable.part[PART_PATH].start) == 0) |
226 |
|
entries[i].skip = 1; |
227 |
|
} |
228 |
|
for (i = 0; i < entry_count; i++) { |
229 |
|
recover(&entries[i].ptable); |
230 |
|
if (!entries[i].skip) |
231 |
|
puts(lines + entries[i].offset); |
232 |
|
} |
233 |
} |
} |
234 |
|
|
235 |
int |
int |
476 |
* is already sorted in alphabetical order by tag name, |
* is already sorted in alphabetical order by tag name, |
477 |
* we splited the output into relatively small unit and |
* we splited the output into relatively small unit and |
478 |
* execute sort for each unit. |
* execute sort for each unit. |
|
* |
|
|
* It is not certain whether the present unit value is the best. |
|
479 |
*/ |
*/ |
|
int unit = 1500; |
|
480 |
STRBUF *ib = strbuf_open(MAXBUFLEN); |
STRBUF *ib = strbuf_open(MAXBUFLEN); |
481 |
const char *ctags_x = strbuf_fgets(ib, stdin, 0); |
STRBUF *sb = strbuf_open(MAXBUFLEN); |
482 |
|
VARRAY *vb = varray_open(sizeof(struct dup_entry), 100); |
483 |
while (ctags_x != NULL) { |
char *ctags_x, prev[IDENTLEN]; |
484 |
int count = 0; |
|
485 |
FILE *op = popen("gnusort -k 1,1 -k 3,3 -k 2,2n -u", "w"); |
prev[0] = '\0'; |
486 |
do { |
while ((ctags_x = strbuf_fgets(ib, stdin, STRBUF_NOCRLF)) != NULL) { |
487 |
fputs(ctags_x, op); |
const char *tag; |
488 |
} while ((ctags_x = strbuf_fgets(ib, stdin, 0)) != NULL && ++count < unit); |
struct dup_entry *entry; |
489 |
if (ctags_x) { |
SPLIT ptable; |
490 |
/* curtag = current tag name */ |
|
491 |
STRBUF *curtag = strbuf_open(0); |
if (split(ctags_x, 2, &ptable) < 2) { |
492 |
const char *p = ctags_x; |
recover(&ptable); |
493 |
while (!isspace((unsigned char)*p)) |
die("too small number of parts.\n'%s'", ctags_x); |
|
strbuf_putc(curtag, *p++); |
|
|
/* read until next tag name */ |
|
|
do { |
|
|
fputs(ctags_x, op); |
|
|
} while ((ctags_x = strbuf_fgets(ib, stdin, 0)) != NULL |
|
|
&& match(strbuf_value(curtag), ctags_x)); |
|
494 |
} |
} |
495 |
if (pclose(op) != 0) |
tag = ptable.part[PART_TAG].start; |
496 |
die("terminated abnormally."); |
if (prev[0] == '\0' || strcmp(prev, tag) != 0) { |
497 |
|
if (prev[0] != '\0') { |
498 |
|
if (vb->length == 1) |
499 |
|
puts(strbuf_value(sb)); |
500 |
|
else |
501 |
|
put_lines(strbuf_value(sb), |
502 |
|
varray_assign(vb, 0, 0), |
503 |
|
vb->length); |
504 |
|
} |
505 |
|
strlimcpy(prev, tag, sizeof(prev)); |
506 |
|
strbuf_reset(sb); |
507 |
|
varray_reset(vb); |
508 |
|
} |
509 |
|
entry = varray_append(vb); |
510 |
|
entry->offset = strbuf_getlen(sb); |
511 |
|
recover(&ptable); |
512 |
|
strbuf_puts0(sb, ctags_x); |
513 |
} |
} |
514 |
|
if (prev[0] != '\0') { |
515 |
|
if (vb->length == 1) |
516 |
|
puts(strbuf_value(sb)); |
517 |
|
else |
518 |
|
put_lines(strbuf_value(sb), |
519 |
|
varray_assign(vb, 0, 0), vb->length); |
520 |
|
} |
521 |
|
strbuf_close(ib); |
522 |
|
strbuf_close(sb); |
523 |
|
varray_close(vb); |
524 |
exit(0); |
exit(0); |
525 |
} else if (do_relative || do_absolute) { |
} else if (do_relative || do_absolute) { |
526 |
/* |
/* |