OpenSolaris_b135/tools/cscope-fast/dir.c

Compare this file to the similar file:
Show the results in this format:

/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*	Copyright (c) 1988 AT&T	*/
/*	  All Rights Reserved  	*/


/*
 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#pragma ident	"%Z%%M%	%I%	%E% SMI"

/*
 *	cscope - interactive C symbol cross-reference
 *
 *	directory searching functions
 */

#include <sys/types.h>	/* needed by stat.h */
#include <sys/stat.h>	/* stat */
#include "global.h"
#include "dirent.h"
#include "vp.h"		/* vpdirs and vpndirs */

#define	DIRSEPS	" ,:"	/* directory list separators */
#define	DIRINC	10	/* directory list size increment */
#define	HASHMOD	2003	/* must be a prime number */
#define	SRCINC	HASHMOD	/* source file list size increment */
			/* largest known database had 22049 files */

char	**incdirs;		/* #include directories */
char	**srcdirs;		/* source directories */
char	**srcfiles;		/* source files */
int	nincdirs;		/* number of #include directories */
int	mincdirs = DIRINC;	/* maximum number of #include directories */
int	nsrcdirs;		/* number of source directories */
int	msrcdirs = DIRINC;	/* maximum number of source directories */
int	nsrcfiles;		/* number of source files */
int	msrcfiles = SRCINC;	/* maximum number of source files */

static	struct	listitem {	/* source file table entry */
	char	*file;
	struct	listitem *next;
} *srcfiletable[HASHMOD];


static void getsrcfiles(char *vpdir, char *dir);
static BOOL issrcfile(char *file);

/* add a source directory to the list for each view path source directory */

void
sourcedir(char *dirlist)
{
	struct	stat	statstruct;
	char	*dir;

	/* don't change environment variable text */
	dirlist = stralloc(dirlist);

	/* parse the directory list */
	dir = strtok(dirlist, DIRSEPS);
	while (dir != NULL) {
		/*
		 * make sure it is a directory (must exist in current
		 * view path node)
		 */
		if (stat(compath(dir), &statstruct) == 0 &&
		    S_ISDIR(statstruct.st_mode)) {
			if (srcdirs == NULL) {
				srcdirs = mymalloc(msrcdirs * sizeof (char *));
			} else if (nsrcdirs == msrcdirs) {
				msrcdirs += DIRINC;
				srcdirs = myrealloc(srcdirs,
				    msrcdirs * sizeof (char *));
			}
			srcdirs[nsrcdirs++] = stralloc(dir);
		}
		dir = strtok((char *)NULL, DIRSEPS);
	}
}

/* add a #include directory to the list for each view path source directory */

void
includedir(char *dirlist)
{
	struct	stat	statstruct;
	char	*dir;

	/* don't change environment variable text */
	dirlist = stralloc(dirlist);

	/* parse the directory list */
	dir = strtok(dirlist, DIRSEPS);
	while (dir != NULL) {

		/*
		 * make sure it is a directory (must exist in current
		 * view path node)
		 */
		if (stat(compath(dir), &statstruct) == 0 &&
		    S_ISDIR(statstruct.st_mode)) {
			if (incdirs == NULL) {
				incdirs = mymalloc(mincdirs * sizeof (char *));
			} else if (nincdirs == mincdirs) {
				mincdirs += DIRINC;
				incdirs = myrealloc(incdirs,
				    mincdirs * sizeof (char *));
			}
			incdirs[nincdirs++] = stralloc(dir);
		}
		dir = strtok((char *)NULL, DIRSEPS);
	}
}

/* make the source file list */

void
makefilelist(void)
{
	static	BOOL	firstbuild = YES;	/* first time through */
	FILE	*names;			/* name file pointer */
	char	dir[PATHLEN + 1];
	char	path[PATHLEN + 1];
	struct	stat	statstruct;
	char	*file;
	char	*s;
	int	i, j;

	/* if there are source file arguments */
	if (fileargc > 0) {
		/* put them in a list that can be expanded */
		for (i = 0; i < fileargc; ++i) {
			file = fileargv[i];
			if (infilelist(file) == NO) {
				if (vpaccess(file, READ) == 0) {
					addsrcfile(file);
				} else {
					(void) fprintf(stderr,
					    "cscope: cannot find file %s\n",
					    file);
					errorsfound = YES;
				}
			}
		}
		return;
	}
	/* see if a file name file exists */
	if (namefile == NULL && vpaccess(NAMEFILE, READ) == 0) {
		namefile = NAMEFILE;
	}
	/* if there is a file of source file names */
	if (namefile != NULL) {
		if ((names = vpfopen(namefile, "r")) == NULL) {
			cannotopen(namefile);
			myexit(1);
		}
		/* get the names in the file */
		while (fscanf(names, "%s", path) == 1) {
			if (*path == '-') {	/* if an option */
				i = path[1];
				switch (i) {
				case 'q':	/* quick search */
					invertedindex = YES;
					break;
				case 'T':
					/* truncate symbols to 8 characters */
					truncatesyms = YES;
					break;
				case 'I':	/* #include file directory */
				case 'p':	/* file path components to */
						/* display */
					s = path + 2;	  /* for "-Ipath" */
					if (*s == '\0') { /* if "-I path" */
						(void) fscanf(names,
						    "%s", path);
						s = path;
					}
					switch (i) {
					case 'I': /* #include file directory */
						if (firstbuild == YES) {
							/* expand $ and ~ */
							shellpath(dir,
							    sizeof (dir), s);
							includedir(dir);
						}
						break;
					case 'p':
						/* file path components */
						/* to display */
						if (*s < '0' || *s > '9') {
							(void) fprintf(stderr,
							    "cscope: -p option "
							    "in file %s: "
							    "missing or "
							    "invalid numeric "
							    "value\n",
							    namefile);
						}
						dispcomponents = atoi(s);
						break;
					}
					break;
				default:
					(void) fprintf(stderr,
					    "cscope: only -I, -p, and -T "
					    "options can be in file %s\n",
					    namefile);
				}
			} else if (vpaccess(path, READ) == 0) {
				addsrcfile(path);
			} else {
				(void) fprintf(stderr,
				    "cscope: cannot find file %s\n",
				    path);
				errorsfound = YES;
			}
		}
		(void) fclose(names);
		firstbuild = NO;
		return;
	}
	/* make a list of all the source files in the directories */
	for (i = 0; i < nsrcdirs; ++i) {
		s = srcdirs[i];
		getsrcfiles(s, s);
		if (*s != '/') {	/* if it isn't a full path name */

			/* compute its path from any higher view path nodes */
			for (j = 1; j < vpndirs; ++j) {
				(void) sprintf(dir, "%s/%s", vpdirs[j], s);

				/* make sure it is a directory */
				if (stat(compath(dir), &statstruct) == 0 &&
				    S_ISDIR(statstruct.st_mode)) {
					getsrcfiles(dir, s);
				}
			}
		}
	}
}

