5 #define LEN(a) (sizeof(a) / sizeof((a)[0]))
8 char *ext
; /* file extension */
9 int grp
; /* tag group in pat */
10 char *pat
; /* tag pattern */
11 char *loc
; /* optional tag location; may reference groups in pat */
13 {".c", 1, "^[a-zA-Z_].*\\<([a-zA-Z_][a-zA-Z_0-9]*)\\(.*[^;]$", "/^[a-zA-Z_].*\\<\\1\\>\\(.*[^;]$/"},
14 {".c", 1, "^#define +\\<([a-zA-Z_0-9]+)\\>", "/^#define +\\<(\\1)\\>/"},
15 {".go", 3, "^(func|var|const|type)( +\\([^()]+\\))? +([a-zA-Z_0-9]+)\\>", "/^\\1( +\\(.*\\))? +\\3\\>/"},
16 {".sh", 2, "^(function +)?([a-zA-Z_][a-zA-Z_0-9]*)(\\(\\))? *\\{", "/^\\1\\2(\\(\\))? *\\{$/"},
17 {".py", 2, "^(def|class) +([a-zA-Z_][a-zA-Z_0-9]*)\\>", "/^\\1 +\\2\\>/"},
18 {".ex", 2, "^[ \t]*(def|defp|defmodule)[ \t]+([a-zA-Z_0-9]+\\>[?!]?)", "/^[ \\t]*\\1[ \\t]+\\2\\>[?!]?/"},
21 static int tags_match(int idx
, char *path
)
23 int len
= strlen(tags
[idx
].ext
);
24 if (strlen(path
) > len
&& !strcmp(strchr(path
, '\0') - len
, tags
[idx
].ext
))
29 static void replace(char *dst
, char *rep
, char *ln
, regmatch_t
*subs
)
32 if (rep
[0] == '\\' && rep
[1]) {
33 if (rep
[1] >= '0' && rep
[1] <= '9') {
34 int grp
= rep
[1] - '0';
35 int beg
= subs
[grp
].rm_so
;
36 int end
= subs
[grp
].rm_eo
;
38 memcpy(dst
, ln
+ beg
, len
);
53 static int mktags(char *path
, regex_t
*re
, int grp
, char *rep
)
60 FILE *fp
= fopen(path
, "r");
63 while (fgets(ln
, sizeof(ln
), fp
) != NULL
) {
64 if (regexec(re
, ln
, LEN(grps
), grps
, 0) == 0) {
65 int len
= grps
[grp
].rm_eo
- grps
[grp
].rm_so
;
66 if (len
+ 1 > sizeof(tag
))
67 len
= sizeof(tag
) - 1;
68 memcpy(tag
, ln
+ grps
[grp
].rm_so
, len
);
71 replace(loc
, rep
, ln
, grps
);
73 sprintf(loc
, "%d", lnum
+ 1);
74 printf("%s\t%s\t%s\n", tag
, path
, loc
);
82 int main(int argc
, char *argv
[])
86 printf("usage: %s files >tags\n", argv
[0]);
89 for (i
= 1; i
< argc
; i
++) {
90 for (j
= 0; j
< LEN(tags
); j
++) {
92 if (tags_match(j
, argv
[i
]) != 0)
94 if (regcomp(&re
, tags
[j
].pat
, REG_EXTENDED
) != 0) {
95 fprintf(stderr
, "mktags: bad pattern %s\n", tags
[j
].pat
);
98 if (mktags(argv
[i
], &re
, tags
[j
].grp
, tags
[j
].loc
))
99 fprintf(stderr
, "mktags: failed to read %s\n", argv
[i
]);