Annotation of src/usr.bin/ctags/ctags.c, Revision 1.16
1.16 ! semarie 1: /* $OpenBSD: ctags.c,v 1.15 2015/02/08 23:40:34 deraadt 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: #include <err.h>
34: #include <limits.h>
35: #include <stdio.h>
36: #include <string.h>
37: #include <stdlib.h>
38: #include <unistd.h>
39:
40: #include "ctags.h"
41:
42: /*
43: * ctags: create a tags file
44: */
45:
46: NODE *head; /* head of the sorted binary tree */
47:
48: /* boolean "func" (see init()) */
1.14 tobias 49: bool _wht[256], _itk[256], _btk[256];
1.1 deraadt 50:
51: FILE *inf; /* ioptr for current input file */
52: FILE *outf; /* ioptr for tags file */
53:
54: long lineftell; /* ftell after getc( inf ) == '\n' */
55:
56: int lineno; /* line number of current line */
57: int dflag; /* -d: non-macro defines */
58: int vflag; /* -v: vgrind style index output */
59: int wflag; /* -w: suppress warnings */
60: int xflag; /* -x: cxref style output */
61:
62: char *curfile; /* current input file name */
63: char searchar = '/'; /* use /.../ searches by default */
64: char lbuf[LINE_MAX];
65:
1.6 millert 66: void init(void);
67: void find_entries(char *);
1.16 ! semarie 68: void preload_entries(char *, int, char *[]);
1.1 deraadt 69:
70: int
1.10 deraadt 71: main(int argc, char *argv[])
1.1 deraadt 72: {
73: static char *outfile = "tags"; /* output file */
74: int aflag; /* -a: append to tags */
75: int uflag; /* -u: update tags */
76: int exit_val; /* exit value */
77: int step; /* step through args */
78: int ch; /* getopts char */
79:
80: aflag = uflag = NO;
1.3 millert 81: while ((ch = getopt(argc, argv, "BFadf:tuwvx")) != -1)
1.1 deraadt 82: switch(ch) {
83: case 'B':
84: searchar = '?';
85: break;
86: case 'F':
87: searchar = '/';
88: break;
89: case 'a':
1.15 deraadt 90: aflag = 1;
1.1 deraadt 91: break;
92: case 'd':
1.15 deraadt 93: dflag = 1;
1.1 deraadt 94: break;
95: case 'f':
96: outfile = optarg;
97: break;
98: case 't':
1.13 millert 99: /* backwards compatibility */
1.1 deraadt 100: break;
101: case 'u':
1.15 deraadt 102: uflag = 1;
1.1 deraadt 103: break;
104: case 'w':
1.15 deraadt 105: wflag = 1;
1.1 deraadt 106: break;
107: case 'v':
1.15 deraadt 108: vflag = 1;
1.1 deraadt 109: case 'x':
1.15 deraadt 110: xflag = 1;
1.1 deraadt 111: break;
112: case '?':
113: default:
114: goto usage;
115: }
116: argv += optind;
117: argc -= optind;
118: if (!argc) {
119: usage: (void)fprintf(stderr,
1.13 millert 120: "usage: ctags [-aBdFuvwx] [-f tagsfile] file ...\n");
1.1 deraadt 121: exit(1);
122: }
123:
124: init();
1.16 ! semarie 125: if (uflag && !vflag && !xflag)
! 126: preload_entries(outfile, argc, argv);
1.1 deraadt 127:
128: for (exit_val = step = 0; step < argc; ++step)
129: if (!(inf = fopen(argv[step], "r"))) {
130: warn("%s", argv[step]);
131: exit_val = 1;
132: }
133: else {
134: curfile = argv[step];
135: find_entries(argv[step]);
136: (void)fclose(inf);
137: }
138:
1.4 deraadt 139: if (head) {
1.1 deraadt 140: if (xflag)
141: put_entries(head);
142: else {
143: if (!(outf = fopen(outfile, aflag ? "a" : "w")))
144: err(exit_val, "%s", outfile);
145: put_entries(head);
146: (void)fclose(outf);
147: }
1.4 deraadt 148: }
1.1 deraadt 149: exit(exit_val);
150: }
151:
152: /*
153: * init --
154: * this routine sets up the boolean psuedo-functions which work by
155: * setting boolean flags dependent upon the corresponding character.
156: * Every char which is NOT in that string is false with respect to
157: * the pseudo-function. Therefore, all of the array "_wht" is NO
158: * by default and then the elements subscripted by the chars in
159: * CWHITE are set to YES. Thus, "_wht" of a char is YES if it is in
160: * the string CWHITE, else NO.
161: */
162: void
1.10 deraadt 163: init(void)
1.1 deraadt 164: {
165: int i;
166: unsigned char *sp;
167:
1.14 tobias 168: for (i = 0; i < 256; i++)
169: _wht[i] = _itk[i] = _btk[i] = NO;
1.1 deraadt 170: #define CWHITE " \f\t\n"
171: for (sp = CWHITE; *sp; sp++) /* white space chars */
172: _wht[*sp] = YES;
173: #define CINTOK "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz0123456789"
174: for (sp = CINTOK; *sp; sp++) /* valid in-token chars */
175: _itk[*sp] = YES;
176: #define CBEGIN "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"
177: for (sp = CBEGIN; *sp; sp++) /* token starting chars */
178: _btk[*sp] = YES;
179: }
180:
181: /*
182: * find_entries --
183: * this routine opens the specified file and calls the function
184: * which searches the file.
185: */
186: void
1.10 deraadt 187: find_entries(char *file)
1.1 deraadt 188: {
189: char *cp;
190:
191: lineno = 0; /* should be 1 ?? KB */
1.5 deraadt 192: if ((cp = strrchr(file, '.'))) {
1.1 deraadt 193: if (cp[1] == 'l' && !cp[2]) {
194: int c;
195:
196: for (;;) {
197: if (GETC(==, EOF))
198: return;
199: if (!iswhite(c)) {
200: rewind(inf);
201: break;
202: }
203: }
204: #define LISPCHR ";(["
205: /* lisp */ if (strchr(LISPCHR, c)) {
206: l_entries();
207: return;
208: }
209: /* lex */ else {
210: /*
211: * we search all 3 parts of a lex file
212: * for C references. This may be wrong.
213: */
214: toss_yysec();
1.7 deraadt 215: (void)strlcpy(lbuf, "%%$", sizeof lbuf);
1.1 deraadt 216: pfnote("yylex", lineno);
217: rewind(inf);
218: }
219: }
220: /* yacc */ else if (cp[1] == 'y' && !cp[2]) {
221: /*
222: * we search only the 3rd part of a yacc file
223: * for C references. This may be wrong.
224: */
225: toss_yysec();
1.7 deraadt 226: (void)strlcpy(lbuf, "%%$", sizeof lbuf);
1.1 deraadt 227: pfnote("yyparse", lineno);
228: y_entries();
229: }
230: /* fortran */ else if ((cp[1] != 'c' && cp[1] != 'h') && !cp[2]) {
231: if (PF_funcs())
232: return;
233: rewind(inf);
234: }
235: }
236: /* C */ c_entries();
1.16 ! semarie 237: }
! 238:
! 239: void
! 240: preload_entries(char *tagsfile, int argc, char *argv[])
! 241: {
! 242: FILE *fp;
! 243: char line[LINE_MAX];
! 244: char *entry = NULL;
! 245: char *file = NULL;
! 246: char *pattern = NULL;
! 247: char *eol;
! 248: int i;
! 249:
! 250: in_preload = YES;
! 251:
! 252: if ((fp = fopen(tagsfile, "r")) == NULL)
! 253: err(1, "preload_entries: %s", tagsfile);
! 254:
! 255: while (1) {
! 256: next:
! 257: if (fgets(line, sizeof(line), fp) == NULL)
! 258: break;
! 259:
! 260: if ((eol = strchr(line, '\n')) == NULL)
! 261: errx(1, "preload_entries: line too long");
! 262: *eol = '\0';
! 263:
! 264: /* extract entry */
! 265: entry = line;
! 266: if ((file = strchr(line, '\t')) == NULL)
! 267: errx(1, "preload_entries: couldn't parse entry: %s",
! 268: tagsfile);
! 269: *file = '\0';
! 270:
! 271: /* extract file */
! 272: file++;
! 273: if ((pattern = strchr(file, '\t')) == NULL)
! 274: errx(1, "preload_entries: couldn't parse filename: %s",
! 275: tagsfile);
! 276: *pattern = '\0';
! 277:
! 278: /* skip this file ? */
! 279: for(i = 0; i < argc; i++)
! 280: if (strcmp(file, argv[i]) == 0)
! 281: goto next;
! 282:
! 283: /* rest of string is pattern */
! 284: pattern++;
! 285:
! 286: /* grab searchar, and don't keep it around the pattern */
! 287: if ((pattern[0] == '/' || pattern[0] == '?')
! 288: && pattern[1] == '^') {
! 289:
! 290: i = strlen(pattern);
! 291: if (pattern[i-1] == pattern[0])
! 292: /* remove searchar at end */
! 293: pattern[i-1] = '\0';
! 294: else
! 295: errx(1, "preload_entries: couldn't parse "
! 296: "pattern: %s", tagsfile);
! 297:
! 298: /* remove searchar at begin */
! 299: pattern += 2;
! 300: }
! 301:
! 302: /* add entry */
! 303: if ((curfile = strdup(file)) == NULL)
! 304: err(1, "preload_entries: strdup");
! 305: (void)strlcpy(lbuf, pattern, sizeof(lbuf));
! 306: pfnote(entry, 0);
! 307: }
! 308: if (ferror(fp))
! 309: err(1, "preload_entries: fgets");
! 310:
! 311: (void)fclose(fp);
! 312: in_preload = NO;
1.1 deraadt 313: }