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