OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [gold/] [dirsearch.cc] - Blame information for rev 161

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 khays
// dirsearch.cc -- directory searching for gold
2
 
3
// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
4
// Written by Ian Lance Taylor <iant@google.com>.
5
 
6
// This file is part of gold.
7
 
8
// This program is free software; you can redistribute it and/or modify
9
// it under the terms of the GNU General Public License as published by
10
// the Free Software Foundation; either version 3 of the License, or
11
// (at your option) any later version.
12
 
13
// This program is distributed in the hope that it will be useful,
14
// but WITHOUT ANY WARRANTY; without even the implied warranty of
15
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
// GNU General Public License for more details.
17
 
18
// You should have received a copy of the GNU General Public License
19
// along with this program; if not, write to the Free Software
20
// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21
// MA 02110-1301, USA.
22
 
23
#include "gold.h"
24
 
25
#include <cerrno>
26
#include <cstring>
27
#include <sys/types.h>
28
#include <dirent.h>
29
 
30
#include "debug.h"
31
#include "gold-threads.h"
32
#include "options.h"
33
#include "workqueue.h"
34
#include "dirsearch.h"
35
 
36
namespace
37
{
38
 
39
// Read all the files in a directory.
40
 
41
class Dir_cache
42
{
43
 public:
44
  Dir_cache(const char* dirname)
45
    : dirname_(dirname), files_()
46
  { }
47
 
48
  // Read the files in the directory.
49
  void read_files();
50
 
51
  // Return whether a file (a base name) is present in the directory.
52
  bool find(const std::string&) const;
53
 
54
 private:
55
  // We can not copy this class.
56
  Dir_cache(const Dir_cache&);
57
  Dir_cache& operator=(const Dir_cache&);
58
 
59
  const char* dirname_;
60
  Unordered_set<std::string> files_;
61
};
62
 
63
void
64
Dir_cache::read_files()
65
{
66
  DIR* d = opendir(this->dirname_);
67
  if (d == NULL)
68
    {
69 159 khays
      // We ignore directories which do not exist or are actually file
70
      // names.
71
      if (errno != ENOENT && errno != ENOTDIR)
72 27 khays
        gold::gold_error(_("%s: can not read directory: %s"),
73
                         this->dirname_, strerror(errno));
74
      return;
75
    }
76
 
77
  dirent* de;
78
  while ((de = readdir(d)) != NULL)
79
    this->files_.insert(std::string(de->d_name));
80
 
81
  if (closedir(d) != 0)
82
    gold::gold_warning("%s: closedir failed: %s", this->dirname_,
83
                       strerror(errno));
84
}
85
 
86
bool
87
Dir_cache::find(const std::string& basename) const
88
{
89
  return this->files_.find(basename) != this->files_.end();
90
}
91
 
92
// A mapping from directory names to caches.  A lock permits
93
// concurrent update.  There is no lock for read operations--some
94
// other mechanism must be used to prevent reads from conflicting with
95
// writes.
96
 
97
class Dir_caches
98
{
99
 public:
100
  Dir_caches()
101
    : lock_(), caches_()
102
  { }
103
 
104
  ~Dir_caches();
105
 
106
  // Add a cache for a directory.
107
  void add(const char*);
108
 
109
  // Look up a directory in the cache.  This much be locked against
110
  // calls to Add.
111
  Dir_cache* lookup(const char*) const;
112
 
113
 private:
114
  // We can not copy this class.
115
  Dir_caches(const Dir_caches&);
116
  Dir_caches& operator=(const Dir_caches&);
117
 
118
  typedef Unordered_map<const char*, Dir_cache*> Cache_hash;
119
 
120
  gold::Lock lock_;
121
  Cache_hash caches_;
122
};
123
 
124
Dir_caches::~Dir_caches()
125
{
126
  for (Cache_hash::iterator p = this->caches_.begin();
127
       p != this->caches_.end();
128
       ++p)
129
    delete p->second;
130
}
131
 
132
void
133
Dir_caches::add(const char* dirname)
134
{
135
  {
136
    gold::Hold_lock hl(this->lock_);
137
    if (this->lookup(dirname) != NULL)
138
      return;
139
  }
140
 
141
  Dir_cache* cache = new Dir_cache(dirname);
142
 
143
  cache->read_files();
144
 
145
  {
146
    gold::Hold_lock hl(this->lock_);
147
 
148
    std::pair<const char*, Dir_cache*> v(dirname, cache);
149
    std::pair<Cache_hash::iterator, bool> p = this->caches_.insert(v);
150
    gold_assert(p.second);
151
  }
152
}
153
 
154
Dir_cache*
155
Dir_caches::lookup(const char* dirname) const
156
{
157
  Cache_hash::const_iterator p = this->caches_.find(dirname);
158
  if (p == this->caches_.end())
159
    return NULL;
160
  return p->second;
161
}
162
 
163
// The caches.
164
 
165
Dir_caches* caches;
166
 
167
// A Task to read the directory.
168
 
169
class Dir_cache_task : public gold::Task
170
{
171
 public:
172
  Dir_cache_task(const char* dir, gold::Task_token& token)
173
    : dir_(dir), token_(token)
174
  { }
175
 
176
  gold::Task_token*
177
  is_runnable();
178
 
179
  void
180
  locks(gold::Task_locker*);
181
 
182
  void
183
  run(gold::Workqueue*);
184
 
185
  std::string
186
  get_name() const
187
  { return std::string("Dir_cache_task ") + this->dir_; }
188
 
189
 private:
190
  const char* dir_;
191
  gold::Task_token& token_;
192
};
193
 
194
// We can always run the task to read the directory.
195
 
196
gold::Task_token*
197
Dir_cache_task::is_runnable()
198
{
199
  return NULL;
200
}
201
 
202
// Return the locks to hold.  We use a blocker lock to prevent file
203
// lookups from starting until the directory contents have been read.
204
 
205
void
206
Dir_cache_task::locks(gold::Task_locker* tl)
207
{
208
  tl->add(this, &this->token_);
209
}
210
 
211
// Run the task--read the directory contents.
212
 
213
void
214
Dir_cache_task::run(gold::Workqueue*)
215
{
216
  caches->add(this->dir_);
217
}
218
 
219
}
220
 
