#include <sys/types.h>
#include <sys/stat.h>
#include "global.h"
#include "dirent.h"
#include "vp.h"
#define DIRSEPS " ,:"
#define DIRINC 10
#define HASHMOD 2003
#define SRCINC HASHMOD
char **incdirs;
char **srcdirs;
char **srcfiles;
int nincdirs;
int mincdirs = DIRINC;
int nsrcdirs;
int msrcdirs = DIRINC;
int nsrcfiles;
int msrcfiles = SRCINC;
static struct listitem {
char *file;
struct listitem *next;
} *srcfiletable[HASHMOD];
static void getsrcfiles(char *vpdir, char *dir);
static BOOL issrcfile(char *file);
void
sourcedir(char *dirlist)
{
struct stat statstruct;
char *dir;
dirlist = stralloc(dirlist);
dir = strtok(dirlist, DIRSEPS);
while (dir != NULL) {
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);
}
}
void
includedir(char *dirlist)
{
struct stat statstruct;
char *dir;
dirlist = stralloc(dirlist);
dir = strtok(dirlist, DIRSEPS);
while (dir != NULL) {
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);
}
}
void
makefilelist(void)
{
static BOOL firstbuild = YES;
FILE *names;
char dir[PATHLEN + 1];
char path[PATHLEN + 1];
struct stat statstruct;
char *file;
char *s;
int i, j;
if (fileargc > 0) {
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;
}
if (namefile == NULL && vpaccess(NAMEFILE, READ) == 0) {
namefile = NAMEFILE;
}
if (namefile != NULL) {
if ((names = vpfopen(namefile, "r")) == NULL) {
cannotopen(namefile);
myexit(1);
}
while (fscanf(names, "%s", path) == 1) {
if (*path == '-') {
i = path[1];
switch (i) {
case 'q':
invertedindex = YES;
break;
case 'T':
truncatesyms = 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, -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;
}
for (i = 0; i < nsrcdirs; ++i) {
s = srcdirs[i];
getsrcfiles(s, s);
if (*s != '/') {
for (j = 1; j < vpndirs; ++j) {
(void) sprintf(dir, "%s/%s", vpdirs[j], s);
if (stat(compath(dir), &statstruct) == 0 &&
S_ISDIR(statstruct.st_mode)) {
getsrcfiles(dir, s);
}
}
}
}
}
static void
getsrcfiles(char *vpdir, char *dir)
{
DIR *dirfile;
struct dirent *entry;
char path[PATHLEN + 1];
if ((dirfile = opendir(vpdir)) != NULL) {
while ((entry = readdir(dirfile)) != NULL) {
(void) sprintf(path, "%s/%s", dir, entry->d_name);
if (entry->d_ino != 0 &&
issrcfile(path) && infilelist(path) == NO) {
addsrcfile(path);
}
}
closedir(dirfile);
}
}
static 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 == 'p' && s[1] == 'r' ||
*s == 's' && s[1] == 'd') {
if (vpstat(file, &statstruct) == 0 &&
S_ISREG(statstruct.st_mode)) {
return (YES);
}
}
}
}
return (NO);
}
void
incfile(char *file, int type)
{
char path[PATHLEN + 1];
int i;
if (infilelist(file) == YES) {
return;
}
if (type == '"' && vpaccess(file, READ) == 0) {
addsrcfile(file);
} else {
for (i = 0; i < nincdirs; ++i) {
(void) sprintf(path, "%s/%s", incdirs[i], file);
if (infilelist(path) == YES) {
break;
}
if (vpaccess(compath(path), READ) == 0) {
addsrcfile(path);
break;
}
}
}
}
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);
}
void
addsrcfile(char *path)
{
struct listitem *p;
int i;
if (nsrcfiles == msrcfiles) {
msrcfiles += SRCINC;
srcfiles = myrealloc(srcfiles, msrcfiles * sizeof (char *));
}
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;
}
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;
}
}