date and time created 87/03/16 18:00:32 by bostic
[unix-history] / usr / src / usr.bin / ctags / ctags.c
... / ...
CommitLineData
1/*
2 * Copyright (c) 1987 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 */
6
7#ifndef lint
8char copyright[] =
9"@(#) Copyright (c) 1987 Regents of the University of California.\n\
10 All rights reserved.\n";
11#endif not lint
12
13#ifndef lint
14static char sccsid[] = "@(#)ctags.c 5.3 (Berkeley) %G%";
15#endif not lint
16
17#include <ctags.h>
18#include <strings.h>
19
20/*
21 * ctags: create a tags file
22 */
23
24NODE *head; /* head of the sorted binary tree */
25
26 /* boolean "func" (see init()) */
27bool _wht[0177],_etk[0177],_itk[0177],_btk[0177],_gd[0177];
28
29FILE *inf, /* ioptr for current input file */
30 *outf; /* ioptr for tags file */
31
32long lineftell; /* ftell after getc( inf ) == '\n' */
33
34int lineno, /* line number of current line */
35 dflag, /* -d: non-macro defines */
36 tflag, /* -t: create tags for typedefs */
37 wflag, /* -w: suppress warnings */
38 vflag, /* -v: vgrind style index output */
39 xflag; /* -x: cxref style output */
40
41char *curfile, /* current input file name */
42 searchar = '/', /* use /.../ searches by default */
43 lbuf[BUFSIZ];
44
45main(argc,argv)
46 int argc;
47 char **argv;
48{
49 extern char *optarg; /* getopt arguments */
50 extern int optind;
51 static char *outfile = "tags"; /* output file */
52 int aflag, /* -a: append to tags */
53 uflag, /* -u: update tags */
54 exit_val, /* exit value */
55 step, /* step through args */
56 ch; /* getopts char */
57 char cmd[100]; /* too ugly to explain */
58
59 aflag = uflag = NO;
60 while ((ch = getopt(argc,argv,"BFadf:tuwvx")) != EOF)
61 switch((char)ch) {
62 case 'B':
63 searchar = '?';
64 break;
65 case 'F':
66 searchar = '/';
67 break;
68 case 'a':
69 aflag++;
70 break;
71 case 'd':
72 dflag++;
73 break;
74 case 'f':
75 outfile = optarg;
76 break;
77 case 't':
78 tflag++;
79 break;
80 case 'u':
81 uflag++;
82 break;
83 case 'w':
84 wflag++;
85 break;
86 case 'v':
87 vflag++;
88 case 'x':
89 xflag++;
90 break;
91 case '?':
92 default:
93 goto usage;
94 }
95 argv += optind;
96 argc -= optind;
97 if (!argc) {
98usage: puts("Usage: ctags [-BFadtuwvx] [-f tagsfile] file ...");
99 exit(1);
100 }
101
102 init();
103
104 for (exit_val = step = 0;step < argc;++step)
105 if (!(inf = fopen(argv[step],"r"))) {
106 perror(argv[step]);
107 exit_val = 1;
108 }
109 else {
110 curfile = argv[step];
111 find_entries(argv[step]);
112 (void)fclose(inf);
113 }
114
115 if (head)
116 if (xflag)
117 put_entries(head);
118 else {
119 if (uflag) {
120 for (step = 0;step < argc;step++) {
121 (void)sprintf(cmd,"mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",outfile,argv[step],outfile);
122 system(cmd);
123 }
124 ++aflag;
125 }
126 if (!(outf = fopen(outfile, aflag ? "a" : "w"))) {
127 perror(outfile);
128 exit(exit_val);
129 }
130 put_entries(head);
131 (void)fclose(outf);
132 if (uflag) {
133 (void)sprintf(cmd,"sort %s -o %s",outfile,outfile);
134 system(cmd);
135 }
136 }
137 exit(exit_val);
138}
139
140/*
141 * init --
142 * this routine sets up the boolean psuedo-functions which work by
143 * setting boolean flags dependent upon the corresponding character.
144 * Every char which is NOT in that string is false with respect to
145 * the pseudo-function. Therefore, all of the array "_wht" is NO
146 * by default and then the elements subscripted by the chars in
147 * CWHITE are set to YES. Thus, "_wht" of a char is YES if it is in
148 * the string CWHITE, else NO.
149 */
150init()
151{
152 register int i;
153 register char *sp;
154
155 for (i = 0; i < 0177; i++) {
156 _wht[i] = _etk[i] = _itk[i] = _btk[i] = NO;
157 _gd[i] = YES;
158 }
159#define CWHITE " \f\t\n"
160 for (sp = CWHITE; *sp; sp++) /* white space chars */
161 _wht[*sp] = YES;
162#define CTOKEN " \t\n\"'#()[]{}=-+%*/&|^~!<>;,.:?"
163 for (sp = CTOKEN; *sp; sp++) /* token ending chars */
164 _etk[*sp] = YES;
165#define CINTOK "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz0123456789"
166 for (sp = CINTOK; *sp; sp++) /* valid in-token chars */
167 _itk[*sp] = YES;
168#define CBEGIN "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"
169 for (sp = CBEGIN; *sp; sp++) /* token starting chars */
170 _btk[*sp] = YES;
171#define CNOTGD ",;"
172 for (sp = CNOTGD; *sp; sp++) /* invalid after-function chars */
173 _gd[*sp] = NO;
174}
175
176/*
177 * find_entries --
178 * this routine opens the specified file and calls the function
179 * which searches the file.
180 */
181find_entries(file)
182 char *file;
183{
184 register char *cp;
185
186 lineno = 0; /* should be 1 ?? KB */
187 if (cp = rindex(file, '.')) {
188 if (cp[1] == 'l' && !cp[2]) {
189 register int c;
190
191 for (;;) {
192 if (GETC(==,EOF))
193 return;
194 if (!iswhite(c)) {
195 rewind(inf);
196 break;
197 }
198 }
199#define LISPCHR ";(["
200/* lisp */ if (index(LISPCHR,(char)c)) {
201 l_entries();
202 return;
203 }
204/* lex */ else {
205 /*
206 * we search all 3 parts of a lex file
207 * for C references. This may be wrong.
208 */
209 (void)strcpy(lbuf,"%%$");
210 pfnote("yylex",0);
211 }
212 }
213/* yacc */ else if (cp[1] == 'y' && !cp[2]) {
214 /*
215 * we search only the 3rd part of a yacc file
216 * for C references. This may be wrong.
217 */
218 toss_yysec();
219 y_entries();
220 }
221/* fortran */ else if ((cp[1] != 'c' && cp[1] != 'h') && !cp[2]) {
222 if (PF_funcs())
223 return;
224 rewind(inf);
225 }
226 }
227/* C */ c_entries();
228}