4 * Ctags generates tags from preprocessing results.
6 * Copyright (C) 2006 Christopher Li
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
35 static struct symbol_list
*taglist
= NULL
;
37 static void examine_symbol(struct symbol
*sym
);
39 #define MAX(_x,_y) ((_x) > (_y) ? (_x) : (_y))
41 static int cmp_sym(const void *m
, const void *n
)
43 const struct ident
*a
= ((const struct symbol
*)m
)->ident
;
44 const struct ident
*b
= ((const struct symbol
*)n
)->ident
;
45 int ret
= strncmp(a
->name
, b
->name
, MAX(a
->len
, b
->len
));
47 const struct position a_pos
= ((const struct symbol
*)m
)->pos
;
48 const struct position b_pos
= ((const struct symbol
*)n
)->pos
;
50 ret
= strcmp(stream_name(a_pos
.stream
),
51 stream_name(b_pos
.stream
));
53 return a_pos
.line
< b_pos
.line
;
58 static void show_tag_header(FILE *fp
)
60 fprintf(fp
, "!_TAG_FILE_FORMAT\t2\t/extended format; --format=1 will not append ;\" to lines/\n");
61 fprintf(fp
, "!_TAG_FILE_SORTED\t0\t/0=unsorted, 1=sorted, 2=foldcase/\n");
62 fprintf(fp
, "!_TAG_PROGRAM_AUTHOR\tChristopher Li\t/sparse@chrisli.org/\n");
63 fprintf(fp
, "!_TAG_PROGRAM_NAME\tSparse Ctags\t//\n");
64 fprintf(fp
, "!_TAG_PROGRAM_URL\thttp://www.kernel.org/pub/software/devel/sparse/\t/official site/\n");
65 fprintf(fp
, "!_TAG_PROGRAM_VERSION\t0.01\t//\n");
68 static inline void show_symbol_tag(FILE *fp
, struct symbol
*sym
)
70 fprintf(fp
, "%s\t%s\t%d;\"\t%c\tfile:\n", show_ident(sym
->ident
),
71 stream_name(sym
->pos
.stream
), sym
->pos
.line
, (int)sym
->kind
);
74 static void show_tags(struct symbol_list
*list
)
77 struct ident
*ident
= NULL
;
78 struct position pos
= {};
79 static const char *filename
;
85 fp
= fopen("tags", "w");
87 perror("open tags file");
91 FOR_EACH_PTR(list
, sym
) {
92 if (ident
== sym
->ident
&& pos
.line
== sym
->pos
.line
&&
93 !strcmp(filename
, stream_name(sym
->pos
.stream
)))
96 show_symbol_tag(fp
, sym
);
99 filename
= stream_name(sym
->pos
.stream
);
100 } END_FOR_EACH_PTR(sym
);
104 static inline void add_tag(struct symbol
*sym
)
106 if (sym
->ident
&& !sym
->visited
) {
108 add_symbol(&taglist
, sym
);
112 static inline void examine_members(struct symbol_list
*list
)
116 FOR_EACH_PTR(list
, sym
) {
119 } END_FOR_EACH_PTR(sym
);
122 static void examine_symbol(struct symbol
*sym
)
124 struct symbol
*base
= sym
;
126 if (!sym
|| sym
->visited
)
128 if (sym
->ident
&& sym
->ident
->reserved
)
130 if (sym
->type
== SYM_KEYWORD
|| sym
->type
== SYM_PREPROCESSOR
)
134 base
= sym
->ctype
.base_type
;
138 if (base
->type
== SYM_FN
)
140 examine_symbol(base
);
144 examine_members(sym
->symbol_list
);
148 examine_members(sym
->symbol_list
);
157 examine_symbol(sym
->ctype
.base_type
);
163 die("unknown symbol %s namespace:%d type:%d\n", show_ident(sym
->ident
),
164 sym
->namespace, sym
->type
);
171 static void examine_namespace(struct symbol
*sym
)
175 if (sym
->ident
&& sym
->ident
->reserved
)
178 switch(sym
->namespace) {
180 case NS_PREPROCESSOR
:
196 die("unknown namespace %d symbol:%s type:%d\n", sym
->namespace,
197 show_ident(sym
->ident
), sym
->type
);
202 static inline void examine_symbol_list(struct symbol_list
*list
)
208 FOR_EACH_PTR(list
, sym
) {
209 examine_namespace(sym
);
210 } END_FOR_EACH_PTR(sym
);
213 int main(int argc
, char **argv
)
215 struct string_list
*filelist
= NULL
;
218 examine_symbol_list(sparse_initialize(argc
, argv
, &filelist
));
219 FOR_EACH_PTR_NOTAG(filelist
, file
) {
221 examine_symbol_list(file_scope
->symbols
);
222 } END_FOR_EACH_PTR_NOTAG(file
);
223 examine_symbol_list(global_scope
->symbols
);
224 sort_list((struct ptr_list
**)&taglist
, cmp_sym
);