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