4 * Ctags generates tags from preprocessing results.
6 * Copyright (C) 2006 Christopher Li
8 * Licensed under the Open Software License version 1.1
19 static struct symbol_list
*taglist
= NULL
;
21 static void examine_symbol(struct symbol
*sym
);
23 #define MAX(_x,_y) ((_x) > (_y) ? (_x) : (_y))
25 static int cmp_sym(const void *m
, const void *n
)
27 struct ident
*a
= ((struct symbol
*)m
)->ident
;
28 struct ident
*b
= ((struct symbol
*)n
)->ident
;
29 int ret
= strncmp(a
->name
, b
->name
, MAX(a
->len
, b
->len
));
31 struct position a
= ((struct symbol
*)m
)->pos
;
32 struct position b
= ((struct symbol
*)n
)->pos
;
34 ret
= strcmp(stream_name(a
.stream
), stream_name(b
.stream
));
36 return a
.line
< b
.line
;
41 static void show_tag_header(FILE *fp
)
43 fprintf(fp
, "!_TAG_FILE_FORMAT\t2\t/extended format; --format=1 will not append ;\" to lines/\n");
44 fprintf(fp
, "!_TAG_FILE_SORTED\t0\t/0=unsorted, 1=sorted, 2=foldcase/\n");
45 fprintf(fp
, "!_TAG_PROGRAM_AUTHOR\tChristopher Li\t/sparse@chrisli.org/\n");
46 fprintf(fp
, "!_TAG_PROGRAM_NAME\tSparse Ctags\t//\n");
47 fprintf(fp
, "!_TAG_PROGRAM_URL\thttp://kernel.org/pub/linux/kernel/people/josh/sparse/\t/official site/\n");
48 fprintf(fp
, "!_TAG_PROGRAM_VERSION\t0.01\t//\n");
51 static inline void show_symbol_tag(FILE *fp
, struct symbol
*sym
)
53 fprintf(fp
, "%s\t%s\t%d;\"\t%c\tfile:\n", show_ident(sym
->ident
),
54 stream_name(sym
->pos
.stream
), sym
->pos
.line
, (int)sym
->kind
);
57 static void show_tags(struct symbol_list
*list
)
60 struct ident
*ident
= NULL
;
61 struct position pos
= {};
62 static const char *filename
;
68 fp
= fopen("tags", "w");
70 perror("open tags file");
74 FOR_EACH_PTR(list
, sym
) {
75 if (ident
== sym
->ident
&& pos
.line
== sym
->pos
.line
&&
76 !strcmp(filename
, stream_name(sym
->pos
.stream
)))
79 show_symbol_tag(fp
, sym
);
82 filename
= stream_name(sym
->pos
.stream
);
83 } END_FOR_EACH_PTR(sym
);
87 static inline void add_tag(struct symbol
*sym
)
89 if (sym
->ident
&& !sym
->visited
) {
91 add_symbol(&taglist
, sym
);
95 static inline void examine_members(struct symbol_list
*list
)
99 FOR_EACH_PTR(list
, sym
) {
102 } END_FOR_EACH_PTR(sym
);
105 static void examine_symbol(struct symbol
*sym
)
107 struct symbol
*base
= sym
;
109 if (!sym
|| sym
->visited
)
111 if (sym
->ident
&& sym
->ident
->reserved
)
115 base
= sym
->ctype
.base_type
;
119 if (base
->type
== SYM_FN
)
121 examine_symbol(base
);
125 examine_members(sym
->symbol_list
);
129 examine_members(sym
->symbol_list
);
138 examine_symbol(sym
->ctype
.base_type
);
144 die("unknown symbol %s namespace:%d type:%d\n", show_ident(sym
->ident
),
145 sym
->namespace, sym
->type
);
152 static void examine_namespace(struct symbol
*sym
)
156 if (sym
->ident
&& sym
->ident
->reserved
)
159 switch(sym
->namespace) {
163 case NS_PREPROCESSOR
:
176 die("unknown namespace %d symbol:%s type:%d\n", sym
->namespace,
177 show_ident(sym
->ident
), sym
->type
);
182 static inline void examine_symbol_list(struct symbol_list
*list
)
188 FOR_EACH_PTR(list
, sym
) {
189 examine_namespace(sym
);
190 } END_FOR_EACH_PTR(sym
);
193 int main(int argc
, char **argv
)
195 struct string_list
*filelist
= NULL
;
198 examine_symbol_list(sparse_initialize(argc
, argv
, &filelist
));
199 FOR_EACH_PTR_NOTAG(filelist
, file
) {
201 examine_symbol_list(file_scope
->symbols
);
202 } END_FOR_EACH_PTR_NOTAG(file
);
203 examine_symbol_list(global_scope
->symbols
);
204 sort_list((struct ptr_list
**)&taglist
, cmp_sym
);