221
namespace gold
222
{
223
 
224
// Initialize.
225
 
226
void
227
Dirsearch::initialize(Workqueue* workqueue,
228
                      const General_options::Dir_list* directories)
229
{
230
  gold_assert(caches == NULL);
231
  caches = new Dir_caches;
232
  this->directories_ = directories;
233
  this->token_.add_blockers(directories->size());
234
  for (General_options::Dir_list::const_iterator p = directories->begin();
235
       p != directories->end();
236
       ++p)
237
    workqueue->queue(new Dir_cache_task(p->name().c_str(), this->token_));
238
}
239
 
240
// Search for a file.  NOTE: we only log failed file-lookup attempts
241
// here.  Successfully lookups will eventually get logged in
242
// File_read::open.
243
 
244
std::string
245
Dirsearch::find(const std::vector<std::string>& names,
246
                bool* is_in_sysroot, int* pindex,
247
                std::string *found_name) const
248
{
249
  gold_assert(!this->token_.is_blocked());
250
  gold_assert(*pindex >= 0);
251
 
252
  for (unsigned int i = static_cast<unsigned int>(*pindex);
253
       i < this->directories_->size();
254
       ++i)
255
    {
256
      const Search_directory* p = &this->directories_->at(i);
257
      Dir_cache* pdc = caches->lookup(p->name().c_str());
258
      gold_assert(pdc != NULL);
259
      for (std::vector<std::string>::const_iterator n = names.begin();
260
           n != names.end();
261
           ++n)
262
        {
263
          if (pdc->find(*n))
264
            {
265
              *is_in_sysroot = p->is_in_sysroot();
266
              *pindex = i;
267
              *found_name = *n;
268
              return p->name() + '/' + *n;
269
            }
270
          else
271
            gold_debug(DEBUG_FILES, "Attempt to open %s/%s failed",
272
                       p->name().c_str(), (*n).c_str());
273
        }
274
    }
275
 
276
  *pindex = -2;
277
  return std::string();
278
}
279
 
280
} // End namespace gold.

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.