| Shinichiro Hamaji | e799275 | 2015-06-29 18:38:35 +0900 | [diff] [blame] | 1 | // Copyright 2015 Google Inc. All rights reserved | 
 | 2 | // | 
 | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); | 
 | 4 | // you may not use this file except in compliance with the License. | 
 | 5 | // You may obtain a copy of the License at | 
 | 6 | // | 
 | 7 | //      http://www.apache.org/licenses/LICENSE-2.0 | 
 | 8 | // | 
 | 9 | // Unless required by applicable law or agreed to in writing, software | 
 | 10 | // distributed under the License is distributed on an "AS IS" BASIS, | 
 | 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | 12 | // See the License for the specific language governing permissions and | 
 | 13 | // limitations under the License. | 
 | 14 |  | 
 | 15 | // +build ignore | 
 | 16 |  | 
| Shinichiro Hamaji | d18c427 | 2016-02-09 17:35:28 +0900 | [diff] [blame] | 17 | //#define ENABLE_TID_CHECK | 
 | 18 |  | 
| Shinichiro Hamaji | e799275 | 2015-06-29 18:38:35 +0900 | [diff] [blame] | 19 | #include "symtab.h" | 
 | 20 |  | 
| Shinichiro Hamaji | d18c427 | 2016-02-09 17:35:28 +0900 | [diff] [blame] | 21 | #ifdef ENABLE_TID_CHECK | 
 | 22 | #include <pthread.h> | 
 | 23 | #endif | 
| Shinichiro Hamaji | e799275 | 2015-06-29 18:38:35 +0900 | [diff] [blame] | 24 | #include <string.h> | 
 | 25 |  | 
 | 26 | #include <unordered_map> | 
 | 27 |  | 
 | 28 | #include "log.h" | 
 | 29 | #include "strutil.h" | 
| Shinichiro Hamaji | c9b9e5e | 2016-02-18 18:18:54 +0900 | [diff] [blame] | 30 | #include "var.h" | 
 | 31 |  | 
 | 32 | struct SymbolData { | 
 | 33 |   SymbolData() | 
 | 34 |       : gv(kUndefined) { | 
 | 35 |   } | 
 | 36 |  | 
 | 37 |   Var* gv; | 
 | 38 | }; | 
| Shinichiro Hamaji | e799275 | 2015-06-29 18:38:35 +0900 | [diff] [blame] | 39 |  | 
| Shinichiro Hamaji | ba2ccdb | 2015-07-17 05:55:42 +0900 | [diff] [blame] | 40 | vector<string*>* g_symbols; | 
| Shinichiro Hamaji | c9b9e5e | 2016-02-18 18:18:54 +0900 | [diff] [blame] | 41 | static vector<SymbolData> g_symbol_data; | 
| Shinichiro Hamaji | e799275 | 2015-06-29 18:38:35 +0900 | [diff] [blame] | 42 |  | 
| Shinichiro Hamaji | 43defe0 | 2015-07-11 07:06:43 +0900 | [diff] [blame] | 43 | Symbol kEmptySym = Symbol(Symbol::IsUninitialized()); | 
| Shinichiro Hamaji | 94d6f2a | 2015-07-05 05:32:25 +0900 | [diff] [blame] | 44 | Symbol kShellSym = Symbol(Symbol::IsUninitialized()); | 
 | 45 |  | 
| Shinichiro Hamaji | e799275 | 2015-06-29 18:38:35 +0900 | [diff] [blame] | 46 | Symbol::Symbol(int v) | 
 | 47 |     : v_(v) { | 
 | 48 | } | 
 | 49 |  | 
