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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [binutils-2.20.1/] [gold/] [dirsearch.cc] - Blame information for rev 205

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

Line No. Rev Author Line
1 205 julius
// dirsearch.cc -- directory searching for gold
2
 
3
// Copyright 2006, 2007, 2008 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
      // We ignore directories which do not exist.
70
      if (errno != ENOENT)
71
        gold::gold_error(_("%s: can not read directory: %s"),
72
                         this->dirname_, strerror(errno));
73
      return;
74
    }
75
 
76
  dirent* de;
77
  while ((de = readdir(d)) != NULL)
78
    this->files_.insert(std::string(de->d_name));
79
 
80
  if (closedir(d) != 0)
81
    gold::gold_warning("%s: closedir failed: %s", this->dirname_,
82
                       strerror(errno));
83
}
84
 
85
bool
86
Dir_cache::find(const std::string& basename) const
87
{
88
  return this->files_.find(basename) != this->files_.end();
89
}
90
 
91
// A mapping from directory names to caches.  A lock permits
92
// concurrent update.  There is no lock for read operations--some
93
// other mechanism must be used to prevent reads from conflicting with
94
// writes.
95
 
96
class Dir_caches
97
{
98
 public:
99
  Dir_caches()
100
    : lock_(), caches_()
101
  { }
102
 
103
  ~Dir_caches();
104
 
105
  // Add a cache for a directory.
106
  void add(const char*);
107
 
108
  // Look up a directory in the cache.  This much be locked against
109
  // calls to Add.
110
  Dir_cache* lookup(const char*) const;
111
 
112
 private:
113
  // We can not copy this class.
114
  Dir_caches(const Dir_caches&);
115
  Dir_caches& operator=(const Dir_caches&);
116
 
117
  typedef Unordered_map<const char*, Dir_cache*> Cache_hash;
118
 
119
  gold::Lock lock_;
120
  Cache_hash caches_;
121
};
122
 
123
Dir_caches::~Dir_caches()
124
{
125
  for (Cache_hash::iterator p = this->caches_.begin();
126
       p != this->caches_.end();
127
       ++p)
128
    delete p->second;
129
}
130
 
131
void
132
Dir_caches::add(const char* dirname)
133
{
134
  {
135
    gold::Hold_lock hl(this->lock_);
136
    if (this->lookup(dirname) != NULL)
137
      return;
138
  }
139
 
140
  Dir_cache* cache = new Dir_cache(dirname);
141
 
142
  cache->read_files();
143
 
144
  {
145
    gold::Hold_lock hl(this->lock_);
146
 
147
    std::pair<const char*, Dir_cache*> v(dirname, cache);
148
    std::pair<Cache_hash::iterator, bool> p = this->caches_.insert(v);
149
    gold_assert(p.second);
150
  }
151
}
152
 
153
Dir_cache*
154
Dir_caches::lookup(const char* dirname) const
155
{
156
  Cache_hash::const_iterator p = this->caches_.find(dirname);
157
  if (p == this->caches_.end())
158
    return NULL;
159
  return p->second;
160
}
161
 
162
// The caches.
163
 
164
Dir_caches* caches;
165
 
166
// A Task to read the directory.
167
 
168
class Dir_cache_task : public gold::Task
169
{
170
 public:
171
  Dir_cache_task(const char* dir, gold::Task_token& token)
172
    : dir_(dir), token_(token)
173
  { }
174
 
175
  gold::Task_token*
176
  is_runnable();
177
 
178
  void
179
  locks(gold::Task_locker*);
180
 
181
  void
182
  run(gold::Workqueue*);
183
 
184
  std::string
185
  get_name() const
186
  { return std::string("Dir_cache_task ") + this->dir_; }
187
 
188
 private:
189
  const char* dir_;
190
  gold::Task_token& token_;
191
};
192
 
193
// We can always run the task to read the directory.
194
 
195
gold::Task_token*
196
Dir_cache_task::is_runnable()
197
{
198
  return NULL;
199
}
200
 
201
// Return the locks to hold.  We use a blocker lock to prevent file
202
// lookups from starting until the directory contents have been read.
203
 
204
void
205
Dir_cache_task::locks(gold::Task_locker* tl)
206
{
207
  tl->add(this, &this->token_);
208
}
209
 
210
// Run the task--read the directory contents.
211
 
212
void
213
Dir_cache_task::run(gold::Workqueue*)
214
{
215
  caches->add(this->dir_);
216
}
217
 
218
}
219
 
220
namespace gold
221
{
222
 
223
// Initialize.
224
 
225
void
226
Dirsearch::initialize(Workqueue* workqueue,
227
                      const General_options::Dir_list* directories)
228
{
229
  gold_assert(caches == NULL);
230
  caches = new Dir_caches;
231
  this->directories_ = directories;
232
  for (General_options::Dir_list::const_iterator p = directories->begin();
233
       p != directories->end();
234
       ++p)
235
    {
236
      this->token_.add_blocker();
237
      workqueue->queue(new Dir_cache_task(p->name().c_str(), this->token_));
238
    }
239
}
240
 
241
// Search for a file.  NOTE: we only log failed file-lookup attempts
242
// here.  Successfully lookups will eventually get logged in
243
// File_read::open.
244
 
245
std::string
246
Dirsearch::find(const std::string& n1, const std::string& n2,
247
                bool* is_in_sysroot, int* pindex) 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
      if (pdc->find(n1))
260
        {
261
          *is_in_sysroot = p->is_in_sysroot();
262
          *pindex = i;
263
          return p->name() + '/' + n1;
264
        }
265
      else
266
        gold_debug(DEBUG_FILES, "Attempt to open %s/%s failed",
267
                   p->name().c_str(), n1.c_str());
268
 
269
      if (!n2.empty())
270
        {
271
          if (pdc->find(n2))
272
            {
273
              *is_in_sysroot = p->is_in_sysroot();
274
              *pindex = i;
275
              return p->name() + '/' + n2;
276
            }
277
          else
278
            gold_debug(DEBUG_FILES, "Attempt to open %s/%s failed",
279
                       p->name().c_str(), n2.c_str());
280
        }
281
    }
282
 
283
  *pindex = -2;
284
  return std::string();
285
}
286
 
287
} // End namespace gold.

powered by: WebSVN 2.1.0

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