1 1.1 christos /* Implementation of pattern-matching file search paths for GNU Make. 2 1.1 christos Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 3 1.1 christos 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software 4 1.1 christos Foundation, Inc. 5 1.1 christos This file is part of GNU Make. 6 1.1 christos 7 1.1 christos GNU Make is free software; you can redistribute it and/or modify it under the 8 1.1 christos terms of the GNU General Public License as published by the Free Software 9 1.1 christos Foundation; either version 2, or (at your option) any later version. 10 1.1 christos 11 1.1 christos GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY 12 1.1 christos WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 1.1 christos A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 1.1 christos 15 1.1 christos You should have received a copy of the GNU General Public License along with 16 1.1 christos GNU Make; see the file COPYING. If not, write to the Free Software 17 1.1 christos Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ 18 1.1 christos 19 1.1 christos #include "make.h" 20 1.1 christos #include "filedef.h" 21 1.1 christos #include "variable.h" 22 1.1 christos #ifdef WINDOWS32 23 1.1 christos #include "pathstuff.h" 24 1.1 christos #endif 25 1.1 christos 26 1.1 christos 27 1.1 christos /* Structure used to represent a selective VPATH searchpath. */ 28 1.1 christos 29 1.1 christos struct vpath 30 1.1 christos { 31 1.1 christos struct vpath *next; /* Pointer to next struct in the linked list. */ 32 1.1 christos char *pattern; /* The pattern to match. */ 33 1.1 christos char *percent; /* Pointer into `pattern' where the `%' is. */ 34 1.1 christos unsigned int patlen;/* Length of the pattern. */ 35 1.1 christos char **searchpath; /* Null-terminated list of directories. */ 36 1.1 christos unsigned int maxlen;/* Maximum length of any entry in the list. */ 37 1.1 christos }; 38 1.1 christos 39 1.1 christos /* Linked-list of all selective VPATHs. */ 40 1.1 christos 41 1.1 christos static struct vpath *vpaths; 42 1.1 christos 43 1.1 christos /* Structure for the general VPATH given in the variable. */ 44 1.1 christos 45 1.1 christos static struct vpath *general_vpath; 46 1.1 christos 47 1.1 christos /* Structure for GPATH given in the variable. */ 48 1.1 christos 49 1.1 christos static struct vpath *gpaths; 50 1.1 christos 51 1.1 christos static int selective_vpath_search PARAMS ((struct vpath *path, char **file, FILE_TIMESTAMP *mtime_ptr)); 53 1.1 christos 54 1.1 christos /* Reverse the chain of selective VPATH lists so they 55 1.1 christos will be searched in the order given in the makefiles 56 1.1 christos and construct the list from the VPATH variable. */ 57 1.1 christos 58 1.1 christos void 59 1.1 christos build_vpath_lists () 60 1.1 christos { 61 1.1 christos register struct vpath *new = 0; 62 1.1 christos register struct vpath *old, *nexto; 63 1.1 christos register char *p; 64 1.1 christos 65 1.1 christos /* Reverse the chain. */ 66 1.1 christos for (old = vpaths; old != 0; old = nexto) 67 1.1 christos { 68 1.1 christos nexto = old->next; 69 1.1 christos old->next = new; 70 1.1 christos new = old; 71 1.1 christos } 72 1.1 christos 73 1.1 christos vpaths = new; 74 1.1 christos 75 1.1 christos /* If there is a VPATH variable with a nonnull value, construct the 76 1.1 christos general VPATH list from it. We use variable_expand rather than just 77 1.1 christos calling lookup_variable so that it will be recursively expanded. */ 78 1.1 christos 79 1.1 christos { 80 1.1 christos /* Turn off --warn-undefined-variables while we expand SHELL and IFS. */ 81 1.1 christos int save = warn_undefined_variables_flag; 82 1.1 christos warn_undefined_variables_flag = 0; 83 1.1 christos 84 1.1 christos p = variable_expand ("$(strip $(VPATH))"); 85 1.1 christos 86 1.1 christos warn_undefined_variables_flag = save; 87 1.1 christos } 88 1.1 christos 89 1.1 christos if (*p != '\0') 90 1.1 christos { 91 1.1 christos /* Save the list of vpaths. */ 92 1.1 christos struct vpath *save_vpaths = vpaths; 93 1.1 christos 94 1.1 christos /* Empty `vpaths' so the new one will have no next, and `vpaths' 95 1.1 christos will still be nil if P contains no existing directories. */ 96 1.1 christos vpaths = 0; 97 1.1 christos 98 1.1 christos /* Parse P. */ 99 1.1 christos construct_vpath_list ("%", p); 100 1.1 christos 101 1.1 christos /* Store the created path as the general path, 102 1.1 christos and restore the old list of vpaths. */ 103 1.1 christos general_vpath = vpaths; 104 1.1 christos vpaths = save_vpaths; 105 1.1 christos } 106 1.1 christos 107 1.1 christos /* If there is a GPATH variable with a nonnull value, construct the 108 1.1 christos GPATH list from it. We use variable_expand rather than just 109 1.1 christos calling lookup_variable so that it will be recursively expanded. */ 110 1.1 christos 111 1.1 christos { 112 1.1 christos /* Turn off --warn-undefined-variables while we expand SHELL and IFS. */ 113 1.1 christos int save = warn_undefined_variables_flag; 114 1.1 christos warn_undefined_variables_flag = 0; 115 1.1 christos 116 1.1 christos p = variable_expand ("$(strip $(GPATH))"); 117 1.1 christos 118 1.1 christos warn_undefined_variables_flag = save; 119 1.1 christos } 120 1.1 christos 121 1.1 christos if (*p != '\0') 122 1.1 christos { 123 1.1 christos /* Save the list of vpaths. */ 124 1.1 christos struct vpath *save_vpaths = vpaths; 125 1.1 christos 126 1.1 christos /* Empty `vpaths' so the new one will have no next, and `vpaths' 127 1.1 christos will still be nil if P contains no existing directories. */ 128 1.1 christos vpaths = 0; 129 1.1 christos 130 1.1 christos /* Parse P. */ 131 1.1 christos construct_vpath_list ("%", p); 132 1.1 christos 133 1.1 christos /* Store the created path as the GPATH, 134 1.1 christos and restore the old list of vpaths. */ 135 1.1 christos gpaths = vpaths; 136 1.1 christos vpaths = save_vpaths; 137 1.1 christos } 138 1.1 christos } 139 1.1 christos 140 1.1 christos /* Construct the VPATH listing for the pattern and searchpath given. 142 1.1 christos 143 1.1 christos This function is called to generate selective VPATH lists and also for 144 1.1 christos the general VPATH list (which is in fact just a selective VPATH that 145 1.1 christos is applied to everything). The returned pointer is either put in the 146 1.1 christos linked list of all selective VPATH lists or in the GENERAL_VPATH 147 1.1 christos variable. 148 1.1 christos 149 1.1 christos If SEARCHPATH is nil, remove all previous listings with the same 150 1.1 christos pattern. If PATTERN is nil, remove all VPATH listings. Existing 151 1.1 christos and readable directories that are not "." given in the searchpath 152 1.1 christos separated by the path element separator (defined in make.h) are 153 1.1 christos loaded into the directory hash table if they are not there already 154 1.1 christos and put in the VPATH searchpath for the given pattern with trailing 155 1.1 christos slashes stripped off if present (and if the directory is not the 156 1.1 christos root, "/"). The length of the longest entry in the list is put in 157 1.1 christos the structure as well. The new entry will be at the head of the 158 1.1 christos VPATHS chain. */ 159 1.1 christos 160 1.1 christos void 161 1.1 christos construct_vpath_list (char *pattern, char *dirpath) 162 1.1 christos { 163 1.1 christos register unsigned int elem; 164 1.1 christos register char *p; 165 1.1 christos register char **vpath; 166 1.1 christos register unsigned int maxvpath; 167 1.1 christos unsigned int maxelem; 168 1.1 christos char *percent = NULL; 169 1.1 christos 170 1.1 christos if (pattern != 0) 171 1.1 christos { 172 1.1 christos pattern = xstrdup (pattern); 173 1.1 christos percent = find_percent (pattern); 174 1.1 christos } 175 1.1 christos 176 1.1 christos if (dirpath == 0) 177 1.1 christos { 178 1.1 christos /* Remove matching listings. */ 179 1.1 christos register struct vpath *path, *lastpath; 180 1.1 christos 181 1.1 christos lastpath = 0; 182 1.1 christos path = vpaths; 183 1.1 christos while (path != 0) 184 1.1 christos { 185 1.1 christos struct vpath *next = path->next; 186 1.1 christos 187 1.1 christos if (pattern == 0 188 1.1 christos || (((percent == 0 && path->percent == 0) 189 1.1 christos || (percent - pattern == path->percent - path->pattern)) 190 1.1 christos && streq (pattern, path->pattern))) 191 1.1 christos { 192 1.1 christos /* Remove it from the linked list. */ 193 1.1 christos if (lastpath == 0) 194 1.1 christos vpaths = path->next; 195 1.1 christos else 196 1.1 christos lastpath->next = next; 197 1.1 christos 198 1.1 christos /* Free its unused storage. */ 199 1.1 christos free (path->pattern); 200 1.1 christos free ((char *) path->searchpath); 201 1.1 christos free ((char *) path); 202 1.1 christos } 203 1.1 christos else 204 1.1 christos lastpath = path; 205 1.1 christos 206 1.1 christos path = next; 207 1.1 christos } 208 1.1 christos 209 1.1 christos if (pattern != 0) 210 1.1 christos free (pattern); 211 1.1 christos return; 212 1.1 christos } 213 1.1 christos 214 1.1 christos #ifdef WINDOWS32 215 1.1 christos convert_vpath_to_windows32(dirpath, ';'); 216 1.1 christos #endif 217 1.1 christos 218 1.1 christos /* Figure out the maximum number of VPATH entries and put it in 219 1.1 christos MAXELEM. We start with 2, one before the first separator and one 220 1.1 christos nil (the list terminator) and increment our estimated number for 221 1.1 christos each separator or blank we find. */ 222 1.1 christos maxelem = 2; 223 1.1 christos p = dirpath; 224 1.1 christos while (*p != '\0') 225 1.1 christos if (*p++ == PATH_SEPARATOR_CHAR || isblank ((unsigned char)*p)) 226 1.1 christos ++maxelem; 227 1.1 christos 228 1.1 christos vpath = (char **) xmalloc (maxelem * sizeof (char *)); 229 1.1 christos maxvpath = 0; 230 1.1 christos 231 1.1 christos /* Skip over any initial separators and blanks. */ 232 1.1 christos p = dirpath; 233 1.1 christos while (*p == PATH_SEPARATOR_CHAR || isblank ((unsigned char)*p)) 234 1.1 christos ++p; 235 1.1 christos 236 1.1 christos elem = 0; 237 1.1 christos while (*p != '\0') 238 1.1 christos { 239 1.1 christos char *v; 240 1.1 christos unsigned int len; 241 1.1 christos 242 1.1 christos /* Find the end of this entry. */ 243 1.1 christos v = p; 244 1.1 christos while (*p != '\0' && *p != PATH_SEPARATOR_CHAR 245 1.1 christos && !isblank ((unsigned char)*p)) 246 1.1 christos ++p; 247 1.1 christos 248 1.1 christos len = p - v; 249 1.1 christos /* Make sure there's no trailing slash, 250 1.1 christos but still allow "/" as a directory. */ 251 1.1 christos #if defined(__MSDOS__) || defined(__EMX__) 252 1.1 christos /* We need also to leave alone a trailing slash in "d:/". */ 253 1.1 christos if (len > 3 || (len > 1 && v[1] != ':')) 254 1.1 christos #endif 255 1.1 christos if (len > 1 && p[-1] == '/') 256 1.1 christos --len; 257 1.1 christos 258 1.1 christos if (len > 1 || *v != '.') 259 1.1 christos { 260 1.1 christos v = savestring (v, len); 261 1.1 christos 262 1.1 christos /* Verify that the directory actually exists. */ 263 1.1 christos 264 1.1 christos if (dir_file_exists_p (v, "")) 265 1.1 christos { 266 1.1 christos /* It does. Put it in the list. */ 267 1.1 christos vpath[elem++] = dir_name (v); 268 1.1 christos free (v); 269 1.1 christos if (len > maxvpath) 270 1.1 christos maxvpath = len; 271 1.1 christos } 272 1.1 christos else 273 1.1 christos /* The directory does not exist. Omit from the list. */ 274 1.1 christos free (v); 275 1.1 christos } 276 1.1 christos 277 1.1 christos /* Skip over separators and blanks between entries. */ 278 1.1 christos while (*p == PATH_SEPARATOR_CHAR || isblank ((unsigned char)*p)) 279 1.1 christos ++p; 280 1.1 christos } 281 1.1 christos 282 1.1 christos if (elem > 0) 283 1.1 christos { 284 1.1 christos struct vpath *path; 285 1.1 christos /* ELEM is now incremented one element past the last 286 1.1 christos entry, to where the nil-pointer terminator goes. 287 1.1 christos Usually this is maxelem - 1. If not, shrink down. */ 288 1.1 christos if (elem < (maxelem - 1)) 289 1.1 christos vpath = (char **) xrealloc ((char *) vpath, 290 1.1 christos (elem + 1) * sizeof (char *)); 291 1.1 christos 292 1.1 christos /* Put the nil-pointer terminator on the end of the VPATH list. */ 293 1.1 christos vpath[elem] = 0; 294 1.1 christos 295 1.1 christos /* Construct the vpath structure and put it into the linked list. */ 296 1.1 christos path = (struct vpath *) xmalloc (sizeof (struct vpath)); 297 1.1 christos path->searchpath = vpath; 298 1.1 christos path->maxlen = maxvpath; 299 1.1 christos path->next = vpaths; 300 1.1 christos vpaths = path; 301 1.1 christos 302 1.1 christos /* Set up the members. */ 303 1.1 christos path->pattern = pattern; 304 1.1 christos path->percent = percent; 305 1.1 christos path->patlen = strlen (pattern); 306 1.1 christos } 307 1.1 christos else 308 1.1 christos { 309 1.1 christos /* There were no entries, so free whatever space we allocated. */ 310 1.1 christos free ((char *) vpath); 311 1.1 christos if (pattern != 0) 312 1.1 christos free (pattern); 313 1.1 christos } 314 1.1 christos } 315 1.1 christos 316 1.1 christos /* Search the GPATH list for a pathname string that matches the one passed 318 1.1 christos in. If it is found, return 1. Otherwise we return 0. */ 319 1.1 christos 320 1.1 christos int 321 1.1 christos gpath_search (char *file, unsigned int len) 322 1.1 christos { 323 1.1 christos char **gp; 324 1.1 christos 325 1.1 christos if (gpaths && (len <= gpaths->maxlen)) 326 1.1 christos for (gp = gpaths->searchpath; *gp != NULL; ++gp) 327 1.1 christos if (strneq (*gp, file, len) && (*gp)[len] == '\0') 328 1.1 christos return 1; 329 1.1 christos 330 1.1 christos return 0; 331 1.1 christos } 332 1.1 christos 333 1.1 christos /* Search the VPATH list whose pattern matches *FILE for a directory 335 1.1 christos where the name pointed to by FILE exists. If it is found, we set *FILE to 336 1.1 christos the newly malloc'd name of the existing file, *MTIME_PTR (if MTIME_PTR is 337 1.1 christos not NULL) to its modtime (or zero if no stat call was done), and return 1. 338 1.1 christos Otherwise we return 0. */ 339 1.1 christos 340 1.1 christos int 341 1.1 christos vpath_search (char **file, FILE_TIMESTAMP *mtime_ptr) 342 1.1 christos { 343 1.1 christos register struct vpath *v; 344 1.1 christos 345 1.1 christos /* If there are no VPATH entries or FILENAME starts at the root, 346 1.1 christos there is nothing we can do. */ 347 1.1 christos 348 1.1 christos if (**file == '/' 349 1.1 christos #ifdef HAVE_DOS_PATHS 350 1.1 christos || **file == '\\' 351 1.1 christos || (*file)[1] == ':' 352 1.1 christos #endif 353 1.1 christos || (vpaths == 0 && general_vpath == 0)) 354 1.1 christos return 0; 355 1.1 christos 356 1.1 christos for (v = vpaths; v != 0; v = v->next) 357 1.1 christos if (pattern_matches (v->pattern, v->percent, *file)) 358 1.1 christos if (selective_vpath_search (v, file, mtime_ptr)) 359 1.1 christos return 1; 360 1.1 christos 361 1.1 christos if (general_vpath != 0 362 1.1 christos && selective_vpath_search (general_vpath, file, mtime_ptr)) 363 1.1 christos return 1; 364 1.1 christos 365 1.1 christos return 0; 366 1.1 christos } 367 1.1 christos 368 1.1 christos 369 1.1 christos /* Search the given VPATH list for a directory where the name pointed 370 1.1 christos to by FILE exists. If it is found, we set *FILE to the newly malloc'd 371 1.1 christos name of the existing file, *MTIME_PTR (if MTIME_PTR is not NULL) to 372 1.1 christos its modtime (or zero if no stat call was done), and we return 1. 373 1.1 christos Otherwise we return 0. */ 374 1.1 christos 375 1.1 christos static int 376 1.1 christos selective_vpath_search (struct vpath *path, char **file, 377 1.1 christos FILE_TIMESTAMP *mtime_ptr) 378 1.1 christos { 379 1.1 christos int not_target; 380 1.1 christos char *name, *n; 381 1.1 christos char *filename; 382 1.1 christos register char **vpath = path->searchpath; 383 1.1 christos unsigned int maxvpath = path->maxlen; 384 1.1 christos register unsigned int i; 385 1.1 christos unsigned int flen, vlen, name_dplen; 386 1.1 christos int exists = 0; 387 1.1 christos 388 1.1 christos /* Find out if *FILE is a target. 389 1.1 christos If and only if it is NOT a target, we will accept prospective 390 1.1 christos files that don't exist but are mentioned in a makefile. */ 391 1.1 christos { 392 1.1 christos struct file *f = lookup_file (*file); 393 1.1 christos not_target = f == 0 || !f->is_target; 394 1.1 christos } 395 1.1 christos 396 1.1 christos flen = strlen (*file); 397 1.1 christos 398 1.1 christos /* Split *FILE into a directory prefix and a name-within-directory. 399 1.1 christos NAME_DPLEN gets the length of the prefix; FILENAME gets the 400 1.1 christos pointer to the name-within-directory and FLEN is its length. */ 401 1.1 christos 402 1.1 christos n = strrchr (*file, '/'); 403 1.1 christos #ifdef HAVE_DOS_PATHS 404 1.1 christos /* We need the rightmost slash or backslash. */ 405 1.1 christos { 406 1.1 christos char *bslash = strrchr(*file, '\\'); 407 1.1 christos if (!n || bslash > n) 408 1.1 christos n = bslash; 409 1.1 christos } 410 1.1 christos #endif 411 1.1 christos name_dplen = n != 0 ? n - *file : 0; 412 1.1 christos filename = name_dplen > 0 ? n + 1 : *file; 413 1.1 christos if (name_dplen > 0) 414 1.1 christos flen -= name_dplen + 1; 415 1.1 christos 416 1.1 christos /* Allocate enough space for the biggest VPATH entry, 417 1.1 christos a slash, the directory prefix that came with *FILE, 418 1.1 christos another slash (although this one may not always be 419 1.1 christos necessary), the filename, and a null terminator. */ 420 1.1 christos name = (char *) xmalloc (maxvpath + 1 + name_dplen + 1 + flen + 1); 421 1.1 christos 422 1.1 christos /* Try each VPATH entry. */ 423 1.1 christos for (i = 0; vpath[i] != 0; ++i) 424 1.1 christos { 425 1.1 christos int exists_in_cache = 0; 426 1.1 christos 427 1.1 christos n = name; 428 1.1 christos 429 1.1 christos /* Put the next VPATH entry into NAME at N and increment N past it. */ 430 1.1 christos vlen = strlen (vpath[i]); 431 1.1 christos bcopy (vpath[i], n, vlen); 432 1.1 christos n += vlen; 433 1.1 christos 434 1.1 christos /* Add the directory prefix already in *FILE. */ 435 1.1 christos if (name_dplen > 0) 436 1.1 christos { 437 1.1 christos #ifndef VMS 438 1.1 christos *n++ = '/'; 439 1.1 christos #endif 440 1.1 christos bcopy (*file, n, name_dplen); 441 1.1 christos n += name_dplen; 442 1.1 christos } 443 1.1 christos 444 1.1 christos #ifdef HAVE_DOS_PATHS 445 1.1 christos /* Cause the next if to treat backslash and slash alike. */ 446 1.1 christos if (n != name && n[-1] == '\\' ) 447 1.1 christos n[-1] = '/'; 448 1.1 christos #endif 449 1.1 christos /* Now add the name-within-directory at the end of NAME. */ 450 1.1 christos #ifndef VMS 451 1.1 christos if (n != name && n[-1] != '/') 452 1.1 christos { 453 1.1 christos *n = '/'; 454 1.1 christos bcopy (filename, n + 1, flen + 1); 455 1.1 christos } 456 1.1 christos else 457 1.1 christos #endif 458 1.1 christos bcopy (filename, n, flen + 1); 459 1.1 christos 460 1.1 christos /* Check if the file is mentioned in a makefile. If *FILE is not 461 1.1 christos a target, that is enough for us to decide this file exists. 462 1.1 christos If *FILE is a target, then the file must be mentioned in the 463 1.1 christos makefile also as a target to be chosen. 464 1.1 christos 465 1.1 christos The restriction that *FILE must not be a target for a 466 1.1 christos makefile-mentioned file to be chosen was added by an 467 1.1 christos inadequately commented change in July 1990; I am not sure off 468 1.1 christos hand what problem it fixes. 469 1.1 christos 470 1.1 christos In December 1993 I loosened this restriction to allow a file 471 1.1 christos to be chosen if it is mentioned as a target in a makefile. This 472 1.1 christos seem logical. 473 1.1 christos 474 1.1 christos Special handling for -W / -o: make sure we preserve the special 475 1.1 christos values here. Actually this whole thing is a little bogus: I think 476 1.1 christos we should ditch the name/hname thing and look into the renamed 477 1.1 christos capability that already exists for files: that is, have a new struct 478 1.1 christos file* entry for the VPATH-found file, and set the renamed field if 479 1.1 christos we use it. 480 1.1 christos */ 481 1.1 christos { 482 1.1 christos struct file *f = lookup_file (name); 483 1.1 christos if (f != 0) 484 1.1 christos { 485 1.1 christos exists = not_target || f->is_target; 486 1.1 christos if (exists && mtime_ptr 487 1.1 christos && (f->last_mtime == OLD_MTIME || f->last_mtime == NEW_MTIME)) 488 1.1 christos { 489 1.1 christos *mtime_ptr = f->last_mtime; 490 1.1 christos mtime_ptr = 0; 491 1.1 christos } 492 1.1 christos } 493 1.1 christos } 494 1.1 christos 495 1.1 christos if (!exists) 496 1.1 christos { 497 1.1 christos /* That file wasn't mentioned in the makefile. 498 1.1 christos See if it actually exists. */ 499 1.1 christos 500 1.1 christos #ifdef VMS 501 1.1 christos exists_in_cache = exists = dir_file_exists_p (vpath[i], filename); 502 1.1 christos #else 503 1.1 christos /* Clobber a null into the name at the last slash. 504 1.1 christos Now NAME is the name of the directory to look in. */ 505 1.1 christos *n = '\0'; 506 1.1 christos 507 1.1 christos /* We know the directory is in the hash table now because either 508 1.1 christos construct_vpath_list or the code just above put it there. 509 1.1 christos Does the file we seek exist in it? */ 510 1.1 christos exists_in_cache = exists = dir_file_exists_p (name, filename); 511 1.1 christos #endif 512 1.1 christos } 513 1.1 christos 514 1.1 christos if (exists) 515 1.1 christos { 516 1.1 christos /* The file is in the directory cache. 517 1.1 christos Now check that it actually exists in the filesystem. 518 1.1 christos The cache may be out of date. When vpath thinks a file 519 1.1 christos exists, but stat fails for it, confusion results in the 520 1.1 christos higher levels. */ 521 1.1 christos 522 1.1 christos struct stat st; 523 1.1 christos 524 1.1 christos #ifndef VMS 525 1.1 christos /* Put the slash back in NAME. */ 526 1.1 christos *n = '/'; 527 1.1 christos #endif 528 1.1 christos 529 1.1 christos if (exists_in_cache) /* Makefile-mentioned file need not exist. */ 530 1.1 christos { 531 1.1 christos int e; 532 1.1 christos 533 1.1 christos EINTRLOOP (e, stat (name, &st)); /* Does it really exist? */ 534 1.1 christos if (e != 0) 535 1.1 christos { 536 1.1 christos exists = 0; 537 1.1 christos continue; 538 1.1 christos } 539 1.1 christos 540 1.1 christos /* Store the modtime into *MTIME_PTR for the caller. */ 541 1.1 christos if (mtime_ptr != 0) 542 1.1 christos { 543 1.1 christos *mtime_ptr = FILE_TIMESTAMP_STAT_MODTIME (name, st); 544 1.1 christos mtime_ptr = 0; 545 1.1 christos } 546 1.1 christos } 547 1.1 christos 548 1.1 christos /* We have found a file. 549 1.1 christos Store the name we found into *FILE for the caller. */ 550 1.1 christos 551 1.1 christos *file = savestring (name, (n + 1 - name) + flen); 552 1.1 christos 553 1.1 christos /* If we get here and mtime_ptr hasn't been set, record 554 1.1 christos UNKNOWN_MTIME to indicate this. */ 555 1.1 christos if (mtime_ptr != 0) 556 1.1 christos *mtime_ptr = UNKNOWN_MTIME; 557 1.1 christos 558 1.1 christos free (name); 559 1.1 christos return 1; 560 1.1 christos } 561 1.1 christos } 562 1.1 christos 563 1.1 christos free (name); 564 1.1 christos return 0; 565 1.1 christos } 566 1.1 christos 567 1.1 christos /* Print the data base of VPATH search paths. */ 569 1.1 christos 570 1.1 christos void 571 1.1 christos print_vpath_data_base (void) 572 1.1 christos { 573 1.1 christos register unsigned int nvpaths; 574 1.1 christos register struct vpath *v; 575 1.1 christos 576 1.1 christos puts (_("\n# VPATH Search Paths\n")); 577 1.1 christos 578 1.1 christos nvpaths = 0; 579 1.1 christos for (v = vpaths; v != 0; v = v->next) 580 1.1 christos { 581 1.1 christos register unsigned int i; 582 1.1 christos 583 1.1 christos ++nvpaths; 584 1.1 christos 585 1.1 christos printf ("vpath %s ", v->pattern); 586 1.1 christos 587 1.1 christos for (i = 0; v->searchpath[i] != 0; ++i) 588 1.1 christos printf ("%s%c", v->searchpath[i], 589 1.1 christos v->searchpath[i + 1] == 0 ? '\n' : PATH_SEPARATOR_CHAR); 590 1.1 christos } 591 1.1 christos 592 1.1 christos if (vpaths == 0) 593 1.1 christos puts (_("# No `vpath' search paths.")); 594 1.1 christos else 595 1.1 christos printf (_("\n# %u `vpath' search paths.\n"), nvpaths); 596 1.1 christos 597 1.1 christos if (general_vpath == 0) 598 1.1 christos puts (_("\n# No general (`VPATH' variable) search path.")); 599 1.1 christos else 600 1.1 christos { 601 1.1 christos register char **path = general_vpath->searchpath; 602 1.1 christos register unsigned int i; 603 1.1 christos 604 1.1 christos fputs (_("\n# General (`VPATH' variable) search path:\n# "), stdout); 605 1.1 christos 606 for (i = 0; path[i] != 0; ++i) 607 printf ("%s%c", path[i], 608 path[i + 1] == 0 ? '\n' : PATH_SEPARATOR_CHAR); 609 } 610 } 611