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