| Shinichiro Hamaji | c9b9e5e | 2016-02-18 18:18:54 +0900 | [diff] [blame] | 50 | Var* Symbol::GetGlobalVar() const { | 
 | 51 |   if (static_cast<size_t>(v_) >= g_symbol_data.size()) { | 
 | 52 |     g_symbol_data.resize(v_ + 1); | 
 | 53 |   } | 
 | 54 |   Var* v = g_symbol_data[v_].gv; | 
 | 55 |   if (v->Origin() == VarOrigin::ENVIRONMENT || | 
 | 56 |       v->Origin() == VarOrigin::ENVIRONMENT_OVERRIDE) { | 
 | 57 |     Vars::add_used_env_vars(*this); | 
 | 58 |   } | 
 | 59 |   return v; | 
 | 60 | } | 
 | 61 |  | 
 | 62 | void Symbol::SetGlobalVar(Var* v) const { | 
 | 63 |   if (static_cast<size_t>(v_) >= g_symbol_data.size()) { | 
 | 64 |     g_symbol_data.resize(v_ + 1); | 
 | 65 |   } | 
 | 66 |   Var* orig = g_symbol_data[v_].gv; | 
 | 67 |   if (orig->Origin() == VarOrigin::OVERRIDE || | 
 | 68 |       orig->Origin() == VarOrigin::ENVIRONMENT_OVERRIDE) { | 
 | 69 |     return; | 
 | 70 |   } | 
 | 71 |   if (orig->Origin() == VarOrigin::AUTOMATIC) { | 
 | 72 |     ERROR("overriding automatic variable is not implemented yet"); | 
 | 73 |   } | 
 | 74 |   if (orig->IsDefined()) | 
 | 75 |     delete orig; | 
 | 76 |   g_symbol_data[v_].gv = v; | 
 | 77 | } | 
 | 78 |  | 
 | 79 | ScopedGlobalVar::ScopedGlobalVar(Symbol name, Var* var) | 
 | 80 |     : name_(name), orig_(NULL) { | 
 | 81 |   orig_ = name.GetGlobalVar(); | 
 | 82 |   g_symbol_data[name_.val()].gv = var; | 
 | 83 | } | 
 | 84 |  | 
 | 85 | ScopedGlobalVar::~ScopedGlobalVar() { | 
 | 86 |   g_symbol_data[name_.val()].gv = orig_; | 
 | 87 | } | 
 | 88 |  | 
