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