~ubuntu-branches/ubuntu/hardy/pmake/hardy

« back to all changes in this revision

Viewing changes to dir.c

  • Committer: Bazaar Package Importer
  • Author(s): Sam Hocevar (Debian packages)
  • Date: 2004-03-12 13:14:27 UTC
  • mfrom: (0.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040312131427-us94ehmatt3kxhm8
Tags: 1.98-3
* mk/bsd.man.mk:
  + Use symlinks instead of hard links when using the MLINKS directive
    to link manual pages, courtesy of Robert Millan.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*      $NetBSD: dir.c,v 1.20 1997/09/28 03:31:02 lukem Exp $   */
 
1
/*      $NetBSD: dir.c,v 1.40 2004/02/03 19:25:29 chuck Exp $   */
2
2
 
3
3
/*
4
4
 * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
 
5
 * All rights reserved.
 
6
 *
 
7
 * This code is derived from software contributed to Berkeley by
 
8
 * Adam de Boor.
 
9
 *
 
10
 * Redistribution and use in source and binary forms, with or without
 
11
 * modification, are permitted provided that the following conditions
 
12
 * are met:
 
13
 * 1. Redistributions of source code must retain the above copyright
 
14
 *    notice, this list of conditions and the following disclaimer.
 
15
 * 2. Redistributions in binary form must reproduce the above copyright
 
16
 *    notice, this list of conditions and the following disclaimer in the
 
17
 *    documentation and/or other materials provided with the distribution.
 
18
 * 3. Neither the name of the University nor the names of its contributors
 
19
 *    may be used to endorse or promote products derived from this software
 
20
 *    without specific prior written permission.
 
21
 *
 
22
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 
23
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
24
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
25
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 
26
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
27
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 
28
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
29
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 
30
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 
31
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 
32
 * SUCH DAMAGE.
 
33
 */
 
34
 
 
35
/*
5
36
 * Copyright (c) 1988, 1989 by Adam de Boor
6
37
 * Copyright (c) 1989 by Berkeley Softworks
7
38
 * All rights reserved.
39
70
 */
40
71
 
41
72
#ifdef MAKE_BOOTSTRAP
42
 
static char rcsid[] = "$NetBSD: dir.c,v 1.20 1997/09/28 03:31:02 lukem Exp $";
 
73
static char rcsid[] = "$NetBSD: dir.c,v 1.40 2004/02/03 19:25:29 chuck Exp $";
43
74
#else
44
75
#include <sys/cdefs.h>
45
76
#ifndef lint
46
77
#if 0
47
78
static char sccsid[] = "@(#)dir.c       8.2 (Berkeley) 1/2/94";
48
79
#else
49
 
__RCSID("$NetBSD: dir.c,v 1.20 1997/09/28 03:31:02 lukem Exp $");
 
80
__RCSID("$NetBSD: dir.c,v 1.40 2004/02/03 19:25:29 chuck Exp $");
50
81
#endif
51
82
#endif /* not lint */
52
83
#endif
60
91
 * The interface for this module is:
61
92
 *      Dir_Init            Initialize the module.
62
93
 *
 
94
 *      Dir_InitCur         Set the cur Path.
 
95
 *
 
96
 *      Dir_InitDot         Set the dot Path.
 
97
 *
63
98
 *      Dir_End             Cleanup the module.
64
99
 *
 
100
 *      Dir_SetPATH         Set ${.PATH} to reflect state of dirSearchPath.
 
101
 *
65
102
 *      Dir_HasWildcards    Returns TRUE if the name given it needs to
66
103
 *                          be wildcard-expanded.
67
104
 *
72
109
 *                          If it exists, the entire path is returned.
73
110
 *                          Otherwise NULL is returned.
74
111
 *
 
112
 *      Dir_FindHereOrAbove Search for a path in the current directory and
 
113
 *                          then all the directories above it in turn until
 
114
 *                          the path is found or we reach the root ("/").
 
115
 * 
75
116
 *      Dir_MTime           Return the modification time of a node. The file
76
117
 *                          is searched for along the default search path.
77
118
 *                          The path and mtime fields of the node are filled
94
135
 *      Dir_PrintDirectories    Print stats about the directory cache.
95
136
 */
96
137
 
97
 
#include <stdio.h>
98
138
#include <sys/types.h>
 
139
#include <sys/stat.h>
 
140
 
99
141
#include <dirent.h>
100
 
#include <sys/stat.h>
 
142
#include <errno.h>
 
143
#include <stdio.h>
 
144
 
101
145
#include "make.h"
102
146
#include "hash.h"
103
147
#include "dir.h"
187
231
 
188
232
static Path       *dot;     /* contents of current directory */
189
233
static Path       *cur;     /* contents of current directory, if not dot */
 
234
static Path       *dotLast; /* a fake path entry indicating we need to
 
235
                             * look for . last */
190
236
static Hash_Table mtimes;   /* Results of doing a last-resort stat in
191
237
                             * Dir_FindFile -- if we have to go to the
192
238
                             * system to find the file, we might as well
198
244
                             * should be ok, but... */
199
245
 
200
246
 
201
 
static int DirFindName __P((ClientData, ClientData));
202
 
static int DirMatchFiles __P((char *, Path *, Lst));
203
 
static void DirExpandCurly __P((char *, char *, Lst, Lst));
204
 
static void DirExpandInt __P((char *, Lst, Lst));
205
 
static int DirPrintWord __P((ClientData, ClientData));
206
 
static int DirPrintDir __P((ClientData, ClientData));
207
 
static char *DirLookup __P((Path *, char *, char *, Boolean));
208
 
static char *DirLookupSubdir __P((Path *, char *));
 
247
static int DirFindName(ClientData, ClientData);
 
248
static int DirMatchFiles(const char *, Path *, Lst);
 
249
static void DirExpandCurly(const char *, const char *, Lst, Lst);
 
250
static void DirExpandInt(const char *, Lst, Lst);
 
251
static int DirPrintWord(ClientData, ClientData);
 
252
static int DirPrintDir(ClientData, ClientData);
 
253
static char *DirLookup(Path *, const char *, const char *, Boolean);
 
254
static char *DirLookupSubdir(Path *, const char *);
 
255
static char *DirFindDot(Boolean, const char *, const char *);
 
256
static char *DirLookupAbs(Path *, const char *, const char *);
209
257
 
210
258
/*-
211
259
 *-----------------------------------------------------------------------
220
268
 *-----------------------------------------------------------------------
221
269
 */
222
270
void
223
 
Dir_Init (cdname)
224
 
    const char *cdname;
 
271
Dir_Init (const char *cdname)
225
272
{
226
273
    dirSearchPath = Lst_Init (FALSE);
227
274
    openDirectories = Lst_Init (FALSE);
228
275
    Hash_InitTable(&mtimes, 0);
229
276
 
230
 
    /*
231
 
     * Since the Path structure is placed on both openDirectories and
232
 
     * the path we give Dir_AddDir (which in this case is openDirectories),
233
 
     * we need to remove "." from openDirectories and what better time to
234
 
     * do it than when we have to fetch the thing anyway?
235
 
     */
 
277
    Dir_InitCur(cdname);
 
278
 
 
279
    dotLast = (Path *) emalloc (sizeof (Path));
 
280
    dotLast->refCount = 1;
 
281
    dotLast->hits = 0;
 
282
    dotLast->name = estrdup(".DOTLAST");
 
283
    Hash_InitTable (&dotLast->files, -1);
 
284
}
 
285
 
 
286
/*
 
287
 * Called by Dir_Init() and whenever .CURDIR is assigned to.
 
288
 */
 
289
void
 
290
Dir_InitCur (const char *cdname)
 
291
{
 
292
    Path *p;
 
293
    
 
294
    if (cdname != NULL) {
 
295
        /*
 
296
         * Our build directory is not the same as our source directory.
 
297
         * Keep this one around too.
 
298
         */
 
299
        if ((p = Dir_AddDir(NULL, cdname))) {
 
300
            p->refCount += 1;
 
301
            if (cur && cur != p) {
 
302
                /*
 
303
                 * We've been here before, cleanup.
 
304
                 */
 
305
                cur->refCount -= 1;
 
306
                Dir_Destroy((ClientData) cur);
 
307
            }
 
308
            cur = p;
 
309
        }
 
310
    }
 
311
}
 
312
 
 
313
/*-
 
314
 *-----------------------------------------------------------------------
 
315
 * Dir_InitDot --
 
316
 *      (re)initialize "dot" (current/object directory) path hash
 
317
 *
 
318
 * Results:
 
319
 *      none
 
320
 *
 
321
 * Side Effects:
 
322
 *      some directories may be opened.
 
323
 *-----------------------------------------------------------------------
 
324
 */
 
325
void
 
326
Dir_InitDot(void)
 
327
{
 
328
    if (dot != NULL) {
 
329
        LstNode ln;
 
330
 
 
331
        /* Remove old entry from openDirectories, but do not destroy. */
 
332
        ln = Lst_Member (openDirectories, (ClientData)dot);
 
333
        (void) Lst_Remove (openDirectories, ln);
 
334
    }
 
335
 
236
336
    dot = Dir_AddDir (NULL, ".");
237
337
 
 
338
    if (dot == NULL) {
 
339
        Error("Cannot open `.' (%s)", strerror(errno));
 
340
        exit(1);
 
341
    }
 
342
 
238
343
    /*
239
344
     * We always need to have dot around, so we increment its reference count
240
345
     * to make sure it's not destroyed.
241
346
     */
242
347
    dot->refCount += 1;
243
 
 
244
 
    if (cdname != NULL) {
245
 
        /*
246
 
         * Our build directory is not the same as our source directory.
247
 
         * Keep this one around too.
248
 
         */
249
 
        cur = Dir_AddDir (NULL, cdname);
250
 
        cur->refCount += 1;
251
 
    }
 
348
    Dir_SetPATH();                      /* initialize */
252
349
}
253
350
 
254
351
/*-
264
361
 *-----------------------------------------------------------------------
265
362
 */
266
363
void
267
 
Dir_End()
 
364
Dir_End(void)
268
365
{
 
366
#ifdef CLEANUP
269
367
    if (cur) {
270
368
        cur->refCount -= 1;
271
369
        Dir_Destroy((ClientData) cur);
272
370
    }
273
371
    dot->refCount -= 1;
 
372
    dotLast->refCount -= 1;
 
373
    Dir_Destroy((ClientData) dotLast);
274
374
    Dir_Destroy((ClientData) dot);
275
375
    Dir_ClearPath(dirSearchPath);
276
376
    Lst_Destroy(dirSearchPath, NOFREE);
277
377
    Dir_ClearPath(openDirectories);
278
378
    Lst_Destroy(openDirectories, NOFREE);
279
379
    Hash_DeleteTable(&mtimes);
 
380
#endif
 
381
}
 
382
 
 
383
/*
 
384
 * We want ${.PATH} to indicate the order in which we will actually
 
385
 * search, so we rebuild it after any .PATH: target.
 
386
 * This is the simplest way to deal with the effect of .DOTLAST.
 
387
 */
 
388
void
 
389
Dir_SetPATH (void)
 
390
{
 
391
    LstNode       ln;           /* a list element */
 
392
    Path *p;
 
393
    Boolean       hasLastDot = FALSE;   /* true we should search dot last */
 
394
 
 
395
    Var_Delete(".PATH", VAR_GLOBAL);
 
396
    
 
397
    if (Lst_Open (dirSearchPath) == SUCCESS) {
 
398
        if ((ln = Lst_First (dirSearchPath)) != NILLNODE) {
 
399
            p = (Path *) Lst_Datum (ln);
 
400
            if (p == dotLast) {
 
401
                hasLastDot = TRUE;
 
402
                Var_Append(".PATH", dotLast->name, VAR_GLOBAL);
 
403
            }
 
404
        }
 
405
 
 
406
        if (!hasLastDot) {
 
407
            if (dot)
 
408
                Var_Append(".PATH", dot->name, VAR_GLOBAL);
 
409
            if (cur)
 
410
                Var_Append(".PATH", cur->name, VAR_GLOBAL);
 
411
        }
 
412
 
 
413
        while ((ln = Lst_Next (dirSearchPath)) != NILLNODE) {
 
414
            p = (Path *) Lst_Datum (ln);
 
415
            if (p == dotLast)
 
416
                continue;
 
417
            if (p == dot && hasLastDot)
 
418
                continue;
 
419
            Var_Append(".PATH", p->name, VAR_GLOBAL);
 
420
        }
 
421
 
 
422
        if (hasLastDot) {
 
423
            if (dot)
 
424
                Var_Append(".PATH", dot->name, VAR_GLOBAL);
 
425
            if (cur)
 
426
                Var_Append(".PATH", cur->name, VAR_GLOBAL);
 
427
        }
 
428
        Lst_Close(dirSearchPath);
 
429
    }
280
430
}
281
431
 
282
432
/*-
286
436
 *      given one by comparing their names. Called from Dir_AddDir via
287
437
 *      Lst_Find when searching the list of open directories.
288
438
 *
 
439
 * Input:
 
440
 *      p               Current name
 
441
 *      dname           Desired name
 
442
 *
289
443
 * Results:
290
444
 *      0 if it is the same. Non-zero otherwise
291
445
 *
294
448
 *-----------------------------------------------------------------------
295
449
 */
296
450
static int
297
 
DirFindName (p, dname)
298
 
    ClientData    p;          /* Current name */
299
 
    ClientData    dname;      /* Desired name */
 
451
DirFindName(ClientData p, ClientData dname)
300
452
{
301
453
    return (strcmp (((Path *)p)->name, (char *) dname));
302
454
}
311
463
 *      patterns, because then you have to set a mechanism for
312
464
 *      escaping the expansion!
313
465
 *
 
466
 * Input:
 
467
 *      name            name to check
 
468
 *
314
469
 * Results:
315
470
 *      returns TRUE if the word should be expanded, FALSE otherwise
316
471
 *
319
474
 *-----------------------------------------------------------------------
320
475
 */
321
476
Boolean
322
 
Dir_HasWildcards (name)
323
 
    char          *name;        /* name to check */
 
477
Dir_HasWildcards(char *name)
324
478
{
325
 
    register char *cp;
 
479
    char *cp;
326
480
    int wild = 0, brace = 0, bracket = 0;
327
481
 
328
482
    for (cp = name; *cp; cp++) {
361
515
 *      src / *src / *.c properly (just *.c on any of the directories), but it
362
516
 *      will do for now.
363
517
 *
 
518
 * Input:
 
519
 *      pattern         Pattern to look for
 
520
 *      p               Directory to search
 
521
 *      expansion       Place to store the results
 
522
 *
364
523
 * Results:
365
524
 *      Always returns 0
366
525
 *
370
529
 *-----------------------------------------------------------------------
371
530
 */
372
531
static int
373
 
DirMatchFiles (pattern, p, expansions)
374
 
    char          *pattern;     /* Pattern to look for */
375
 
    Path          *p;           /* Directory to search */
376
 
    Lst           expansions;   /* Place to store the results */
 
532
DirMatchFiles(const char *pattern, Path *p, Lst expansions)
377
533
{
378
534
    Hash_Search   search;       /* Index into the directory's table */
379
535
    Hash_Entry    *entry;       /* Current entry in the table */
412
568
 *      done there are no wildcard characters in the result, the result is
413
569
 *      placed on the list WITHOUT CHECKING FOR ITS EXISTENCE.
414
570
 *
 
571
 * Input:
 
572
 *      word            Entire word to expand
 
573
 *      brace           First curly brace in it
 
574
 *      path            Search path to use
 
575
 *      expansions      Place to store the expansions
 
576
 *
415
577
 * Results:
416
578
 *      None.
417
579
 *
421
583
 *-----------------------------------------------------------------------
422
584
 */
423
585
static void
424
 
DirExpandCurly(word, brace, path, expansions)
425
 
    char          *word;        /* Entire word to expand */
426
 
    char          *brace;       /* First curly brace in it */
427
 
    Lst           path;         /* Search path to use */
428
 
    Lst           expansions;   /* Place to store the expansions */
 
586
DirExpandCurly(const char *word, const char *brace, Lst path, Lst expansions)
429
587
{
430
 
    char          *end;         /* Character after the closing brace */
431
 
    char          *cp;          /* Current position in brace clause */
432
 
    char          *start;       /* Start of current piece of brace clause */
 
588
    const char   *end;          /* Character after the closing brace */
 
589
    const char   *cp;           /* Current position in brace clause */
 
590
    const char   *start;        /* Start of current piece of brace clause */
433
591
    int           bracelevel;   /* Number of braces we've seen. If we see a
434
592
                                 * right brace when this is 0, we've hit the
435
593
                                 * end of the clause. */
436
 
    char          *file;        /* Current expansion */
 
594
    char         *file;         /* Current expansion */
437
595
    int           otherLen;     /* The length of the other pieces of the
438
596
                                 * expansion (chars before and after the
439
597
                                 * clause in 'word') */
440
 
    char          *cp2;         /* Pointer for checking for wildcards in
 
598
    char         *cp2;          /* Pointer for checking for wildcards in
441
599
                                 * expansion before calling Dir_Expand */
442
600
 
443
601
    start = brace+1;
523
681
 *      path one by one, calling DirMatchFiles for each. NOTE: This still
524
682
 *      doesn't handle patterns in directories...
525
683
 *
 
684
 * Input:
 
685
 *      word            Word to expand
 
686
 *      path            Path on which to look
 
687
 *      expansions      Place to store the result
 
688
 *
526
689
 * Results:
527
690
 *      None.
528
691
 *
532
695
 *-----------------------------------------------------------------------
533
696
 */
534
697
static void
535
 
DirExpandInt(word, path, expansions)
536
 
    char          *word;        /* Word to expand */
537
 
    Lst           path;         /* Path on which to look */
538
 
    Lst           expansions;   /* Place to store the result */
 
698
DirExpandInt(const char *word, Lst path, Lst expansions)
539
699
{
540
700
    LstNode       ln;           /* Current node */
541
701
    Path          *p;           /* Directory in the node */
564
724
 *-----------------------------------------------------------------------
565
725
 */
566
726
static int
567
 
DirPrintWord(word, dummy)
568
 
    ClientData  word;
569
 
    ClientData  dummy;
 
727
DirPrintWord(ClientData word, ClientData dummy)
570
728
{
571
729
    printf("%s ", (char *) word);
572
730
 
579
737
 *      Expand the given word into a list of words by globbing it looking
580
738
 *      in the directories on the given search path.
581
739
 *
 
740
 * Input:
 
741
 *      word            the word to expand
 
742
 *      path            the list of directories in which to find the
 
743
 *                      resulting files
 
744
 *      expansions      the list on which to place the results
 
745
 *
582
746
 * Results:
583
747
 *      A list of words consisting of the files which exist along the search
584
748
 *      path matching the given pattern.
588
752
 *-----------------------------------------------------------------------
589
753
 */
590
754
void
591
 
Dir_Expand (word, path, expansions)
592
 
    char    *word;      /* the word to expand */
593
 
    Lst     path;       /* the list of directories in which to find
594
 
                         * the resulting files */
595
 
    Lst     expansions; /* the list on which to place the results */
 
755
Dir_Expand(const char *word, Lst path, Lst expansions)
596
756
{
597
 
    char          *cp;
 
757
    const char            *cp;
598
758
 
599
759
    if (DEBUG(DIR)) {
600
 
        printf("expanding \"%s\"...", word);
 
760
        printf("Expanding \"%s\"... ", word);
601
761
    }
602
762
 
603
763
    cp = strchr(word, '{');
637
797
                     * all the components up to the one with a wildcard.
638
798
                     */
639
799
                    sc = cp[1];
640
 
                    cp[1] = '\0';
 
800
                    ((char *)UNCONST(cp))[1] = '\0';
641
801
                    dirpath = Dir_FindFile(word, path);
642
 
                    cp[1] = sc;
 
802
                    ((char *)UNCONST(cp))[1] = sc;
643
803
                    /*
644
804
                     * dirpath is null if can't find the leading component
645
805
                     * XXX: Dir_FindFile won't find internal components.
692
852
 *      Find if the file with the given name exists in the given path.
693
853
 *
694
854
 * Results:
695
 
 *      The path to the file, the empty string or NULL. If the file is
696
 
 *      the empty string, the search should be terminated.
697
 
 *      This path is guaranteed to be in a
 
855
 *      The path to the file or NULL. This path is guaranteed to be in a
698
856
 *      different part of memory than name and so may be safely free'd.
699
857
 *
700
858
 * Side Effects:
702
860
 *-----------------------------------------------------------------------
703
861
 */
704
862
static char *
705
 
DirLookup(p, name, cp, hasSlash)
706
 
    Path *p;
707
 
    char *name;
708
 
    char *cp;
709
 
    Boolean hasSlash;
 
863
DirLookup(Path *p, const char *name, const char *cp, Boolean hasSlash)
710
864
{
711
 
    char *p1;           /* pointer into p->name */
712
 
    char *p2;           /* pointer into name */
713
865
    char *file;         /* the current filename to check */
714
866
 
715
867
    if (DEBUG(DIR)) {
716
 
        printf("%s...", p->name);
717
 
    }
718
 
    if (Hash_FindEntry (&p->files, cp) != (Hash_Entry *)NULL) {
719
 
        if (DEBUG(DIR)) {
720
 
            printf("here...");
721
 
        }
722
 
        if (hasSlash) {
723
 
            /*
724
 
             * If the name had a slash, its initial components and p's
725
 
             * final components must match. This is false if a mismatch
726
 
             * is encountered before all of the initial components
727
 
             * have been checked (p2 > name at the end of the loop), or
728
 
             * we matched only part of one of the components of p
729
 
             * along with all the rest of them (*p1 != '/').
730
 
             */
731
 
            p1 = p->name + strlen (p->name) - 1;
732
 
            p2 = cp - 2;
733
 
            while (p2 >= name && p1 >= p->name && *p1 == *p2) {
734
 
                p1 -= 1; p2 -= 1;
735
 
            }
736
 
            if (p2 >= name || (p1 >= p->name && *p1 != '/')) {
737
 
                if (DEBUG(DIR)) {
738
 
                    printf("component mismatch -- continuing...");
739
 
                }
740
 
                return NULL;
741
 
            }
742
 
        }
743
 
        file = str_concat (p->name, cp, STR_ADDSLASH);
744
 
        if (DEBUG(DIR)) {
745
 
            printf("returning %s\n", file);
746
 
        }
747
 
        p->hits += 1;
748
 
        hits += 1;
749
 
        return file;
750
 
    } else if (hasSlash) {
751
 
        /*
752
 
         * If the file has a leading path component and that component
753
 
         * exactly matches the entire name of the current search
754
 
         * directory, we assume the file doesn't exist and return NULL.
755
 
         */
756
 
        for (p1 = p->name, p2 = name; *p1 && *p1 == *p2; p1++, p2++) {
757
 
            continue;
758
 
        }
759
 
        if (*p1 == '\0' && p2 == cp - 1) {
760
 
            if (DEBUG(DIR)) {
761
 
                printf("must be here but isn't -- returing\n");
762
 
            }
763
 
            return "";
764
 
        }
765
 
    }
766
 
    return NULL;
 
868
        printf("   %s ...\n", p->name);
 
869
    }
 
870
 
 
871
    if (Hash_FindEntry (&p->files, cp) == (Hash_Entry *)NULL)
 
872
        return NULL;
 
873
 
 
874
    file = str_concat (p->name, cp, STR_ADDSLASH);
 
875
    if (DEBUG(DIR)) {
 
876
        printf("   returning %s\n", file);
 
877
    }
 
878
    p->hits += 1;
 
879
    hits += 1;
 
880
    return file;
767
881
}
768
882
 
769
883
 
782
896
 *-----------------------------------------------------------------------
783
897
 */
784
898
static char *
785
 
DirLookupSubdir(p, name)
786
 
    Path *p;
787
 
    char *name;
 
899
DirLookupSubdir(Path *p, const char *name)
788
900
{
789
901
    struct stat   stb;          /* Buffer for stat, if necessary */
790
902
    Hash_Entry   *entry;        /* Entry for mtimes table */
800
912
    }
801
913
 
802
914
    if (DEBUG(DIR)) {
803
 
        printf("checking %s...", file);
 
915
        printf("checking %s ...\n", file);
804
916
    }
805
917
 
806
918
    if (stat (file, &stb) == 0) {
807
 
        if (DEBUG(DIR)) {
808
 
            printf("got it.\n");
809
 
        }
810
 
 
811
919
        /*
812
920
         * Save the modification time so if it's needed, we don't have
813
921
         * to fetch it again.
814
922
         */
815
923
        if (DEBUG(DIR)) {
816
 
            printf("Caching %s for %s\n", Targ_FmtTime(stb.st_mtime),
 
924
            printf("   Caching %s for %s\n", Targ_FmtTime(stb.st_mtime),
817
925
                    file);
818
926
        }
819
927
        entry = Hash_CreateEntry(&mtimes, (char *) file,
828
936
 
829
937
/*-
830
938
 *-----------------------------------------------------------------------
 
939
 * DirLookupAbs  --
 
940
 *      Find if the file with the given name exists in the given path.
 
941
 *
 
942
 * Results:
 
943
 *      The path to the file, the empty string or NULL. If the file is
 
944
 *      the empty string, the search should be terminated.
 
945
 *      This path is guaranteed to be in a different part of memory
 
946
 *      than name and so may be safely free'd.
 
947
 *
 
948
 * Side Effects:
 
949
 *      None.
 
950
 *-----------------------------------------------------------------------
 
951
 */
 
952
static char *
 
953
DirLookupAbs(Path *p, const char *name, const char *cp)
 
954
{
 
955
        char *p1;               /* pointer into p->name */
 
956
        const char *p2;         /* pointer into name */
 
957
 
 
958
        if (DEBUG(DIR)) {
 
959
                printf("   %s ...\n", p->name);
 
960
        }
 
961
 
 
962
        /*
 
963
         * If the file has a leading path component and that component
 
964
         * exactly matches the entire name of the current search
 
965
         * directory, we can attempt another cache lookup. And if we don't
 
966
         * have a hit, we can safely assume the file does not exist at all.
 
967
         */
 
968
        for (p1 = p->name, p2 = name; *p1 && *p1 == *p2; p1++, p2++) {
 
969
                continue;
 
970
        }
 
971
        if (*p1 != '\0' || p2 != cp - 1) {
 
972
                return NULL;
 
973
        }
 
974
 
 
975
        if (Hash_FindEntry (&p->files, cp) == (Hash_Entry *)NULL) {
 
976
                if (DEBUG(DIR)) {
 
977
                        printf("   must be here but isn't -- returning\n");
 
978
                }
 
979
                /* Return empty string: terminates search */
 
980
                return estrdup("");
 
981
        }
 
982
 
 
983
        p->hits += 1;
 
984
        hits += 1;
 
985
        if (DEBUG(DIR)) {
 
986
                printf("   returning %s\n", name);
 
987
        }
 
988
        return (estrdup (name));
 
989
}
 
990
 
 
991
/*-
 
992
 *-----------------------------------------------------------------------
 
993
 * DirFindDot  --
 
994
 *      Find the file given on "." or curdir
 
995
 *
 
996
 * Results:
 
997
 *      The path to the file or NULL. This path is guaranteed to be in a
 
998
 *      different part of memory than name and so may be safely free'd.
 
999
 *
 
1000
 * Side Effects:
 
1001
 *      Hit counts change
 
1002
 *-----------------------------------------------------------------------
 
1003
 */
 
1004
static char *
 
1005
DirFindDot(Boolean hasSlash, const char *name, const char *cp)
 
1006
{
 
1007
 
 
1008
        if (Hash_FindEntry (&dot->files, cp) != (Hash_Entry *)NULL) {
 
1009
            if (DEBUG(DIR)) {
 
1010
                printf("   in '.'\n");
 
1011
            }
 
1012
            hits += 1;
 
1013
            dot->hits += 1;
 
1014
            return (estrdup (name));
 
1015
        }
 
1016
        if (cur &&
 
1017
            Hash_FindEntry (&cur->files, cp) != (Hash_Entry *)NULL) {
 
1018
            if (DEBUG(DIR)) {
 
1019
                printf("   in ${.CURDIR} = %s\n", cur->name);
 
1020
            }
 
1021
            hits += 1;
 
1022
            cur->hits += 1;
 
1023
            return str_concat (cur->name, cp, STR_ADDSLASH);
 
1024
        }
 
1025
 
 
1026
        return NULL;
 
1027
}
 
1028
 
 
1029
/*-
 
1030
 *-----------------------------------------------------------------------
831
1031
 * Dir_FindFile  --
832
1032
 *      Find the file with the given name along the given search path.
833
1033
 *
 
1034
 * Input:
 
1035
 *      name            the file to find
 
1036
 *      path            the Lst of directories to search
 
1037
 *
834
1038
 * Results:
835
1039
 *      The path to the file or NULL. This path is guaranteed to be in a
836
1040
 *      different part of memory than name and so may be safely free'd.
845
1049
 *-----------------------------------------------------------------------
846
1050
 */
847
1051
char *
848
 
Dir_FindFile (name, path)
849
 
    char          *name;    /* the file to find */
850
 
    Lst           path;     /* the Lst of directories to search */
 
1052
Dir_FindFile(const char *name, Lst path)
851
1053
{
852
 
    LstNode       ln;       /* a list element */
853
 
    register char *file;    /* the current filename to check */
854
 
    register Path *p;       /* current path member */
855
 
    register char *cp;      /* index of first slash, if any */
856
 
    Boolean       hasSlash; /* true if 'name' contains a / */
857
 
    struct stat   stb;      /* Buffer for stat, if necessary */
858
 
    Hash_Entry    *entry;   /* Entry for mtimes table */
 
1054
    LstNode       ln;                   /* a list element */
 
1055
    char          *file;                /* the current filename to check */
 
1056
    Path          *p;                   /* current path member */
 
1057
    const char    *cp;                  /* index of first slash, if any */
 
1058
    Boolean       hasLastDot = FALSE;   /* true we should search dot last */
 
1059
    Boolean       hasSlash;             /* true if 'name' contains a / */
 
1060
    struct stat   stb;                  /* Buffer for stat, if necessary */
 
1061
    Hash_Entry    *entry;               /* Entry for mtimes table */
859
1062
 
860
1063
    /*
861
1064
     * Find the final component of the name and note whether it has a
871
1074
    }
872
1075
 
873
1076
    if (DEBUG(DIR)) {
874
 
        printf("Searching for %s...", name);
875
 
    }
876
 
    /*
877
 
     * No matter what, we always look for the file in the current directory
878
 
     * before anywhere else and we *do not* add the ./ to it if it exists.
879
 
     * This is so there are no conflicts between what the user specifies
880
 
     * (fish.c) and what pmake finds (./fish.c).
881
 
     */
882
 
    if ((!hasSlash || (cp - name == 2 && *name == '.'))) {
883
 
        if (Hash_FindEntry (&dot->files, cp) != (Hash_Entry *)NULL) {
884
 
            if (DEBUG(DIR)) {
885
 
                printf("in '.'\n");
886
 
            }
887
 
            hits += 1;
888
 
            dot->hits += 1;
889
 
            return (estrdup (name));
890
 
        }
891
 
        if (cur &&
892
 
            Hash_FindEntry (&cur->files, cp) != (Hash_Entry *)NULL) {
893
 
            if (DEBUG(DIR)) {
894
 
                printf("in ${.CURDIR} = %s\n", cur->name);
895
 
            }
896
 
            hits += 1;
897
 
            cur->hits += 1;
898
 
            return str_concat (cur->name, cp, STR_ADDSLASH);
899
 
        }
 
1077
        printf("Searching for %s ...", name);
900
1078
    }
901
1079
 
902
1080
    if (Lst_Open (path) == FAILURE) {
907
1085
        return ((char *) NULL);
908
1086
    }
909
1087
 
910
 
    if (cur && (file = DirLookup(cur, name, cp, hasSlash)) != NULL) {
911
 
        if (*file)
912
 
            return file;
913
 
        else
914
 
            return NULL;
 
1088
    if ((ln = Lst_First (path)) != NILLNODE) {
 
1089
        p = (Path *) Lst_Datum (ln);
 
1090
        if (p == dotLast) {
 
1091
            hasLastDot = TRUE;
 
1092
            if (DEBUG(DIR))
 
1093
                printf("[dot last]...");
 
1094
        }
 
1095
    }
 
1096
    if (DEBUG(DIR)) {
 
1097
        printf("\n");
915
1098
    }
916
1099
 
917
1100
    /*
918
 
     * We look through all the directories on the path seeking one which
919
 
     * contains the final component of the given name and whose final
920
 
     * component(s) match the name's initial component(s). If such a beast
921
 
     * is found, we concatenate the directory name and the final component
922
 
     * and return the resulting string. If we don't find any such thing,
923
 
     * we go on to phase two...
 
1101
     * If there's no leading directory components or if the leading
 
1102
     * directory component is exactly `./', consult the cached contents
 
1103
     * of each of the directories on the search path.
924
1104
     */
925
 
    while ((ln = Lst_Next (path)) != NILLNODE) {
926
 
        p = (Path *) Lst_Datum (ln);
927
 
        if ((file = DirLookup(p, name, cp, hasSlash)) != NULL) {
928
 
            Lst_Close (path);
929
 
            if (*file)
930
 
                return file;
931
 
            else
932
 
                return NULL;
933
 
        }
 
1105
    if ((!hasSlash || (cp - name == 2 && *name == '.'))) {
 
1106
            /*
 
1107
             * We look through all the directories on the path seeking one which
 
1108
             * contains the final component of the given name.  If such a beast
 
1109
             * is found, we concatenate the directory name and the final
 
1110
             * component and return the resulting string. If we don't find any
 
1111
             * such thing, we go on to phase two...
 
1112
             * 
 
1113
             * No matter what, we always look for the file in the current
 
1114
             * directory before anywhere else (unless we found the magic
 
1115
             * DOTLAST path, in which case we search it last) and we *do not*
 
1116
             * add the ./ to it if it exists.
 
1117
             * This is so there are no conflicts between what the user
 
1118
             * specifies (fish.c) and what pmake finds (./fish.c).
 
1119
             */
 
1120
            if (!hasLastDot &&
 
1121
                        (file = DirFindDot(hasSlash, name, cp)) != NULL) {
 
1122
                    Lst_Close (path);
 
1123
                    return file;
 
1124
            }
 
1125
 
 
1126
            while ((ln = Lst_Next (path)) != NILLNODE) {
 
1127
                p = (Path *) Lst_Datum (ln);
 
1128
                if (p == dotLast)
 
1129
                    continue;
 
1130
                if ((file = DirLookup(p, name, cp, hasSlash)) != NULL) {
 
1131
                    Lst_Close (path);
 
1132
                        return file;
 
1133
                }
 
1134
            }
 
1135
 
 
1136
            if (hasLastDot &&
 
1137
                        (file = DirFindDot(hasSlash, name, cp)) != NULL) {
 
1138
                    Lst_Close (path);
 
1139
                    return file;
 
1140
            }
934
1141
    }
 
1142
    Lst_Close (path);
935
1143
 
936
1144
    /*
937
 
     * We didn't find the file on any existing members of the directory.
 
1145
     * We didn't find the file on any directory in the search path.
938
1146
     * If the name doesn't contain a slash, that means it doesn't exist.
939
1147
     * If it *does* contain a slash, however, there is still hope: it
940
1148
     * could be in a subdirectory of one of the members of the search
941
1149
     * path. (eg. /usr/include and sys/types.h. The above search would
942
1150
     * fail to turn up types.h in /usr/include, but it *is* in
943
 
     * /usr/include/sys/types.h) If we find such a beast, we assume there
 
1151
     * /usr/include/sys/types.h).
 
1152
     * [ This no longer applies: If we find such a beast, we assume there
944
1153
     * will be more (what else can we assume?) and add all but the last
945
1154
     * component of the resulting name onto the search path (at the
946
 
     * end). This phase is only performed if the file is *not* absolute.
 
1155
     * end).]
 
1156
     * This phase is only performed if the file is *not* absolute.
947
1157
     */
948
1158
    if (!hasSlash) {
949
1159
        if (DEBUG(DIR)) {
950
 
            printf("failed.\n");
 
1160
            printf("   failed.\n");
951
1161
        }
952
1162
        misses += 1;
953
1163
        return ((char *) NULL);
954
1164
    }
955
1165
 
956
 
    if (*name != '/') {
 
1166
    if (name[0] != '/') {
957
1167
        Boolean checkedDot = FALSE;
958
1168
 
959
1169
        if (DEBUG(DIR)) {
960
 
            printf("failed. Trying subdirectories...");
 
1170
            printf("   Trying subdirectories...\n");
961
1171
        }
962
1172
 
963
 
        if (cur && (file = DirLookupSubdir(cur, name)) != NULL)
964
 
            return file;
 
1173
        if (!hasLastDot) {
 
1174
                if (dot) {
 
1175
                        checkedDot = TRUE;
 
1176
                        if ((file = DirLookupSubdir(dot, name)) != NULL)
 
1177
                                return file;
 
1178
                }
 
1179
                if (cur && (file = DirLookupSubdir(cur, name)) != NULL)
 
1180
                        return file;
 
1181
        }
965
1182
 
966
1183
        (void) Lst_Open (path);
967
1184
        while ((ln = Lst_Next (path)) != NILLNODE) {
968
1185
            p = (Path *) Lst_Datum (ln);
969
 
            if (p == dot)
 
1186
            if (p == dotLast)
 
1187
                continue;
 
1188
            if (p == dot) {
 
1189
                    if (checkedDot)
 
1190
                            continue;
970
1191
                checkedDot = TRUE;
 
1192
            }
971
1193
            if ((file = DirLookupSubdir(p, name)) != NULL) {
972
1194
                Lst_Close (path);
973
1195
                return file;
974
1196
            }
975
1197
        }
976
 
 
977
 
        if (DEBUG(DIR)) {
978
 
            printf("failed. ");
979
 
        }
980
1198
        Lst_Close (path);
981
1199
 
 
1200
        if (hasLastDot) {
 
1201
                if (dot && !checkedDot) {
 
1202
                        checkedDot = TRUE;
 
1203
                        if ((file = DirLookupSubdir(dot, name)) != NULL)
 
1204
                                return file;
 
1205
                }
 
1206
                if (cur && (file = DirLookupSubdir(cur, name)) != NULL)
 
1207
                        return file;
 
1208
        }
 
1209
 
982
1210
        if (checkedDot) {
983
1211
            /*
984
1212
             * Already checked by the given name, since . was in the path,
985
1213
             * so no point in proceeding...
986
1214
             */
987
1215
            if (DEBUG(DIR)) {
988
 
                printf("Checked . already, returning NULL\n");
 
1216
                printf("   Checked . already, returning NULL\n");
989
1217
            }
990
1218
            return(NULL);
991
1219
        }
 
1220
 
 
1221
    } else { /* name[0] == '/' */
 
1222
 
 
1223
        /*
 
1224
         * For absolute names, compare directory path prefix against the
 
1225
         * the directory path of each member on the search path for an exact
 
1226
         * match. If we have an exact match on any member of the search path,
 
1227
         * use the cached contents of that member to lookup the final file
 
1228
         * component. If that lookup fails we can safely assume that the
 
1229
         * file does not exist at all.  This is signified by DirLookupAbs()
 
1230
         * returning an empty string.
 
1231
         */
 
1232
        if (DEBUG(DIR)) {
 
1233
            printf("   Trying exact path matches...\n");
 
1234
        }
 
1235
 
 
1236
        if (!hasLastDot && cur && (file = DirLookupAbs(cur, name, cp)) != NULL)
 
1237
            return *file?file:NULL;
 
1238
 
 
1239
        (void) Lst_Open (path);
 
1240
        while ((ln = Lst_Next (path)) != NILLNODE) {
 
1241
            p = (Path *) Lst_Datum (ln);
 
1242
            if (p == dotLast)
 
1243
                continue;
 
1244
            if ((file = DirLookupAbs(p, name, cp)) != NULL) {
 
1245
                Lst_Close (path);
 
1246
                return *file?file:NULL;
 
1247
            }
 
1248
        }
 
1249
        Lst_Close (path);
 
1250
 
 
1251
        if (hasLastDot && cur && (file = DirLookupAbs(cur, name, cp)) != NULL)
 
1252
            return *file?file:NULL;
992
1253
    }
993
1254
 
994
1255
    /*
1028
1289
    }
1029
1290
#else /* !notdef */
1030
1291
    if (DEBUG(DIR)) {
1031
 
        printf("Looking for \"%s\"...", name);
 
1292
        printf("   Looking for \"%s\" ...\n", name);
1032
1293
    }
1033
1294
 
1034
1295
    bigmisses += 1;
1035
1296
    entry = Hash_FindEntry(&mtimes, name);
1036
1297
    if (entry != (Hash_Entry *)NULL) {
1037
1298
        if (DEBUG(DIR)) {
1038
 
            printf("got it (in mtime cache)\n");
 
1299
            printf("   got it (in mtime cache)\n");
1039
1300
        }
1040
1301
        return(estrdup(name));
1041
1302
    } else if (stat (name, &stb) == 0) {
1042
1303
        entry = Hash_CreateEntry(&mtimes, name, (Boolean *)NULL);
1043
1304
        if (DEBUG(DIR)) {
1044
 
            printf("Caching %s for %s\n", Targ_FmtTime(stb.st_mtime),
 
1305
            printf("   Caching %s for %s\n", Targ_FmtTime(stb.st_mtime),
1045
1306
                    name);
1046
1307
        }
1047
1308
        Hash_SetValue(entry, (long)stb.st_mtime);
1048
1309
        return (estrdup (name));
1049
1310
    } else {
1050
1311
        if (DEBUG(DIR)) {
1051
 
            printf("failed. Returning NULL\n");
 
1312
            printf("   failed. Returning NULL\n");
1052
1313
        }
1053
1314
        return ((char *)NULL);
1054
1315
    }
1055
1316
#endif /* notdef */
1056
1317
}
1057
1318
 
 
1319
 
 
1320
/*-
 
1321
 *-----------------------------------------------------------------------
 
1322
 * Dir_FindHereOrAbove  --
 
1323
 *      search for a path starting at a given directory and then working 
 
1324
 *      our way up towards the root.
 
1325
 *
 
1326
 * Input:
 
1327
 *      here            starting directory
 
1328
 *      search_path     the path we are looking for
 
1329
 *      result          the result of a successful search is placed here
 
1330
 *      rlen            the length of the result buffer 
 
1331
 *                      (typically MAXPATHLEN + 1)
 
1332
 *
 
1333
 * Results:
 
1334
 *      0 on failure, 1 on success [in which case the found path is put
 
1335
 *      in the result buffer].
 
1336
 *
 
1337
 * Side Effects:
 
1338
 *-----------------------------------------------------------------------
 
1339
 */
 
1340
int 
 
1341
Dir_FindHereOrAbove(char *here, char *search_path, char *result, int rlen) {
 
1342
 
 
1343
        struct stat st;
 
1344
        char dirbase[MAXPATHLEN + 1], *db_end;
 
1345
        char try[MAXPATHLEN + 1], *try_end;
 
1346
 
 
1347
        /* copy out our starting point */
 
1348
        snprintf(dirbase, sizeof(dirbase), "%s", here);
 
1349
        db_end = dirbase + strlen(dirbase);
 
1350
 
 
1351
        /* loop until we determine a result */
 
1352
        while (1) {
 
1353
 
 
1354
                /* try and stat(2) it ... */
 
1355
                snprintf(try, sizeof(try), "%s/%s", dirbase, search_path);
 
1356
                if (stat(try, &st) != -1) {
 
1357
                        /*
 
1358
                         * success!  if we found a file, chop off
 
1359
                         * the filename so we return a directory.
 
1360
                         */
 
1361
                        if ((st.st_mode & S_IFMT) != S_IFDIR) {
 
1362
                                try_end = try + strlen(try);
 
1363
                                while (try_end > try && *try_end != '/')
 
1364
                                        try_end--;
 
1365
                                if (try_end > try) 
 
1366
                                        *try_end = 0;   /* chop! */
 
1367
                        }
 
1368
 
 
1369
                        /*
 
1370
                         * done!
 
1371
                         */
 
1372
                        snprintf(result, rlen, "%s", try);
 
1373
                        return(1);
 
1374
                }
 
1375
 
 
1376
                /* 
 
1377
                 * nope, we didn't find it.  if we used up dirbase we've
 
1378
                 * reached the root and failed.
 
1379
                 */
 
1380
                if (db_end == dirbase)
 
1381
                        break;          /* failed! */
 
1382
 
 
1383
                /*
 
1384
                 * truncate dirbase from the end to move up a dir
 
1385
                 */
 
1386
                while (db_end > dirbase && *db_end != '/')
 
1387
                        db_end--;
 
1388
                *db_end = 0;            /* chop! */
 
1389
 
 
1390
        } /* while (1) */
 
1391
 
 
1392
        /*
 
1393
         * we failed... 
 
1394
         */
 
1395
        return(0);
 
1396
}
 
1397
 
1058
1398
/*-
1059
1399
 *-----------------------------------------------------------------------
1060
1400
 * Dir_MTime  --
1061
1401
 *      Find the modification time of the file described by gn along the
1062
1402
 *      search path dirSearchPath.
1063
1403
 *
 
1404
 * Input:
 
1405
 *      gn              the file whose modification time is desired
 
1406
 *
1064
1407
 * Results:
1065
1408
 *      The modification time or 0 if it doesn't exist
1066
1409
 *
1071
1414
 *-----------------------------------------------------------------------
1072
1415
 */
1073
1416
int
1074
 
Dir_MTime (gn)
1075
 
    GNode         *gn;        /* the file whose modification time is
1076
 
                               * desired */
 
1417
Dir_MTime(GNode *gn)
1077
1418
{
1078
1419
    char          *fullName;  /* the full pathname of name */
1079
1420
    struct stat   stb;        /* buffer for finding the mod time */
1081
1422
 
1082
1423
    if (gn->type & OP_ARCHV) {
1083
1424
        return Arch_MTime (gn);
 
1425
    } else if (gn->type & OP_PHONY) {
 
1426
        gn->mtime = 0;
 
1427
        return 0;
1084
1428
    } else if (gn->path == (char *)NULL) {
1085
 
        if (gn->type & (OP_PHONY|OP_NOPATH))
 
1429
        if (gn->type & OP_NOPATH)
1086
1430
            fullName = NULL;
1087
1431
        else
1088
1432
            fullName = Dir_FindFile (gn->name, dirSearchPath);
1131
1475
 *      the arguments is backwards so ParseDoDependency can do a
1132
1476
 *      Lst_ForEach of its list of paths...
1133
1477
 *
 
1478
 * Input:
 
1479
 *      path            the path to which the directory should be
 
1480
 *                      added
 
1481
 *      name            the name of the directory to add
 
1482
 *
1134
1483
 * Results:
1135
1484
 *      none
1136
1485
 *
1140
1489
 *-----------------------------------------------------------------------
1141
1490
 */
1142
1491
Path *
1143
 
Dir_AddDir (path, name)
1144
 
    Lst           path;       /* the path to which the directory should be
1145
 
                               * added */
1146
 
    const char   *name;       /* the name of the directory to add */
 
1492
Dir_AddDir(Lst path, const char *name)
1147
1493
{
1148
 
    LstNode       ln;         /* node in case Path structure is found */
1149
 
    register Path *p = NULL;  /* pointer to new Path structure */
 
1494
    LstNode       ln = NILLNODE; /* node in case Path structure is found */
 
1495
    Path          *p = NULL;  /* pointer to new Path structure */
1150
1496
    DIR           *d;         /* for reading directory */
1151
 
    register struct dirent *dp; /* entry in directory */
1152
 
 
1153
 
    ln = Lst_Find (openDirectories, (ClientData)name, DirFindName);
 
1497
    struct dirent *dp;        /* entry in directory */
 
1498
 
 
1499
    if (strcmp(name, ".DOTLAST") == 0) {
 
1500
        ln = Lst_Find (path, (ClientData)UNCONST(name), DirFindName);
 
1501
        if (ln != NILLNODE)
 
1502
            return (Path *) Lst_Datum(ln);
 
1503
        else {
 
1504
            dotLast->refCount += 1;
 
1505
            (void)Lst_AtFront(path, (ClientData)dotLast);
 
1506
        }
 
1507
    }
 
1508
 
 
1509
    if (path)
 
1510
        ln = Lst_Find (openDirectories, (ClientData)UNCONST(name), DirFindName);
1154
1511
    if (ln != NILLNODE) {
1155
1512
        p = (Path *)Lst_Datum (ln);
1156
1513
        if (Lst_Member(path, (ClientData)p) == NILLNODE) {
1159
1516
        }
1160
1517
    } else {
1161
1518
        if (DEBUG(DIR)) {
1162
 
            printf("Caching %s...", name);
 
1519
            printf("Caching %s ...", name);
1163
1520
            fflush(stdout);
1164
1521
        }
1165
1522
 
1170
1527
            p->refCount = 1;
1171
1528
            Hash_InitTable (&p->files, -1);
1172
1529
 
1173
 
            /*
1174
 
             * Skip the first two entries -- these will *always* be . and ..
1175
 
             */
1176
 
            (void)readdir(d);
1177
 
            (void)readdir(d);
1178
 
 
1179
1530
            while ((dp = readdir (d)) != (struct dirent *) NULL) {
1180
1531
#if defined(sun) && defined(d_ino) /* d_ino is a sunos4 #define for d_fileno */
1181
1532
                /*
1216
1567
 *-----------------------------------------------------------------------
1217
1568
 */
1218
1569
ClientData
1219
 
Dir_CopyDir(p)
1220
 
    ClientData p;
 
1570
Dir_CopyDir(ClientData p)
1221
1571
{
1222
1572
    ((Path *) p)->refCount += 1;
1223
1573
 
1232
1582
 *      module to create variables for compilers based on suffix search
1233
1583
 *      paths.
1234
1584
 *
 
1585
 * Input:
 
1586
 *      flag            flag which should precede each directory
 
1587
 *      path            list of directories
 
1588
 *
1235
1589
 * Results:
1236
1590
 *      The string mentioned above. Note that there is no space between
1237
1591
 *      the given flag and each directory. The empty string is returned if
1242
1596
 *-----------------------------------------------------------------------
1243
1597
 */
1244
1598
char *
1245
 
Dir_MakeFlags (flag, path)
1246
 
    char          *flag;  /* flag which should precede each directory */
1247
 
    Lst           path;   /* list of directories */
 
1599
Dir_MakeFlags(const char *flag, Lst path)
1248
1600
{
1249
1601
    char          *str;   /* the string which will be returned */
1250
 
    char          *tstr;  /* the current directory preceded by 'flag' */
 
1602
    char          *s1, *s2;/* the current directory preceded by 'flag' */
1251
1603
    LstNode       ln;     /* the node of the current directory */
1252
1604
    Path          *p;     /* the structure describing the current directory */
1253
1605
 
1256
1608
    if (Lst_Open (path) == SUCCESS) {
1257
1609
        while ((ln = Lst_Next (path)) != NILLNODE) {
1258
1610
            p = (Path *) Lst_Datum (ln);
1259
 
            tstr = str_concat (flag, p->name, 0);
1260
 
            str = str_concat (str, tstr, STR_ADDSPACE | STR_DOFREE);
 
1611
            s2 = str_concat (flag, p->name, 0);
 
1612
            str = str_concat (s1 = str, s2, STR_ADDSPACE);
 
1613
            free(s1);
 
1614
            free(s2);
1261
1615
        }
1262
1616
        Lst_Close (path);
1263
1617
    }
1271
1625
 *      Nuke a directory descriptor, if possible. Callback procedure
1272
1626
 *      for the suffixes module when destroying a search path.
1273
1627
 *
 
1628
 * Input:
 
1629
 *      pp              The directory descriptor to nuke
 
1630
 *
1274
1631
 * Results:
1275
1632
 *      None.
1276
1633
 *
1281
1638
 *-----------------------------------------------------------------------
1282
1639
 */
1283
1640
void
1284
 
Dir_Destroy (pp)
1285
 
    ClientData    pp;       /* The directory descriptor to nuke */
 
1641
Dir_Destroy(ClientData pp)
1286
1642
{
1287
1643
    Path          *p = (Path *) pp;
1288
1644
    p->refCount -= 1;
1305
1661
 *      Clear out all elements of the given search path. This is different
1306
1662
 *      from destroying the list, notice.
1307
1663
 *
 
1664
 * Input:
 
1665
 *      path            Path to clear
 
1666
 *
1308
1667
 * Results:
1309
1668
 *      None.
1310
1669
 *
1314
1673
 *-----------------------------------------------------------------------
1315
1674
 */
1316
1675
void
1317
 
Dir_ClearPath(path)
1318
 
    Lst     path;       /* Path to clear */
 
1676
Dir_ClearPath(Lst path)
1319
1677
{
1320
1678
    Path    *p;
1321
1679
    while (!Lst_IsEmpty(path)) {
1331
1689
 *      Concatenate two paths, adding the second to the end of the first.
1332
1690
 *      Makes sure to avoid duplicates.
1333
1691
 *
 
1692
 * Input:
 
1693
 *      path1           Dest
 
1694
 *      path2           Source
 
1695
 *
1334
1696
 * Results:
1335
1697
 *      None
1336
1698
 *
1340
1702
 *-----------------------------------------------------------------------
1341
1703
 */
1342
1704
void
1343
 
Dir_Concat(path1, path2)
1344
 
    Lst     path1;      /* Dest */
1345
 
    Lst     path2;      /* Source */
 
1705
Dir_Concat(Lst path1, Lst path2)
1346
1706
{
1347
1707
    LstNode ln;
1348
1708
    Path    *p;
1358
1718
 
1359
1719
/********** DEBUG INFO **********/
1360
1720
void
1361
 
Dir_PrintDirectories()
 
1721
Dir_PrintDirectories(void)
1362
1722
{
1363
1723
    LstNode     ln;
1364
1724
    Path        *p;
1378
1738
    }
1379
1739
}
1380
1740
 
1381
 
static int DirPrintDir (p, dummy)
1382
 
    ClientData  p;
1383
 
    ClientData  dummy;
 
1741
static int
 
1742
DirPrintDir(ClientData p, ClientData dummy)
1384
1743
{
1385
1744
    printf ("%s ", ((Path *) p)->name);
1386
1745
    return (dummy ? 0 : 0);
1387
1746
}
1388
1747
 
1389
1748
void
1390
 
Dir_PrintPath (path)
1391
 
    Lst path;
 
1749
Dir_PrintPath(Lst path)
1392
1750
{
1393
1751
    Lst_ForEach (path, DirPrintDir, (ClientData)0);
1394
1752
}