11590Srgrimes/* Implementation of pattern-matching file search paths for GNU Make. 21590SrgrimesCopyright (C) 1988,89,91,92,93,94,95,96,97 Free Software Foundation, Inc. 31590SrgrimesThis file is part of GNU Make. 41590Srgrimes 51590SrgrimesGNU Make is free software; you can redistribute it and/or modify 61590Srgrimesit under the terms of the GNU General Public License as published by 71590Srgrimesthe Free Software Foundation; either version 2, or (at your option) 81590Srgrimesany later version. 91590Srgrimes 101590SrgrimesGNU Make is distributed in the hope that it will be useful, 111590Srgrimesbut WITHOUT ANY WARRANTY; without even the implied warranty of 121590SrgrimesMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 131590SrgrimesGNU General Public License for more details. 141590Srgrimes 151590SrgrimesYou should have received a copy of the GNU General Public License 161590Srgrimesalong with GNU Make; see the file COPYING. If not, write to 171590Srgrimesthe Free Software Foundation, Inc., 59 Temple Place - Suite 330, 181590SrgrimesBoston, MA 02111-1307, USA. */ 191590Srgrimes 201590Srgrimes#include "make.h" 211590Srgrimes#include "filedef.h" 221590Srgrimes#include "variable.h" 231590Srgrimes#ifdef WINDOWS32 241590Srgrimes#include "pathstuff.h" 251590Srgrimes#endif 261590Srgrimes 271590Srgrimes 281590Srgrimes/* Structure used to represent a selective VPATH searchpath. */ 291590Srgrimes 301590Srgrimesstruct vpath 311590Srgrimes { 321590Srgrimes struct vpath *next; /* Pointer to next struct in the linked list. */ 331590Srgrimes char *pattern; /* The pattern to match. */ 341590Srgrimes char *percent; /* Pointer into `pattern' where the `%' is. */ 351590Srgrimes unsigned int patlen;/* Length of the pattern. */ 361590Srgrimes char **searchpath; /* Null-terminated list of directories. */ 37207705Sdelphij unsigned int maxlen;/* Maximum length of any entry in the list. */ 38207705Sdelphij }; 39207705Sdelphij 40207705Sdelphij/* Linked-list of all selective VPATHs. */ 41207705Sdelphij 42207705Sdelphijstatic struct vpath *vpaths; 4393604Sobrien 4493604Sobrien/* Structure for the general VPATH given in the variable. */ 451590Srgrimes 461590Srgrimesstatic struct vpath *general_vpath; 471590Srgrimes 481590Srgrimes/* Structure for GPATH given in the variable. */ 491590Srgrimes 501590Srgrimesstatic struct vpath *gpaths; 5172945Sknu 52200462Sdelphijstatic int selective_vpath_search PARAMS ((struct vpath *path, char **file, FILE_TIMESTAMP *mtime_ptr)); 531590Srgrimes 541590Srgrimes/* Reverse the chain of selective VPATH lists so they 551590Srgrimes will be searched in the order given in the makefiles 561590Srgrimes and construct the list from the VPATH variable. */ 571590Srgrimes 58207705Sdelphijvoid 5991400Sdwmalonebuild_vpath_lists () 601590Srgrimes{ 61176478Simp register struct vpath *new = 0; 621590Srgrimes register struct vpath *old, *nexto; 6376250Sphk register char *p; 6476250Sphk 6576250Sphk /* Reverse the chain. */ 66157555Sceri for (old = vpaths; old != 0; old = nexto) 67157555Sceri { 68157555Sceri nexto = old->next; 6976250Sphk old->next = new; 70127796Sbmilekic new = old; 7176250Sphk } 7276250Sphk 7376250Sphk vpaths = new; 7476250Sphk 7576250Sphk /* If there is a VPATH variable with a nonnull value, construct the 7676250Sphk general VPATH list from it. We use variable_expand rather than just 7776250Sphk calling lookup_variable so that it will be recursively expanded. */ 78176478Simp 79176478Simp { 8076250Sphk /* Turn off --warn-undefined-variables while we expand SHELL and IFS. */ 81129812Seik int save = warn_undefined_variables_flag; 8276250Sphk warn_undefined_variables_flag = 0; 8376250Sphk 8476250Sphk p = variable_expand ("$(strip $(VPATH))"); 85176478Simp 8676250Sphk warn_undefined_variables_flag = save; 87176478Simp } 8876250Sphk 89176478Simp if (*p != '\0') 90176478Simp { 91176478Simp /* Save the list of vpaths. */ 9276250Sphk struct vpath *save_vpaths = vpaths; 93176478Simp 9476250Sphk /* Empty `vpaths' so the new one will have no next, and `vpaths' 95176478Simp will still be nil if P contains no existing directories. */ 96176478Simp vpaths = 0; 9776250Sphk 9876250Sphk /* Parse P. */ 9976250Sphk construct_vpath_list ("%", p); 10076250Sphk 101176478Simp /* Store the created path as the general path, 10276250Sphk and restore the old list of vpaths. */ 103176478Simp general_vpath = vpaths; 10476250Sphk vpaths = save_vpaths; 10576250Sphk } 10676250Sphk 10776250Sphk /* If there is a GPATH variable with a nonnull value, construct the 10876250Sphk GPATH list from it. We use variable_expand rather than just 109176478Simp calling lookup_variable so that it will be recursively expanded. */ 11076250Sphk 11176250Sphk { 11276250Sphk /* Turn off --warn-undefined-variables while we expand SHELL and IFS. */ 113157555Sceri int save = warn_undefined_variables_flag; 114157555Sceri warn_undefined_variables_flag = 0; 115157555Sceri 116157555Sceri p = variable_expand ("$(strip $(GPATH))"); 117157555Sceri 118157555Sceri warn_undefined_variables_flag = save; 11976250Sphk } 12076250Sphk 12176250Sphk if (*p != '\0') 12276250Sphk { 123157555Sceri /* Save the list of vpaths. */ 12476250Sphk struct vpath *save_vpaths = vpaths; 12576250Sphk 12676250Sphk /* Empty `vpaths' so the new one will have no next, and `vpaths' 12776250Sphk will still be nil if P contains no existing directories. */ 128157555Sceri vpaths = 0; 12976250Sphk 13076250Sphk /* Parse P. */ 13176250Sphk construct_vpath_list ("%", p); 13276250Sphk 13376250Sphk /* Store the created path as the GPATH, 134176478Simp and restore the old list of vpaths. */ 135176478Simp gpaths = vpaths; 136111084Sdes vpaths = save_vpaths; 13776250Sphk } 13876250Sphk} 13976250Sphk 14076250Sphk/* Construct the VPATH listing for the pattern and searchpath given. 14176250Sphk 14276250Sphk This function is called to generate selective VPATH lists and also for 14376250Sphk the general VPATH list (which is in fact just a selective VPATH that 14476250Sphk is applied to everything). The returned pointer is either put in the 14576250Sphk linked list of all selective VPATH lists or in the GENERAL_VPATH 146176478Simp variable. 14776250Sphk 148176478Simp If SEARCHPATH is nil, remove all previous listings with the same 14976250Sphk pattern. If PATTERN is nil, remove all VPATH listings. Existing 150176478Simp and readable directories that are not "." given in the searchpath 15176250Sphk separated by the path element separator (defined in make.h) are 152176478Simp loaded into the directory hash table if they are not there already 15376250Sphk and put in the VPATH searchpath for the given pattern with trailing 154176478Simp slashes stripped off if present (and if the directory is not the 15576250Sphk root, "/"). The length of the longest entry in the list is put in 156176478Simp the structure as well. The new entry will be at the head of the 15776250Sphk VPATHS chain. */ 158176478Simp 1591590Srgrimesvoid 1601590Srgrimesconstruct_vpath_list (pattern, dirpath) 1611590Srgrimes char *pattern, *dirpath; 1621590Srgrimes{ 1631590Srgrimes register unsigned int elem; 1641590Srgrimes register char *p; 1651590Srgrimes register char **vpath; 1661590Srgrimes register unsigned int maxvpath; 1671590Srgrimes unsigned int maxelem; 1681590Srgrimes char *percent = NULL; 1691590Srgrimes 170116333Smarkm if (pattern != 0) 1711590Srgrimes { 17291400Sdwmalone pattern = xstrdup (pattern); 1731590Srgrimes percent = find_percent (pattern); 1741590Srgrimes } 1751590Srgrimes 1761590Srgrimes if (dirpath == 0) 1771590Srgrimes { 17891400Sdwmalone /* Remove matching listings. */ 1791590Srgrimes register struct vpath *path, *lastpath; 1801590Srgrimes 1811590Srgrimes lastpath = 0; 18276250Sphk path = vpaths; 1831590Srgrimes while (path != 0) 1841590Srgrimes { 1851590Srgrimes struct vpath *next = path->next; 1861590Srgrimes 18776250Sphk if (pattern == 0 188116333Smarkm || (((percent == 0 && path->percent == 0) 1891590Srgrimes || (percent - pattern == path->percent - path->pattern)) 1901590Srgrimes && streq (pattern, path->pattern))) 1911590Srgrimes { 1921590Srgrimes /* Remove it from the linked list. */ 1931590Srgrimes if (lastpath == 0) 1941590Srgrimes vpaths = path->next; 1951590Srgrimes else 1961590Srgrimes lastpath->next = next; 197207705Sdelphij 198116333Smarkm /* Free its unused storage. */ 1991590Srgrimes free (path->pattern); 20091400Sdwmalone free ((char *) path->searchpath); 2011590Srgrimes free ((char *) path); 202 } 203 else 204 lastpath = path; 205 206 path = next; 207 } 208 209 if (pattern != 0) 210 free (pattern); 211 return; 212 } 213 214#ifdef WINDOWS32 215 convert_vpath_to_windows32(dirpath, ';'); 216#endif 217 218 /* Figure out the maximum number of VPATH entries and put it in 219 MAXELEM. We start with 2, one before the first separator and one 220 nil (the list terminator) and increment our estimated number for 221 each separator or blank we find. */ 222 maxelem = 2; 223 p = dirpath; 224 while (*p != '\0') 225 if (*p++ == PATH_SEPARATOR_CHAR || isblank ((unsigned char)*p)) 226 ++maxelem; 227 228 vpath = (char **) xmalloc (maxelem * sizeof (char *)); 229 maxvpath = 0; 230 231 /* Skip over any initial separators and blanks. */ 232 p = dirpath; 233 while (*p == PATH_SEPARATOR_CHAR || isblank ((unsigned char)*p)) 234 ++p; 235 236 elem = 0; 237 while (*p != '\0') 238 { 239 char *v; 240 unsigned int len; 241 242 /* Find the end of this entry. */ 243 v = p; 244 while (*p != '\0' && *p != PATH_SEPARATOR_CHAR 245 && !isblank ((unsigned char)*p)) 246 ++p; 247 248 len = p - v; 249 /* Make sure there's no trailing slash, 250 but still allow "/" as a directory. */ 251#ifdef __MSDOS__ 252 /* We need also to leave alone a trailing slash in "d:/". */ 253 if (len > 3 || (len > 1 && v[1] != ':')) 254#endif 255 if (len > 1 && p[-1] == '/') 256 --len; 257 258 if (len > 1 || *v != '.') 259 { 260 v = savestring (v, len); 261 262 /* Verify that the directory actually exists. */ 263 264 if (dir_file_exists_p (v, "")) 265 { 266 /* It does. Put it in the list. */ 267 vpath[elem++] = dir_name (v); 268 free (v); 269 if (len > maxvpath) 270 maxvpath = len; 271 } 272 else 273 /* The directory does not exist. Omit from the list. */ 274 free (v); 275 } 276 277 /* Skip over separators and blanks between entries. */ 278 while (*p == PATH_SEPARATOR_CHAR || isblank ((unsigned char)*p)) 279 ++p; 280 } 281 282 if (elem > 0) 283 { 284 struct vpath *path; 285 /* ELEM is now incremented one element past the last 286 entry, to where the nil-pointer terminator goes. 287 Usually this is maxelem - 1. If not, shrink down. */ 288 if (elem < (maxelem - 1)) 289 vpath = (char **) xrealloc ((char *) vpath, 290 (elem + 1) * sizeof (char *)); 291 292 /* Put the nil-pointer terminator on the end of the VPATH list. */ 293 vpath[elem] = 0; 294 295 /* Construct the vpath structure and put it into the linked list. */ 296 path = (struct vpath *) xmalloc (sizeof (struct vpath)); 297 path->searchpath = vpath; 298 path->maxlen = maxvpath; 299 path->next = vpaths; 300 vpaths = path; 301 302 /* Set up the members. */ 303 path->pattern = pattern; 304 path->percent = percent; 305 path->patlen = strlen (pattern); 306 } 307 else 308 { 309 /* There were no entries, so free whatever space we allocated. */ 310 free ((char *) vpath); 311 if (pattern != 0) 312 free (pattern); 313 } 314} 315 316/* Search the GPATH list for a pathname string that matches the one passed 317 in. If it is found, return 1. Otherwise we return 0. */ 318 319int 320gpath_search (file, len) 321 char *file; 322 int len; 323{ 324 register char **gp; 325 326 if (gpaths && (len <= gpaths->maxlen)) 327 for (gp = gpaths->searchpath; *gp != NULL; ++gp) 328 if (strneq (*gp, file, len) && (*gp)[len] == '\0') 329 return 1; 330 331 return 0; 332} 333 334/* Search the VPATH list whose pattern matches *FILE for a directory 335 where the name pointed to by FILE exists. If it is found, we set *FILE to 336 the newly malloc'd name of the existing file, *MTIME_PTR (if MTIME_PTR is 337 not NULL) to its modtime (or zero if no stat call was done), and return 1. 338 Otherwise we return 0. */ 339 340int 341vpath_search (file, mtime_ptr) 342 char **file; 343 FILE_TIMESTAMP *mtime_ptr; 344{ 345 register struct vpath *v; 346 347 /* If there are no VPATH entries or FILENAME starts at the root, 348 there is nothing we can do. */ 349 350 if (**file == '/' 351#ifdef HAVE_DOS_PATHS 352 || **file == '\\' 353 || (*file)[1] == ':' 354#endif 355 || (vpaths == 0 && general_vpath == 0)) 356 return 0; 357 358 for (v = vpaths; v != 0; v = v->next) 359 if (pattern_matches (v->pattern, v->percent, *file)) 360 if (selective_vpath_search (v, file, mtime_ptr)) 361 return 1; 362 363 if (general_vpath != 0 364 && selective_vpath_search (general_vpath, file, mtime_ptr)) 365 return 1; 366 367 return 0; 368} 369 370 371/* Search the given VPATH list for a directory where the name pointed 372 to by FILE exists. If it is found, we set *FILE to the newly malloc'd 373 name of the existing file, *MTIME_PTR (if MTIME_PTR is not NULL) to 374 its modtime (or zero if no stat call was done), and we return 1. 375 Otherwise we return 0. */ 376 377static int 378selective_vpath_search (path, file, mtime_ptr) 379 struct vpath *path; 380 char **file; 381 FILE_TIMESTAMP *mtime_ptr; 382{ 383 int not_target; 384 char *name, *n; 385 char *filename; 386 register char **vpath = path->searchpath; 387 unsigned int maxvpath = path->maxlen; 388 register unsigned int i; 389 unsigned int flen, vlen, name_dplen; 390 int exists = 0; 391 392 /* Find out if *FILE is a target. 393 If and only if it is NOT a target, we will accept prospective 394 files that don't exist but are mentioned in a makefile. */ 395 { 396 struct file *f = lookup_file (*file); 397 not_target = f == 0 || !f->is_target; 398 } 399 400 flen = strlen (*file); 401 402 /* Split *FILE into a directory prefix and a name-within-directory. 403 NAME_DPLEN gets the length of the prefix; FILENAME gets the 404 pointer to the name-within-directory and FLEN is its length. */ 405 406 n = strrchr (*file, '/'); 407#ifdef HAVE_DOS_PATHS 408 /* We need the rightmost slash or backslash. */ 409 { 410 char *bslash = strrchr(*file, '\\'); 411 if (!n || bslash > n) 412 n = bslash; 413 } 414#endif 415 name_dplen = n != 0 ? n - *file : 0; 416 filename = name_dplen > 0 ? n + 1 : *file; 417 if (name_dplen > 0) 418 flen -= name_dplen + 1; 419 420 /* Allocate enough space for the biggest VPATH entry, 421 a slash, the directory prefix that came with *FILE, 422 another slash (although this one may not always be 423 necessary), the filename, and a null terminator. */ 424 name = (char *) xmalloc (maxvpath + 1 + name_dplen + 1 + flen + 1); 425 426 /* Try each VPATH entry. */ 427 for (i = 0; vpath[i] != 0; ++i) 428 { 429 int exists_in_cache = 0; 430 431 n = name; 432 433 /* Put the next VPATH entry into NAME at N and increment N past it. */ 434 vlen = strlen (vpath[i]); 435 bcopy (vpath[i], n, vlen); 436 n += vlen; 437 438 /* Add the directory prefix already in *FILE. */ 439 if (name_dplen > 0) 440 { 441#ifndef VMS 442 *n++ = '/'; 443#endif 444 bcopy (*file, n, name_dplen); 445 n += name_dplen; 446 } 447 448#ifdef HAVE_DOS_PATHS 449 /* Cause the next if to treat backslash and slash alike. */ 450 if (n != name && n[-1] == '\\' ) 451 n[-1] = '/'; 452#endif 453 /* Now add the name-within-directory at the end of NAME. */ 454#ifndef VMS 455 if (n != name && n[-1] != '/') 456 { 457 *n = '/'; 458 bcopy (filename, n + 1, flen + 1); 459 } 460 else 461#endif 462 bcopy (filename, n, flen + 1); 463 464 /* Check if the file is mentioned in a makefile. If *FILE is not 465 a target, that is enough for us to decide this file exists. 466 If *FILE is a target, then the file must be mentioned in the 467 makefile also as a target to be chosen. 468 469 The restriction that *FILE must not be a target for a 470 makefile-mentioned file to be chosen was added by an 471 inadequately commented change in July 1990; I am not sure off 472 hand what problem it fixes. 473 474 In December 1993 I loosened this restriction to allow a file 475 to be chosen if it is mentioned as a target in a makefile. This 476 seem logical. */ 477 { 478 struct file *f = lookup_file (name); 479 if (f != 0) 480 exists = not_target || f->is_target; 481 } 482 483 if (!exists) 484 { 485 /* That file wasn't mentioned in the makefile. 486 See if it actually exists. */ 487 488#ifdef VMS 489 exists_in_cache = exists = dir_file_exists_p (vpath[i], filename); 490#else 491 /* Clobber a null into the name at the last slash. 492 Now NAME is the name of the directory to look in. */ 493 *n = '\0'; 494 495 /* We know the directory is in the hash table now because either 496 construct_vpath_list or the code just above put it there. 497 Does the file we seek exist in it? */ 498 exists_in_cache = exists = dir_file_exists_p (name, filename); 499#endif 500 } 501 502 if (exists) 503 { 504 /* The file is in the directory cache. 505 Now check that it actually exists in the filesystem. 506 The cache may be out of date. When vpath thinks a file 507 exists, but stat fails for it, confusion results in the 508 higher levels. */ 509 510 struct stat st; 511 512#ifndef VMS 513 /* Put the slash back in NAME. */ 514 *n = '/'; 515#endif 516 517 if (!exists_in_cache /* Makefile-mentioned file need not exist. */ 518 || stat (name, &st) == 0) /* Does it really exist? */ 519 { 520 /* We have found a file. 521 Store the name we found into *FILE for the caller. */ 522 523 *file = savestring (name, (n + 1 - name) + flen); 524 525 if (mtime_ptr != 0) 526 /* Store the modtime into *MTIME_PTR for the caller. 527 If we have had no need to stat the file here, 528 we record UNKNOWN_MTIME to indicate this. */ 529 *mtime_ptr = (exists_in_cache 530 ? FILE_TIMESTAMP_STAT_MODTIME (name, st) 531 : UNKNOWN_MTIME); 532 533 free (name); 534 return 1; 535 } 536 else 537 exists = 0; 538 } 539 } 540 541 free (name); 542 return 0; 543} 544 545/* Print the data base of VPATH search paths. */ 546 547void 548print_vpath_data_base () 549{ 550 register unsigned int nvpaths; 551 register struct vpath *v; 552 553 puts (_("\n# VPATH Search Paths\n")); 554 555 nvpaths = 0; 556 for (v = vpaths; v != 0; v = v->next) 557 { 558 register unsigned int i; 559 560 ++nvpaths; 561 562 printf ("vpath %s ", v->pattern); 563 564 for (i = 0; v->searchpath[i] != 0; ++i) 565 printf ("%s%c", v->searchpath[i], 566 v->searchpath[i + 1] == 0 ? '\n' : PATH_SEPARATOR_CHAR); 567 } 568 569 if (vpaths == 0) 570 puts (_("# No `vpath' search paths.")); 571 else 572 printf (_("\n# %u `vpath' search paths.\n"), nvpaths); 573 574 if (general_vpath == 0) 575 puts (_("\n# No general (`VPATH' variable) search path.")); 576 else 577 { 578 register char **path = general_vpath->searchpath; 579 register unsigned int i; 580 581 fputs (_("\n# General (`VPATH' variable) search path:\n# "), stdout); 582 583 for (i = 0; path[i] != 0; ++i) 584 printf ("%s%c", path[i], 585 path[i + 1] == 0 ? '\n' : PATH_SEPARATOR_CHAR); 586 } 587} 588