#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>
#include <stdlib.h>
#include <sys/stat.h>
#include "global.h"
#include "vp.h"
static char const rcsid[] = "$Id: dir.c,v 1.3 2002/01/09 19:04:04 umeshv Exp $";
#define DIRSEPS " ,:"
#define DIRINC 10
#define HASHMOD 2003
#define SRCINC HASHMOD
char currentdir[PATHLEN + 1];
char **incdirs;
char **srcdirs;
char **srcfiles;
int nincdirs;
int mincdirs = DIRINC;
int nsrcdirs;
int msrcdirs;
int nsrcfiles;
int msrcfiles = SRCINC;
static char **incnames;
static int nvpsrcdirs;
static struct listitem {
char *text;
struct listitem *next;
} *srcnames[HASHMOD];
BOOL issrcfile(char *file);
void addsrcdir(char *dir);
void addincdir(char *name, char *path);
static void scan_dir(const char *dirfile, BOOL recurse);
void
makevpsrcdirs(void)
{
int i;
if (nsrcdirs > 0) {
return;
}
if (getcwd(currentdir, PATHLEN) == NULL) {
(void) fprintf(stderr, "cscope: warning: cannot get current directory name\n");
(void) strcpy(currentdir, "<unknown>");
}
vpinit(currentdir);
if (vpndirs > 1) {
nsrcdirs = vpndirs;
}
else {
nsrcdirs = 1;
}
msrcdirs = nsrcdirs + DIRINC;
srcdirs = mymalloc(msrcdirs * sizeof(char *));
*srcdirs = ".";
for (i = 1; i < vpndirs; ++i) {
srcdirs[i] = vpdirs[i];
}
nvpsrcdirs = nsrcdirs;
}
void
sourcedir(char *dirlist)
{
char path[PATHLEN + 1];
char *dir;
int i;
makevpsrcdirs();
dirlist = stralloc(dirlist);
dir = strtok(dirlist, DIRSEPS);
while (dir != NULL) {
addsrcdir(dir);
if (*dirlist != '/' && vpndirs > 1) {
for (i = 1; i < nvpsrcdirs; ++i) {
(void) sprintf(path, "%s/%s", srcdirs[i], dir);
addsrcdir(path);
}
}
dir = strtok(NULL, DIRSEPS);
}
free(dirlist);
}
void
addsrcdir(char *dir)
{
struct stat statstruct;
if (stat(compath(dir), &statstruct) == 0 &&
(statstruct.st_mode & S_IFDIR)) {
if (nsrcdirs == msrcdirs) {
msrcdirs += DIRINC;
srcdirs = myrealloc(srcdirs, msrcdirs * sizeof(char *));
}
srcdirs[nsrcdirs++] = stralloc(dir);
}
}
void
freesrclist()
{
if (!srcdirs)
return;
while(nsrcdirs>1)
free(srcdirs[--nsrcdirs]);
free(srcdirs);
}
void
includedir(char *dirlist)
{
char path[PATHLEN + 1];
char *dir;
int i;
makevpsrcdirs();
dirlist = stralloc(dirlist);
dir = strtok(dirlist, DIRSEPS);
while (dir != NULL) {
addincdir(dir, dir);
if (*dirlist != '/' && vpndirs > 1) {
for (i = 1; i < nvpsrcdirs; ++i) {
(void) sprintf(path, "%s/%s", srcdirs[i], dir);
addincdir(dir, path);
}
}
dir = strtok(NULL, DIRSEPS);
}
free(dirlist);
}
void
addincdir(char *name, char *path)
{
struct stat statstruct;
if (stat(compath(path), &statstruct) == 0 &&
(statstruct.st_mode & S_IFDIR)) {
if (incdirs == NULL) {
incdirs = mymalloc(mincdirs * sizeof(char *));
incnames = mymalloc(mincdirs * sizeof(char *));
}
else if (nincdirs == mincdirs) {
mincdirs += DIRINC;
incdirs = myrealloc(incdirs,
mincdirs * sizeof(char *));
incnames = myrealloc(incnames,
mincdirs * sizeof(char *));
}
incdirs[nincdirs] = stralloc(path);
incnames[nincdirs++] = stralloc(name);
}
}
void
freeinclist()
{
if (!incdirs)
return;
while(nincdirs>0) {
free(incdirs[--nincdirs]);
free(incnames[nincdirs]);
}
free(incdirs);
free(incnames);
}
void
makefilelist(void)
{
static BOOL firstbuild = YES;
FILE *names;
char dir[PATHLEN + 1];
char path[PATHLEN + 1];
char *file;
char *s;
int i;
makevpsrcdirs();
if (namefile == NULL && fileargc > 0) {
for (i = 0; i < fileargc; ++i) {
file = fileargv[i];
if (infilelist(file) == NO) {
if ((s = inviewpath(file)) != NULL) {
addsrcfile(file, s);
}
else {
(void) fprintf(stderr, "cscope: cannot find file %s\n",
file);
errorsfound = YES;
}
}
}
return;
}
if (namefile == NULL && vpaccess(NAMEFILE, READ) == 0) {
namefile = NAMEFILE;
}
if (namefile != NULL) {
if (strcmp(namefile, "-") == 0)
names = stdin;
else if ((names = vpfopen(namefile, "r")) == NULL) {
cannotopen(namefile);
myexit(1);
}
while (fscanf(names, "%s", path) == 1) {
if (*path == '-') {
i = path[1];
switch (i) {
case 'c':
compress = NO;
break;
case 'k':
kernelmode = YES;
break;
case 'q':
invertedindex = YES;
break;
case 'T':
trun_syms = YES;
break;
case 'I':
case 'p':
s = path + 2;
if (*s == '\0') {
(void) fscanf(names, "%s", path);
s = path;
}
switch (i) {
case 'I':
if (firstbuild == YES) {
shellpath(dir, sizeof(dir), s);
includedir(dir);
}
break;
case 'p':
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, -c, -k, -p, and -T options can be in file %s\n",
namefile);
}
}
else if ((s = inviewpath(path)) != NULL) {
addsrcfile(path, s);
}
else {
(void) fprintf(stderr, "cscope: cannot find file %s\n",
path);
errorsfound = YES;
}
}
if (names == stdin)
clearerr(stdin);
else
(void) fclose(names);
firstbuild = NO;
return;
}
for (i = 0; i < nsrcdirs; ++i) {
scan_dir(srcdirs[i], recurse_dir);
}
}
static void
scan_dir(const char *adir, BOOL recurse_dir) {
DIR *dirfile;
if( (dirfile = opendir(adir)) != NULL ) {
struct dirent *entry;
char path[PATHLEN + 1];
char *file;
while( (entry = readdir(dirfile)) != NULL ) {
if( (strcmp(".",entry->d_name) != 0)
&& (strcmp("..",entry->d_name) != 0) ) {
struct stat buf;
sprintf(path,"%s/%s",adir,entry->d_name);
if(stat(path,&buf) == 0) {
file = entry->d_name;
if( recurse_dir
&& (buf.st_mode & S_IFDIR) ) {
scan_dir(path, recurse_dir);
}
else if (
#ifdef __DJGPP__
1
#else
entry->d_ino != 0
#endif
&& issrcfile(path)
&& infilelist(path) == NO) {
addsrcfile(file, path);
}
}
}
}
closedir(dirfile);
}
return;
}
BOOL
issrcfile(char *file)
{
struct stat statstruct;
char *s;
if ((s = strrchr(file, '.')) != NULL && *++s != '\0') {
if (file[1] == '.' && file + 2 != s) {
switch (*file) {
case 's':
case 'S':
return(NO);
}
}
if (s[1] == '\0') {
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') {
if ((*s == 'b' && s[1] == 'p') ||
(*s == 'q' &&
(s[1] == 'c' || s[1] == 'h')) ||
(*s == 's' && s[1] == 'd') ||
(*s == 'c' && s[1] == 'c') ||
(*s == 'h' && s[1] == 'h')) {
if (stat(file, &statstruct) == 0 &&
(statstruct.st_mode & S_IFREG)) {
return(YES);
}
}
}
else if( s[3] == '\0' ) {
if(
(*s == 't' && s[1] == 'c' && s[2] == 'c' ) ||
0) {
if (stat(file, &statstruct) == 0 &&
(statstruct.st_mode & S_IFREG)) {
return(YES);
}
}
}
}
return(NO);
}
void
incfile(char *file, char *type)
{
char name[PATHLEN + 1];
char path[PATHLEN + 1];
char *s;
int i;
if (infilelist(file) == YES) {
return;
}
if (type[0] == '"' && (s = inviewpath(file)) != NULL) {
addsrcfile(file, s);
}
else {
for (i = 0; i < nincdirs; ++i) {
(void) sprintf(name, "%s/%s", incnames[i], file);
if (infilelist(name) == YES) {
break;
}
(void) sprintf(path, "%s/%s", incdirs[i], file);
if (access(compath(path), READ) == 0) {
addsrcfile(name, path);
break;
}
}
}
}
BOOL
infilelist(char *path)
{
struct listitem *p;
for (p = srcnames[hash(compath(path)) % HASHMOD]; p != NULL; p = p->next) {
if (strequal(path, p->text)) {
return(YES);
}
}
return(NO);
}
char *
inviewpath(char *file)
{
static char path[PATHLEN + 1];
int i;
if (access(compath(file), READ) == 0) {
return(file);
}
if (*file != '/' && vpndirs > 1) {
for (i = 1; i < nvpsrcdirs; ++i) {
(void) sprintf(path, "%s/%s", srcdirs[i], file);
if (access(compath(path), READ) == 0) {
return(path);
}
}
}
return(NULL);
}
void
addsrcfile(char *name, char *path)
{
struct listitem *p;
int i;
if (nsrcfiles == msrcfiles) {
msrcfiles += SRCINC;
srcfiles = myrealloc(srcfiles, msrcfiles * sizeof(char *));
}
srcfiles[nsrcfiles++] = stralloc(compath(path));
p = mymalloc(sizeof(struct listitem));
p->text = stralloc(compath(path));
i = hash(p->text) % HASHMOD;
p->next = srcnames[i];
srcnames[i] = p;
}
void
freefilelist(void)
{
struct listitem *p, *nextp;
int i;
if (isuptodate == NO) {
while (nsrcfiles > 0) {
free (srcfiles[--nsrcfiles]);
}
}
else {
if (nsrcfiles > 0)
free (srcfiles[0]);
nsrcfiles = 0;
}
free (srcfiles);
msrcfiles = 0;
srcfiles=0;
for (i = 0; i < HASHMOD; ++i) {
for (p = srcnames[i]; p != NULL; p = nextp) {
free(p->text);
nextp = p->next;
free(p);
}
srcnames[i] = NULL;
}
}