1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "crazy_linker_search_path_list.h"
6
7#include <string.h>
8
9#include "crazy_linker_debug.h"
10#include "crazy_linker_system.h"
11
12namespace crazy {
13
14void SearchPathList::Reset() {
15  list_.Resize(0);
16  env_list_.Resize(0);
17  full_path_.Resize(0);
18}
19
20void SearchPathList::ResetFromEnv(const char* var_name) {
21  Reset();
22  const char* env = GetEnv(var_name);
23  if (env && *env)
24    env_list_ = env;
25}
26
27void SearchPathList::AddPaths(const char* list, const char* list_end) {
28  // Append a column to the current list, if necessary
29  if (list_.size() > 0 && list_[list_.size() - 1] != ':')
30    list_ += ':';
31  list_.Append(list, list_end - list);
32}
33
34const char* SearchPathList::FindFile(const char* file_name) {
35  // Sanity checks.
36  if (!file_name || !*file_name)
37    return NULL;
38
39  LOG("%s: Looking for %s\n", __FUNCTION__, file_name);
40
41  // Build full list by appending the env_list_ after the regular one.
42  String full_list = list_;
43  if (env_list_.size() > 0) {
44    if (full_list.size() > 0 && full_list[full_list.size() - 1] != ':')
45      full_list += ':';
46    full_list += env_list_;
47  }
48
49  // Iterate over all items in the list.
50  const char* p = full_list.c_str();
51  const char* end = p + full_list.size();
52
53  while (p < end) {
54    // compute current list item, and next item start at the same time.
55    const char* item = p;
56    const char* item_end =
57        reinterpret_cast<const char*>(memchr(p, ':', end - p));
58    if (item_end)
59      p = item_end + 1;
60    else {
61      item_end = end;
62      p = end;
63    }
64
65    full_path_.Assign(item, item_end - item);
66
67    // Add trailing directory separator if needed.
68    if (full_path_.size() > 0 && full_path_[full_path_.size() - 1] != '/')
69      full_path_ += '/';
70
71    full_path_ += file_name;
72
73    if (PathIsFile(full_path_.c_str())) {
74      LOG("    FOUND %s\n", full_path_.c_str());
75      return full_path_.c_str();
76    } else
77      LOG("    skip  %s\n", full_path_.c_str());
78  }
79
80  return NULL;
81}
82
83}  // namespace crazy
84