ctags.c revision 97581
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 97581 2002-05-30 11:43:20Z tjr $"); 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(argc, argv) 90 int argc; 91 char **argv; 92{ 93 static const char *outfile = "tags"; /* output file */ 94 int aflag; /* -a: append to tags */ 95 int uflag; /* -u: update tags */ 96 int exit_val; /* exit value */ 97 int step; /* step through args */ 98 int ch; /* getopts char */ 99 char *cmd; 100 101 setlocale(LC_ALL, ""); 102 103 aflag = uflag = NO; 104 tflag = YES; 105 while ((ch = getopt(argc, argv, "BFTadf:tuwvx")) != -1) 106 switch(ch) { 107 case 'B': 108 searchar = '?'; 109 break; 110 case 'F': 111 searchar = '/'; 112 break; 113 case 'T': 114 tflag = NO; 115 break; 116 case 'a': 117 aflag++; 118 break; 119 case 'd': 120 dflag++; 121 break; 122 case 'f': 123 outfile = optarg; 124 break; 125 case 't': 126 tflag = YES; 127 break; 128 case 'u': 129 uflag++; 130 break; 131 case 'w': 132 wflag++; 133 break; 134 case 'v': 135 vflag++; 136 case 'x': 137 xflag++; 138 break; 139 case '?': 140 default: 141 usage(); 142 } 143 argv += optind; 144 argc -= optind; 145 if (!argc) 146 usage(); 147 148 if (!xflag) 149 setlocale(LC_COLLATE, "C"); 150 151 init(); 152 153 for (exit_val = step = 0; step < argc; ++step) 154 if (!(inf = fopen(argv[step], "r"))) { 155 warn("%s", argv[step]); 156 exit_val = 1; 157 } 158 else { 159 curfile = argv[step]; 160 find_entries(argv[step]); 161 (void)fclose(inf); 162 } 163 164 if (head) { 165 if (xflag) 166 put_entries(head); 167 else { 168 if (uflag) { 169 for (step = 0; step < argc; step++) { 170 (void)asprintf(&cmd, 171 "mv %s OTAGS; fgrep -v '\t%s\t' OTAGS >%s; rm OTAGS", 172 outfile, argv[step], outfile); 173 if (cmd == NULL) 174 err(1, "out of space"); 175 system(cmd); 176 free(cmd); 177 cmd = NULL; 178 } 179 ++aflag; 180 } 181 if (!(outf = fopen(outfile, aflag ? "a" : "w"))) 182 err(1, "%s", outfile); 183 put_entries(head); 184 (void)fclose(outf); 185 if (uflag) { 186 (void)asprintf(&cmd, "sort -o %s %s", 187 outfile, outfile); 188 if (cmd == NULL) 189 err(1, "out of space"); 190 system(cmd); 191 free(cmd); 192 cmd = NULL; 193 } 194 } 195 } 196 exit(exit_val); 197} 198 199static void 200usage() 201{ 202 (void)fprintf(stderr, "usage: ctags [-BFTaduwvx] [-f tagsfile] file ...\n"); 203 exit(1); 204} 205 206/* 207 * init -- 208 * this routine sets up the boolean pseudo-functions which work by 209 * setting boolean flags dependent upon the corresponding character. 210 * Every char which is NOT in that string is false with respect to 211 * the pseudo-function. Therefore, all of the array "_wht" is NO 212 * by default and then the elements subscripted by the chars in 213 * CWHITE are set to YES. Thus, "_wht" of a char is YES if it is in 214 * the string CWHITE, else NO. 215 */ 216void 217init() 218{ 219 int i; 220 const unsigned char *sp; 221 222 for (i = 0; i < 256; i++) { 223 _wht[i] = _etk[i] = _itk[i] = _btk[i] = NO; 224 _gd[i] = YES; 225 } 226#define CWHITE " \f\t\n" 227 for (sp = CWHITE; *sp; sp++) /* white space chars */ 228 _wht[*sp] = YES; 229#define CTOKEN " \t\n\"'#()[]{}=-+%*/&|^~!<>;,.:?" 230 for (sp = CTOKEN; *sp; sp++) /* token ending chars */ 231 _etk[*sp] = YES; 232#define CINTOK "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz0123456789" 233 for (sp = CINTOK; *sp; sp++) /* valid in-token chars */ 234 _itk[*sp] = YES; 235#define CBEGIN "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz" 236 for (sp = CBEGIN; *sp; sp++) /* token starting chars */ 237 _btk[*sp] = YES; 238#define CNOTGD ",;" 239 for (sp = CNOTGD; *sp; sp++) /* invalid after-function chars */ 240 _gd[*sp] = NO; 241} 242 243/* 244 * find_entries -- 245 * this routine opens the specified file and calls the function 246 * which searches the file. 247 */ 248void 249find_entries(file) 250 char *file; 251{ 252 char *cp; 253 254 lineno = 0; /* should be 1 ?? KB */ 255 if ((cp = strrchr(file, '.'))) { 256 if (cp[1] == 'l' && !cp[2]) { 257 int c; 258 259 for (;;) { 260 if (GETC(==, EOF)) 261 return; 262 if (!iswhite(c)) { 263 rewind(inf); 264 break; 265 } 266 } 267#define LISPCHR ";([" 268/* lisp */ if (strchr(LISPCHR, c)) { 269 l_entries(); 270 return; 271 } 272/* lex */ else { 273 /* 274 * we search all 3 parts of a lex file 275 * for C references. This may be wrong. 276 */ 277 toss_yysec(); 278 (void)strcpy(lbuf, "%%$"); 279 pfnote("yylex", lineno); 280 rewind(inf); 281 } 282 } 283/* yacc */ else if (cp[1] == 'y' && !cp[2]) { 284 /* 285 * we search only the 3rd part of a yacc file 286 * for C references. This may be wrong. 287 */ 288 toss_yysec(); 289 (void)strcpy(lbuf, "%%$"); 290 pfnote("yyparse", lineno); 291 y_entries(); 292 } 293/* fortran */ else if ((cp[1] != 'c' && cp[1] != 'h') && !cp[2]) { 294 if (PF_funcs()) 295 return; 296 rewind(inf); 297 } 298 } 299/* C */ c_entries(); 300} 301