Home | History | Annotate | Download | only in cscope-fast
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License, Version 1.0 only
      6  * (the "License").  You may not use this file except in compliance
      7  * with the License.
      8  *
      9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
     10  * or http://www.opensolaris.org/os/licensing.
     11  * See the License for the specific language governing permissions
     12  * and limitations under the License.
     13  *
     14  * When distributing Covered Code, include this CDDL HEADER in each
     15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     16  * If applicable, add the following below this CDDL HEADER, with the
     17  * fields enclosed by brackets "[]" replaced with your own identifying
     18  * information: Portions Copyright [yyyy] [name of copyright owner]
     19  *
     20  * CDDL HEADER END
     21  */
     22 /*	Copyright (c) 1988 AT&T	*/
     23 /*	  All Rights Reserved  	*/
     24 
     25 
     26 /*
     27  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
     28  * Use is subject to license terms.
     29  */
     30 
     31 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     32 
     33 /*
     34  *	cscope - interactive C symbol cross-reference
     35  *
     36  *	directory searching functions
     37  */
     38 
     39 #include <sys/types.h>	/* needed by stat.h */
     40 #include <sys/stat.h>	/* stat */
     41 #include "global.h"
     42 #include "dirent.h"
     43 #include "vp.h"		/* vpdirs and vpndirs */
     44 
     45 #define	DIRSEPS	" ,:"	/* directory list separators */
     46 #define	DIRINC	10	/* directory list size increment */
     47 #define	HASHMOD	2003	/* must be a prime number */
     48 #define	SRCINC	HASHMOD	/* source file list size increment */
     49 			/* largest known database had 22049 files */
     50 
     51 char	**incdirs;		/* #include directories */
     52 char	**srcdirs;		/* source directories */
     53 char	**srcfiles;		/* source files */
     54 int	nincdirs;		/* number of #include directories */
     55 int	mincdirs = DIRINC;	/* maximum number of #include directories */
     56 int	nsrcdirs;		/* number of source directories */
     57 int	msrcdirs = DIRINC;	/* maximum number of source directories */
     58 int	nsrcfiles;		/* number of source files */
     59 int	msrcfiles = SRCINC;	/* maximum number of source files */
     60 
     61 static	struct	listitem {	/* source file table entry */
     62 	char	*file;
     63 	struct	listitem *next;
     64 } *srcfiletable[HASHMOD];
     65 
     66 
     67 static void getsrcfiles(char *vpdir, char *dir);
     68 static BOOL issrcfile(char *file);
     69 
     70 /* add a source directory to the list for each view path source directory */
     71 
     72 void
     73 sourcedir(char *dirlist)
     74 {
     75 	struct	stat	statstruct;
     76 	char	*dir;
     77 
     78 	/* don't change environment variable text */
     79 	dirlist = stralloc(dirlist);
     80 
     81 	/* parse the directory list */
     82 	dir = strtok(dirlist, DIRSEPS);
     83 	while (dir != NULL) {
     84 		/*
     85 		 * make sure it is a directory (must exist in current
     86 		 * view path node)
     87 		 */
     88 		if (stat(compath(dir), &statstruct) == 0 &&
     89 		    S_ISDIR(statstruct.st_mode)) {
     90 			if (srcdirs == NULL) {
     91 				srcdirs = mymalloc(msrcdirs * sizeof (char *));
     92 			} else if (nsrcdirs == msrcdirs) {
     93 				msrcdirs += DIRINC;
     94 				srcdirs = myrealloc(srcdirs,
     95 				    msrcdirs * sizeof (char *));
     96 			}
     97 			srcdirs[nsrcdirs++] = stralloc(dir);
     98 		}
     99 		dir = strtok((char *)NULL, DIRSEPS);
    100 	}
    101 }
    102 
    103 /* add a #include directory to the list for each view path source directory */
    104 
    105 void
    106 includedir(char *dirlist)
    107 {
    108 	struct	stat	statstruct;
    109 	char	*dir;
    110 
    111 	/* don't change environment variable text */
    112 	dirlist = stralloc(dirlist);
    113 
    114 	/* parse the directory list */
    115 	dir = strtok(dirlist, DIRSEPS);
    116 	while (dir != NULL) {
    117 
    118 		/*
    119 		 * make sure it is a directory (must exist in current
    120 		 * view path node)
    121 		 */
    122 		if (stat(compath(dir), &statstruct) == 0 &&
    123 		    S_ISDIR(statstruct.st_mode)) {
    124 			if (incdirs == NULL) {
    125 				incdirs = mymalloc(mincdirs * sizeof (char *));
    126 			} else if (nincdirs == mincdirs) {
    127 				mincdirs += DIRINC;
    128 				incdirs = myrealloc(incdirs,
    129 				    mincdirs * sizeof (char *));
    130 			}
    131 			incdirs[nincdirs++] = stralloc(dir);
    132 		}
    133 		dir = strtok((char *)NULL, DIRSEPS);
    134 	}
    135 }
    136 
    137 /* make the source file list */
    138 
    139 void
    140 makefilelist(void)
    141 {
    142 	static	BOOL	firstbuild = YES;	/* first time through */
    143 	FILE	*names;			/* name file pointer */
    144 	char	dir[PATHLEN + 1];
    145 	char	path[PATHLEN + 1];
    146 	struct	stat	statstruct;
    147 	char	*file;
    148 	char	*s;
    149 	int	i, j;
    150 
    151 	/* if there are source file arguments */
    152 	if (fileargc > 0) {
    153 		/* put them in a list that can be expanded */
    154 		for (i = 0; i < fileargc; ++i) {
    155 			file = fileargv[i];
    156 			if (infilelist(file) == NO) {
    157 				if (vpaccess(file, READ) == 0) {
    158 					addsrcfile(file);
    159 				} else {
    160 					(void) fprintf(stderr,
    161 					    "cscope: cannot find file %s\n",
    162 					    file);
    163 					errorsfound = YES;
    164 				}
    165 			}
    166 		}
    167 		return;
    168 	}
    169 	/* see if a file name file exists */
    170 	if (namefile == NULL && vpaccess(NAMEFILE, READ) == 0) {
    171 		namefile = NAMEFILE;
    172 	}
    173 	/* if there is a file of source file names */
    174 	if (namefile != NULL) {
    175 		if ((names = vpfopen(namefile, "r")) == NULL) {
    176 			cannotopen(namefile);
    177 			myexit(1);
    178 		}
    179 		/* get the names in the file */
    180 		while (fscanf(names, "%s", path) == 1) {
    181 			if (*path == '-') {	/* if an option */
    182 				i = path[1];
    183 				switch (i) {
    184 				case 'q':	/* quick search */
    185 					invertedindex = YES;
    186 					break;
    187 				case 'T':
    188 					/* truncate symbols to 8 characters */
    189 					truncatesyms = YES;
    190 					break;
    191 				case 'I':	/* #include file directory */
    192 				case 'p':	/* file path components to */
    193 						/* display */
    194 					s = path + 2;	  /* for "-Ipath" */
    195 					if (*s == '\0') { /* if "-I path" */
    196 						(void) fscanf(names,
    197 						    "%s", path);
    198 						s = path;
    199 					}
    200 					switch (i) {
    201 					case 'I': /* #include file directory */
    202 						if (firstbuild == YES) {
    203 							/* expand $ and ~ */
    204 							shellpath(dir,
    205 							    sizeof (dir), s);
    206 							includedir(dir);
    207 						}
    208 						break;
    209 					case 'p':
    210 						/* file path components */
    211 						/* to display */
    212 						if (*s < '0' || *s > '9') {
    213 							(void) fprintf(stderr,
    214 							    "cscope: -p option "
    215 							    "in file %s: "
    216 							    "missing or "
    217 							    "invalid numeric "
    218 							    "value\n",
    219 							    namefile);
    220 						}
    221 						dispcomponents = atoi(s);
    222 						break;
    223 					}
    224 					break;
    225 				default:
    226 					(void) fprintf(stderr,
    227 					    "cscope: only -I, -p, and -T "
    228 					    "options can be in file %s\n",
    229 					    namefile);
    230 				}
    231 			} else if (vpaccess(path, READ) == 0) {
    232 				addsrcfile(path);
    233 			} else {
    234 				(void) fprintf(stderr,
    235 				    "cscope: cannot find file %s\n",
    236 				    path);
    237 				errorsfound = YES;
    238 			}
    239 		}
    240 		(void) fclose(names);
    241 		firstbuild = NO;
    242 		return;
    243 	}
    244 	/* make a list of all the source files in the directories */
    245 	for (i = 0; i < nsrcdirs; ++i) {
    246 		s = srcdirs[i];
    247 		getsrcfiles(s, s);
    248 		if (*s != '/') {	/* if it isn't a full path name */
    249 
    250 			/* compute its path from any higher view path nodes */
    251 			for (j = 1; j < vpndirs; ++j) {
    252 				(void) sprintf(dir, "%s/%s", vpdirs[j], s);
    253 
    254 				/* make sure it is a directory */
    255 				if (stat(compath(dir), &statstruct) == 0 &&
    256 				    S_ISDIR(statstruct.st_mode)) {
    257 					getsrcfiles(dir, s);
    258 				}
    259 			}
    260 		}
    261 	}
    262 }
    263 
    264 /* get the source file names in this directory */
    265 
    266 static void
    267 getsrcfiles(char *vpdir, char *dir)
    268 {
    269 	DIR	*dirfile;	/* directory file descriptor */
    270 	struct	dirent	*entry;	/* directory entry pointer */
    271 	char	path[PATHLEN + 1];
    272 
    273 	/* attempt to open the directory */
    274 	if ((dirfile = opendir(vpdir)) != NULL) {
    275 
    276 		/* read each entry in the directory */
    277 		while ((entry = readdir(dirfile)) != NULL) {
    278 
    279 			/* if it is a source file not already found */
    280 			(void) sprintf(path, "%s/%s", dir, entry->d_name);
    281 			if (entry->d_ino != 0 &&
    282 			    issrcfile(path) && infilelist(path) == NO) {
    283 				addsrcfile(path);	/* add it to the list */
    284 			}
    285 		}
    286 		closedir(dirfile);
    287 	}
    288 }
    289 
    290 /* see if this is a source file */
    291 
    292 static BOOL
    293 issrcfile(char *file)
    294 {
    295 	struct	stat	statstruct;
    296 	char	*s;
    297 
    298 	/* if there is a file suffix */
    299 	if ((s = strrchr(file, '.')) != NULL && *++s != '\0') {
    300 
    301 		/* if an SCCS or versioned file */
    302 		if (file[1] == '.' && file + 2 != s) { /* 1 character prefix */
    303 			switch (*file) {
    304 			case 's':
    305 			case 'S':
    306 				return (NO);
    307 			}
    308 		}
    309 		if (s[1] == '\0') {	/* 1 character suffix */
    310 			switch (*s) {
    311 			case 'c':
    312 			case 'h':
    313 			case 'l':
    314 			case 'y':
    315 			case 'C':
    316 			case 'G':
    317 			case 'H':
    318 			case 'L':
    319 				return (YES);
    320 			}
    321 		} else if (s[2] == '\0') {	/* 2 character suffix */
    322 			if (*s == 'b' && s[1] == 'p' ||	/* breakpoint listing */
    323 			    *s == 'q' &&
    324 				(s[1] == 'c' || s[1] == 'h') || /* Ingres */
    325 			    *s == 'p' && s[1] == 'r' ||	/* SDL */
    326 			    *s == 's' && s[1] == 'd') {	/* SDL */
    327 
    328 				/*
    329 				 * some directories have 2 character
    330 				 * suffixes so make sure it is a file
    331 				 */
    332 				if (vpstat(file, &statstruct) == 0 &&
    333 				    S_ISREG(statstruct.st_mode)) {
    334 					return (YES);
    335 				}
    336 			}
    337 		}
    338 	}
    339 	return (NO);
    340 }
    341 
    342 /* add an include file to the source file list */
    343 
    344 void
    345 incfile(char *file, int type)
    346 {
    347 	char	path[PATHLEN + 1];
    348 	int	i;
    349 
    350 	/* see if the file is already in the source file list */
    351 	if (infilelist(file) == YES) {
    352 		return;
    353 	}
    354 	/* look in current directory if it was #include "file" */
    355 	if (type == '"' && vpaccess(file, READ) == 0) {
    356 		addsrcfile(file);
    357 	} else {
    358 		/* search for the file in the #include directory list */
    359 		for (i = 0; i < nincdirs; ++i) {
    360 
    361 			/* don't include the file from two directories */
    362 			(void) sprintf(path, "%s/%s", incdirs[i], file);
    363 			if (infilelist(path) == YES) {
    364 				break;
    365 			}
    366 			/* make sure it exists and is readable */
    367 			if (vpaccess(compath(path), READ) == 0) {
    368 				addsrcfile(path);
    369 				break;
    370 			}
    371 		}
    372 	}
    373 }
    374 
    375 /* see if the file is already in the list */
    376 
    377 BOOL
    378 infilelist(char *file)
    379 {
    380 	struct	listitem *p;
    381 
    382 	for (p = srcfiletable[hash(compath(file)) % HASHMOD];
    383 	    p != NULL; p = p->next) {
    384 		if (strequal(file, p->file)) {
    385 			return (YES);
    386 		}
    387 	}
    388 	return (NO);
    389 }
    390 
    391 /* add a source file to the list */
    392 
    393 void
    394 addsrcfile(char *path)
    395 {
    396 	struct	listitem *p;
    397 	int	i;
    398 
    399 	/* make sure there is room for the file */
    400 	if (nsrcfiles == msrcfiles) {
    401 		msrcfiles += SRCINC;
    402 		srcfiles = myrealloc(srcfiles, msrcfiles * sizeof (char *));
    403 	}
    404 	/* add the file to the list */
    405 	p = (struct listitem *)mymalloc(sizeof (struct listitem));
    406 	p->file = stralloc(compath(path));
    407 	i = hash(p->file) % HASHMOD;
    408 	p->next = srcfiletable[i];
    409 	srcfiletable[i] = p;
    410 	srcfiles[nsrcfiles++] = p->file;
    411 }
    412 
    413 /* free the memory allocated for the source file list */
    414 
    415 void
    416 freefilelist(void)
    417 {
    418 	struct	listitem *p, *nextp;
    419 	int	i;
    420 
    421 	while (nsrcfiles > 0) {
    422 		free(srcfiles[--nsrcfiles]);
    423 	}
    424 	for (i = 0; i < HASHMOD; ++i) {
    425 		for (p = srcfiletable[i]; p != NULL; p = nextp) {
    426 			nextp = p->next;
    427 			free(p);
    428 		}
    429 		srcfiletable[i] = NULL;
    430 	}
    431 }
    432