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