#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include "global.h"
#include "vp.h"
static char const rcsid[] = "$Id: dir.c,v 1.4 2004/07/09 21:34:44 nicolai 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 nsrcdirs;
int nsrcfiles;
int msrcfiles = SRCINC;
static char **incnames;
static int mincdirs = DIRINC;
static int msrcdirs;
static int nvpsrcdirs;
static struct listitem {
char *text;
struct listitem *next;
} *srcnames[HASHMOD];
static BOOL issrcfile(char *file);
static void addsrcdir(char *dir);
static void addincdir(char *name, char *path);
static void scan_dir(const char *dirfile, BOOL recurse);
static void makevpsrcdirs(void);
static 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) {
int dir_len = strlen(dir);
addsrcdir(dir);
if (*dirlist != '/' && vpndirs > 1) {
for (i = 1; i < nvpsrcdirs; ++i) {
(void) sprintf(path, "%.*s/%s",
PATHLEN - 2 - dir_len,
srcdirs[i], dir);
addsrcdir(path);
}
}
dir = strtok(NULL, DIRSEPS);
}
free(dirlist);
}
static void
addsrcdir(char *dir)
{
struct stat statstruct;
if (lstat(compath(dir), &statstruct) == 0 &&
S_ISDIR(statstruct.st_mode)) {
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) {
int dir_len = strlen(dir);
addincdir(dir, dir);
if (*dirlist != '/' && vpndirs > 1) {
for (i = 1; i < nvpsrcdirs; ++i) {
(void) sprintf(path, "%.*s/%s",
PATHLEN - 2 - dir_len,
srcdirs[i], dir);
addincdir(dir, path);
}
}
dir = strtok(NULL, DIRSEPS);
}
free(dirlist);
}
static void
addincdir(char *name, char *path)
{
struct stat statstruct;
if (lstat(compath(path), &statstruct) == 0 &&
S_ISDIR(statstruct.st_mode)) {
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 line[PATHLEN * 10];
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(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 (fgets(line, 10*PATHLEN, names) != NULL) {
char *point_in_line = line + (strlen(line) - 1);
size_t length_of_name = 0;
int unfinished_option = 0;
BOOL done = NO;
if (*point_in_line == '\n')
*point_in_line = '\0';
point_in_line = line;
while (sscanf(point_in_line, "%s", path) == 1) {
length_of_name = strlen(path);
if (*path == '-') {
if (unfinished_option) {
(void) fprintf(stderr, "\
cscope: Syntax error in namelist file %s: unfinished -I or -p option\n",
namefile);
unfinished_option = 0;
}
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') {
unfinished_option = i;
break;
}
#define HANDLE_OPTION_ARGUMENT(i, s) \
switch (i) { \
case 'I': \
if (firstbuild == YES) { \
\
shellpath(dir, sizeof(dir), (s)); \
includedir(dir); \
} \
unfinished_option = 0; \
done = YES; \
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); \
unfinished_option = 0; \
done = YES; \
break; \
default: \
done = NO; \
}
HANDLE_OPTION_ARGUMENT(i, s)
break;
default:
(void) fprintf(stderr, "cscope: only -I, -c, -k, -p, and -T options can be in file %s\n",
namefile);
}
} else if (*path == '"') {
size_t in = 1, out = 0;
char *newpath = mymalloc(PATHLEN + 1);
while (in < PATHLEN && point_in_line[in] != '\0') {
if (point_in_line[in] == '"') {
newpath[out] = '\0';
point_in_line += in + 1;
path[0]='\0';
break;
}
else if (point_in_line[in] == '\\' && in < PATHLEN - 1
&& (point_in_line[in + 1]== '"' || point_in_line[in + 1] == '\\')) {
newpath[out++] = point_in_line[in + 1];
in += 2;
}
else {
newpath[out++] = point_in_line[in++];
}
}
if (in >= PATHLEN) {
newpath[out]='\0';
}
HANDLE_OPTION_ARGUMENT(unfinished_option, newpath);
if (! done) {
if ((s = inviewpath(newpath)) != NULL) {
addsrcfile(s);
} else {
(void) fprintf(stderr,
"cscope: cannot find file %s\n",
newpath);
errorsfound = YES;
}
}
} else {
HANDLE_OPTION_ARGUMENT(unfinished_option, path);
if (!done) {
if ((s = inviewpath(path)) != NULL) {
addsrcfile(s);
} else {
(void) fprintf(stderr, "cscope: cannot find file %s\n",
path);
errorsfound = YES;
}
}
}
point_in_line += length_of_name;
while (isspace((unsigned char) *point_in_line))
point_in_line ++;
}
}
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;
int adir_len = strlen(adir);
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,
PATHLEN - 2 - adir_len,
entry->d_name);
if (lstat(path,&buf) == 0) {
file = entry->d_name;
if (recurse_dir
&& S_ISDIR(buf.st_mode) ) {
scan_dir(path, recurse_dir);
}
else if (
#ifdef __DJGPP__
1
#else
entry->d_ino != 0
#endif
&& issrcfile(mybasename(path))
&& infilelist(path) == NO) {
addsrcfile(path);
}
}
}
}
closedir(dirfile);
}
return;
}
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 == 's' && s[1] == 'd') ||
(*s == 'c' && s[1] == 'c') ||
(*s == 'h' && s[1] == 'h')) {
if (lstat(file, &statstruct) == 0 &&
S_ISREG(statstruct.st_mode)) {
return(YES);
}
}
}
else if( s[3] == '\0' ) {
if(
(*s == 't' && s[1] == 'c' && s[2] == 'c' ) ||
0) {
if (lstat(file, &statstruct) == 0 &&
S_ISREG(statstruct.st_mode)) {
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(s);
}
else {
int file_len = strlen(file);
for (i = 0; i < nincdirs; ++i) {
(void) sprintf(name, "%.*s/%s",
PATHLEN - 2 - file_len, incnames[i],
file);
if (infilelist(name) == YES) {
break;
}
(void) sprintf(path, "%.*s/%s",
PATHLEN - 2 - file_len, incdirs[i],
file);
if (access(compath(path), READ) == 0) {
addsrcfile(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) {
int file_len = strlen(file);
for (i = 1; i < nvpsrcdirs; ++i) {
(void) sprintf(path, "%.*s/%s",
PATHLEN - 2 - file_len, srcdirs[i],
file);
if (access(compath(path), READ) == 0) {
return(path);
}
}
}
return(NULL);
}
void
addsrcfile(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;
}
}