| Shinichiro Hamaji | e799275 | 2015-06-29 18:38:35 +0900 | [diff] [blame] | 89 | class Symtab { | 
 | 90 |  public: | 
 | 91 |   Symtab() { | 
| Shinichiro Hamaji | d18c427 | 2016-02-09 17:35:28 +0900 | [diff] [blame] | 92 | #ifdef ENABLE_TID_CHECK | 
 | 93 |     tid_ = pthread_self(); | 
 | 94 | #endif | 
 | 95 |  | 
| Shinichiro Hamaji | e799275 | 2015-06-29 18:38:35 +0900 | [diff] [blame] | 96 |     CHECK(g_symbols == NULL); | 
 | 97 |     g_symbols = &symbols_; | 
| Shinichiro Hamaji | 82aeb27 | 2015-06-30 02:24:36 +0900 | [diff] [blame] | 98 |  | 
 | 99 |     Symbol s = InternImpl(""); | 
| Shinichiro Hamaji | e799275 | 2015-06-29 18:38:35 +0900 | [diff] [blame] | 100 |     CHECK(s.v_ == 0); | 
 | 101 |     CHECK(Intern("") == s); | 
| Shinichiro Hamaji | 82aeb27 | 2015-06-30 02:24:36 +0900 | [diff] [blame] | 102 |     char b[2]; | 
 | 103 |     b[1] = 0; | 
 | 104 |     for (int i = 1; i < 256; i++) { | 
 | 105 |       b[0] = i; | 
 | 106 |       s = InternImpl(b); | 
 | 107 |       CHECK(s.val() == i); | 
 | 108 |     } | 
| Shinichiro Hamaji | 94d6f2a | 2015-07-05 05:32:25 +0900 | [diff] [blame] | 109 |  | 
| Shinichiro Hamaji | 43defe0 | 2015-07-11 07:06:43 +0900 | [diff] [blame] | 110 |     kEmptySym = Intern(""); | 
| Shinichiro Hamaji | 94d6f2a | 2015-07-05 05:32:25 +0900 | [diff] [blame] | 111 |     kShellSym = Intern("SHELL"); | 
| Shinichiro Hamaji | e799275 | 2015-06-29 18:38:35 +0900 | [diff] [blame] | 112 |   } | 
 | 113 |  | 
| Shinichiro Hamaji | ba2ccdb | 2015-07-17 05:55:42 +0900 | [diff] [blame] | 114 |   ~Symtab() { | 
| Shinichiro Hamaji | 9f127b2 | 2015-10-28 18:08:47 +0900 | [diff] [blame] | 115 |     LOG_STAT("%zu symbols", symbols_.size()); | 
| Shinichiro Hamaji | ba2ccdb | 2015-07-17 05:55:42 +0900 | [diff] [blame] | 116 |     for (string* s : symbols_) | 
 | 117 |       delete s; | 
 | 118 |   } | 
 | 119 |  | 
| Shinichiro Hamaji | 82aeb27 | 2015-06-30 02:24:36 +0900 | [diff] [blame] | 120 |   Symbol InternImpl(StringPiece s) { | 
| Shinichiro Hamaji | e799275 | 2015-06-29 18:38:35 +0900 | [diff] [blame] | 121 |     auto found = symtab_.find(s); | 
 | 122 |     if (found != symtab_.end()) { | 
 | 123 |       return found->second; | 
 | 124 |     } | 
| Shinichiro Hamaji | ba2ccdb | 2015-07-17 05:55:42 +0900 | [diff] [blame] | 125 |     symbols_.push_back(new string(s.data(), s.size())); | 
| Shinichiro Hamaji | e799275 | 2015-06-29 18:38:35 +0900 | [diff] [blame] | 126 |     Symbol sym = Symbol(symtab_.size()); | 
| Shinichiro Hamaji | ba2ccdb | 2015-07-17 05:55:42 +0900 | [diff] [blame] | 127 |     bool ok = symtab_.emplace(*symbols_.back(), sym).second; | 
| Shinichiro Hamaji | e799275 | 2015-06-29 18:38:35 +0900 | [diff] [blame] | 128 |     CHECK(ok); | 
 | 129 |     return sym; | 
 | 130 |   } | 
 | 131 |  | 
| Shinichiro Hamaji | 82aeb27 | 2015-06-30 02:24:36 +0900 | [diff] [blame] | 132 |   Symbol Intern(StringPiece s) { | 
| Shinichiro Hamaji | d18c427 | 2016-02-09 17:35:28 +0900 | [diff] [blame] | 133 | #ifdef ENABLE_TID_CHECK | 
 | 134 |     if (tid_ != pthread_self()) | 
 | 135 |       abort(); | 
 | 136 | #endif | 
 | 137 |  | 
| Shinichiro Hamaji | 82aeb27 | 2015-06-30 02:24:36 +0900 | [diff] [blame] | 138 |     if (s.size() <= 1) { | 
 | 139 |       return Symbol(s.empty() ? 0 : (unsigned char)s[0]); | 
 | 140 |     } | 
 | 141 |     return InternImpl(s); | 
 | 142 |   } | 
 | 143 |  | 
| Shinichiro Hamaji | e799275 | 2015-06-29 18:38:35 +0900 | [diff] [blame] | 144 |  private: | 
 | 145 |   unordered_map<StringPiece, Symbol> symtab_; | 
| Shinichiro Hamaji | ba2ccdb | 2015-07-17 05:55:42 +0900 | [diff] [blame] | 146 |   vector<string*> symbols_; | 
| Shinichiro Hamaji | d18c427 | 2016-02-09 17:35:28 +0900 | [diff] [blame] | 147 | #ifdef ENABLE_TID_CHECK | 
 | 148 |   pthread_t tid_; | 
 | 149 | #endif | 
| Shinichiro Hamaji | e799275 | 2015-06-29 18:38:35 +0900 | [diff] [blame] | 150 | }; | 
 | 151 |  | 
 | 152 | static Symtab* g_symtab; | 
 | 153 |  | 
 | 154 | void InitSymtab() { | 
 | 155 |   g_symtab = new Symtab; | 
 | 156 | } | 
 | 157 |  | 
 | 158 | void QuitSymtab() { | 
 | 159 |   delete g_symtab; | 
 | 160 | } | 
 | 161 |  | 
 | 162 | Symbol Intern(StringPiece s) { | 
 | 163 |   return g_symtab->Intern(s); | 
 | 164 | } | 
 | 165 |  | 
 | 166 | string JoinSymbols(const vector<Symbol>& syms, const char* sep) { | 
 | 167 |   vector<string> strs; | 
 | 168 |   for (Symbol s : syms) { | 
 | 169 |     strs.push_back(s.str()); | 
 | 170 |   } | 
 | 171 |   return JoinStrings(strs, sep); | 
 | 172 | } |