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