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