/* get the source file names in this directory */

static void
getsrcfiles(char *vpdir, char *dir)
{
	DIR	*dirfile;	/* directory file descriptor */
	struct	dirent	*entry;	/* directory entry pointer */
	char	path[PATHLEN + 1];

	/* attempt to open the directory */
	if ((dirfile = opendir(vpdir)) != NULL) {

		/* read each entry in the directory */
		while ((entry = readdir(dirfile)) != NULL) {

			/* if it is a source file not already found */
			(void) sprintf(path, "%s/%s", dir, entry->d_name);
			if (entry->d_ino != 0 &&
			    issrcfile(path) && infilelist(path) == NO) {
				addsrcfile(path);	/* add it to the list */
			}
		}
		closedir(dirfile);
	}
}

/* see if this is a source file */

static BOOL
issrcfile(char *file)
{
	struct	stat	statstruct;
	char	*s;

	/* if there is a file suffix */
	if ((s = strrchr(file, '.')) != NULL && *++s != '\0') {

		/* if an SCCS or versioned file */
		if (file[1] == '.' && file + 2 != s) { /* 1 character prefix */
			switch (*file) {
			case 's':
			case 'S':
				return (NO);
			}
		}
		if (s[1] == '\0') {	/* 1 character suffix */
			switch (*s) {
			case 'c':
			case 'h':
			case 'l':
			case 'y':
			case 'C':
			case 'G':
			case 'H':
			case 'L':
				return (YES);
			}
		} else if (s[2] == '\0') {	/* 2 character suffix */
			if (*s == 'b' && s[1] == 'p' ||	/* breakpoint listing */
			    *s == 'q' &&
				(s[1] == 'c' || s[1] == 'h') || /* Ingres */
			    *s == 'p' && s[1] == 'r' ||	/* SDL */
			    *s == 's' && s[1] == 'd') {	/* SDL */

				/*
				 * some directories have 2 character
				 * suffixes so make sure it is a file
				 */
				if (vpstat(file, &statstruct) == 0 &&
				    S_ISREG(statstruct.st_mode)) {
					return (YES);
				}
			}
		}
	}
	return (NO);
}

/* add an include file to the source file list */

void
incfile(char *file, int type)
{
	char	path[PATHLEN + 1];
	int	i;

	/* see if the file is already in the source file list */
	if (infilelist(file) == YES) {
		return;
	}
	/* look in current directory if it was #include "file" */
	if (type == '"' && vpaccess(file, READ) == 0) {
		addsrcfile(file);
	} else {
		/* search for the file in the #include directory list */
		for (i = 0; i < nincdirs; ++i) {

			/* don't include the file from two directories */
			(void) sprintf(path, "%s/%s", incdirs[i], file);
			if (infilelist(path) == YES) {
				break;
			}
			/* make sure it exists and is readable */
			if (vpaccess(compath(path), READ) == 0) {
				addsrcfile(path);
				break;
			}
		}
	}
}

/* see if the file is already in the list */

BOOL
infilelist(char *file)
{
	struct	listitem *p;

	for (p = srcfiletable[hash(compath(file)) % HASHMOD];
	    p != NULL; p = p->next) {
		if (strequal(file, p->file)) {
			return (YES);
		}
	}
	return (NO);
}

/* add a source file to the list */

void
addsrcfile(char *path)
{
	struct	listitem *p;
	int	i;

	/* make sure there is room for the file */
	if (nsrcfiles == msrcfiles) {
		msrcfiles += SRCINC;
		srcfiles = myrealloc(srcfiles, msrcfiles * sizeof (char *));
	}
	/* add the file to the list */
	p = (struct listitem *)mymalloc(sizeof (struct listitem));
	p->file = stralloc(compath(path));
	i = hash(p->file) % HASHMOD;
	p->next = srcfiletable[i];
	srcfiletable[i] = p;
	srcfiles[nsrcfiles++] = p->file;
}

/* free the memory allocated for the source file list */

void
freefilelist(void)
{
	struct	listitem *p, *nextp;
	int	i;

	while (nsrcfiles > 0) {
		free(srcfiles[--nsrcfiles]);
	}
	for (i = 0; i < HASHMOD; ++i) {
		for (p = srcfiletable[i]; p != NULL; p = nextp) {
			nextp = p->next;
			free(p);
		}
		srcfiletable[i] = NULL;
	}
}