1 | /* |
---|
2 | * Copyright (c) 1987 The Regents of the University of California. |
---|
3 | * All rights reserved. |
---|
4 | * |
---|
5 | * Redistribution and use in source and binary forms, with or without |
---|
6 | * modification, are permitted provided that the following conditions |
---|
7 | * are met: |
---|
8 | * 1. Redistributions of source code must retain the above copyright |
---|
9 | * notice, this list of conditions and the following disclaimer. |
---|
10 | * 2. Redistributions in binary form must reproduce the above copyright |
---|
11 | * notice, this list of conditions and the following disclaimer in the |
---|
12 | * documentation and/or other materials provided with the distribution. |
---|
13 | * 3. All advertising materials mentioning features or use of this software |
---|
14 | * must display the following acknowledgement: |
---|
15 | * This product includes software developed by the University of |
---|
16 | * California, Berkeley and its contributors. |
---|
17 | * 4. Neither the name of the University nor the names of its contributors |
---|
18 | * may be used to endorse or promote products derived from this software |
---|
19 | * without specific prior written permission. |
---|
20 | * |
---|
21 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
---|
22 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
---|
23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
---|
24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
---|
25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
---|
26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
---|
27 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
---|
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
---|
29 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
---|
30 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
---|
31 | * SUCH DAMAGE. |
---|
32 | */ |
---|
33 | |
---|
34 | #ifndef lint |
---|
35 | char copyright[] = |
---|
36 | "@(#) Copyright (c) 1987 The Regents of the University of California.\n\ |
---|
37 | All rights reserved.\n"; |
---|
38 | #endif /* not lint */ |
---|
39 | |
---|
40 | #ifndef lint |
---|
41 | static char sccsid[] = "@(#)ctags.c 5.8 (Berkeley) 2/26/91"; |
---|
42 | #endif /* not lint */ |
---|
43 | |
---|
44 | #include <stdio.h> |
---|
45 | #include <string.h> |
---|
46 | #include <stdlib.h> |
---|
47 | #include "ctags.h" |
---|
48 | |
---|
49 | /* |
---|
50 | * ctags: create a tags file |
---|
51 | */ |
---|
52 | |
---|
53 | NODE *head; /* head of the sorted binary tree */ |
---|
54 | |
---|
55 | /* boolean "func" (see init()) */ |
---|
56 | bool _wht[0177],_etk[0177],_itk[0177],_btk[0177],_gd[0177]; |
---|
57 | |
---|
58 | FILE *inf, /* ioptr for current input file */ |
---|
59 | *outf; /* ioptr for tags file */ |
---|
60 | |
---|
61 | long lineftell; /* ftell after getc( inf ) == '\n' */ |
---|
62 | |
---|
63 | int lineno, /* line number of current line */ |
---|
64 | dflag, /* -d: non-macro defines */ |
---|
65 | tflag, /* -t: create tags for typedefs */ |
---|
66 | wflag, /* -w: suppress warnings */ |
---|
67 | vflag, /* -v: vgrind style index output */ |
---|
68 | xflag, /* -x: cxref style output */ |
---|
69 | yflag; /* -y: yet another style output */ |
---|
70 | |
---|
71 | char *curfile, /* current input file name */ |
---|
72 | searchar = '/', /* use /.../ searches by default */ |
---|
73 | lbuf[BUFSIZ]; |
---|
74 | |
---|
75 | main(argc,argv) |
---|
76 | int argc; |
---|
77 | char **argv; |
---|
78 | { |
---|
79 | extern char *optarg; /* getopt arguments */ |
---|
80 | extern int optind; |
---|
81 | static char *outfile = "tags"; /* output file */ |
---|
82 | int aflag, /* -a: append to tags */ |
---|
83 | uflag, /* -u: update tags */ |
---|
84 | exit_val, /* exit value */ |
---|
85 | step, /* step through args */ |
---|
86 | ch; /* getopts char */ |
---|
87 | char cmd[100]; /* too ugly to explain */ |
---|
88 | |
---|
89 | aflag = uflag = NO; |
---|
90 | while ((ch = getopt(argc,argv,"BFadf:tuwvxy")) != EOF) |
---|
91 | switch((char)ch) { |
---|
92 | case 'B': |
---|
93 | searchar = '?'; |
---|
94 | break; |
---|
95 | case 'F': |
---|
96 | searchar = '/'; |
---|
97 | break; |
---|
98 | case 'a': |
---|
99 | aflag++; |
---|
100 | break; |
---|
101 | case 'd': |
---|
102 | dflag++; |
---|
103 | break; |
---|
104 | case 'f': |
---|
105 | outfile = optarg; |
---|
106 | break; |
---|
107 | case 't': |
---|
108 | tflag++; |
---|
109 | break; |
---|
110 | case 'u': |
---|
111 | uflag++; |
---|
112 | break; |
---|
113 | case 'w': |
---|
114 | wflag++; |
---|
115 | break; |
---|
116 | case 'v': |
---|
117 | vflag++; |
---|
118 | case 'x': |
---|
119 | xflag++; |
---|
120 | break; |
---|
121 | case 'y': |
---|
122 | yflag++; |
---|
123 | break; |
---|
124 | case '?': |
---|
125 | default: |
---|
126 | goto usage; |
---|
127 | } |
---|
128 | argv += optind; |
---|
129 | argc -= optind; |
---|
130 | if (!argc) { |
---|
131 | usage: puts("Usage: ctags [-BFadtuwvx] [-f tagsfile] file ..."); |
---|
132 | exit(1); |
---|
133 | } |
---|
134 | |
---|
135 | init(); |
---|
136 | |
---|
137 | for (exit_val = step = 0;step < argc;++step) |
---|
138 | if (!(inf = fopen(argv[step],"r"))) { |
---|
139 | perror(argv[step]); |
---|
140 | exit_val = 1; |
---|
141 | } |
---|
142 | else { |
---|
143 | curfile = argv[step]; |
---|
144 | find_entries(argv[step]); |
---|
145 | (void)fclose(inf); |
---|
146 | } |
---|
147 | |
---|
148 | if (head) |
---|
149 | if (xflag) |
---|
150 | put_entries(head); |
---|
151 | else { |
---|
152 | if (uflag) { |
---|
153 | for (step = 0;step < argc;step++) { |
---|
154 | (void)sprintf(cmd,"mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",outfile,argv[step],outfile); |
---|
155 | system(cmd); |
---|
156 | } |
---|
157 | ++aflag; |
---|
158 | } |
---|
159 | if (!(outf = fopen(outfile, aflag ? "a" : "w"))) { |
---|
160 | perror(outfile); |
---|
161 | exit(exit_val); |
---|
162 | } |
---|
163 | put_entries(head); |
---|
164 | (void)fclose(outf); |
---|
165 | if (uflag) { |
---|
166 | (void)sprintf(cmd,"sort %s -o %s",outfile,outfile); |
---|
167 | system(cmd); |
---|
168 | } |
---|
169 | } |
---|
170 | exit(exit_val); |
---|
171 | } |
---|
172 | |
---|
173 | /* |
---|
174 | * init -- |
---|
175 | * this routine sets up the boolean psuedo-functions which work by |
---|
176 | * setting boolean flags dependent upon the corresponding character. |
---|
177 | * Every char which is NOT in that string is false with respect to |
---|
178 | * the pseudo-function. Therefore, all of the array "_wht" is NO |
---|
179 | * by default and then the elements subscripted by the chars in |
---|
180 | * CWHITE are set to YES. Thus, "_wht" of a char is YES if it is in |
---|
181 | * the string CWHITE, else NO. |
---|
182 | */ |
---|
183 | init() |
---|
184 | { |
---|
185 | register int i; |
---|
186 | register char *sp; |
---|
187 | |
---|
188 | for (i = 0; i < 0177; i++) { |
---|
189 | _wht[i] = _etk[i] = _itk[i] = _btk[i] = NO; |
---|
190 | _gd[i] = YES; |
---|
191 | } |
---|
192 | #define CWHITE " \f\t\n" |
---|
193 | for (sp = CWHITE; *sp; sp++) /* white space chars */ |
---|
194 | _wht[*sp] = YES; |
---|
195 | #define CTOKEN " \t\n\"'#()[]{}=-+%*/&|^~!<>;,.:?" |
---|
196 | for (sp = CTOKEN; *sp; sp++) /* token ending chars */ |
---|
197 | _etk[*sp] = YES; |
---|
198 | #define CINTOK "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz0123456789" |
---|
199 | for (sp = CINTOK; *sp; sp++) /* valid in-token chars */ |
---|
200 | _itk[*sp] = YES; |
---|
201 | #define CBEGIN "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz" |
---|
202 | for (sp = CBEGIN; *sp; sp++) /* token starting chars */ |
---|
203 | _btk[*sp] = YES; |
---|
204 | #define CNOTGD ",;" |
---|
205 | for (sp = CNOTGD; *sp; sp++) /* invalid after-function chars */ |
---|
206 | _gd[*sp] = NO; |
---|
207 | } |
---|
208 | |
---|
209 | /* |
---|
210 | * find_entries -- |
---|
211 | * this routine opens the specified file and calls the function |
---|
212 | * which searches the file. |
---|
213 | */ |
---|
214 | find_entries(file) |
---|
215 | char *file; |
---|
216 | { |
---|
217 | register char *cp; |
---|
218 | |
---|
219 | lineno = 0; /* should be 1 ?? KB */ |
---|
220 | if (cp = rindex(file, '.')) { |
---|
221 | if (cp[1] == 'l' && !cp[2]) { |
---|
222 | register int c; |
---|
223 | |
---|
224 | for (;;) { |
---|
225 | if (GETC(==,EOF)) |
---|
226 | return; |
---|
227 | if (!iswhite(c)) { |
---|
228 | rewind(inf); |
---|
229 | break; |
---|
230 | } |
---|
231 | } |
---|
232 | #define LISPCHR ";([" |
---|
233 | /* lisp */ if (index(LISPCHR,(char)c)) { |
---|
234 | l_entries(); |
---|
235 | return; |
---|
236 | } |
---|
237 | /* lex */ else { |
---|
238 | /* |
---|
239 | * we search all 3 parts of a lex file |
---|
240 | * for C references. This may be wrong. |
---|
241 | */ |
---|
242 | toss_yysec(); |
---|
243 | (void)strcpy(lbuf,"%%$"); |
---|
244 | pfnote("yylex",lineno); |
---|
245 | rewind(inf); |
---|
246 | } |
---|
247 | } |
---|
248 | /* yacc */ else if (cp[1] == 'y' && !cp[2]) { |
---|
249 | /* |
---|
250 | * we search only the 3rd part of a yacc file |
---|
251 | * for C references. This may be wrong. |
---|
252 | */ |
---|
253 | toss_yysec(); |
---|
254 | (void)strcpy(lbuf,"%%$"); |
---|
255 | pfnote("yyparse",lineno); |
---|
256 | y_entries(); |
---|
257 | } |
---|
258 | /* fortran */ else if ((cp[1] != 'c' && cp[1] != 'h') && !cp[2]) { |
---|
259 | if (PF_funcs()) |
---|
260 | return; |
---|
261 | rewind(inf); |
---|
262 | } |
---|
263 | } |
---|
264 | /* C */ c_entries(); |
---|
265 | } |
---|