blob: fb81bfe50b1187f8dadfb2eb677cf220733500e3 [file] [log] [blame]
Shinichiro Hamajie7992752015-06-29 18:38:35 +09001// 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 Hamajid18c4272016-02-09 17:35:28 +090017//#define ENABLE_TID_CHECK
18
Shinichiro Hamajie7992752015-06-29 18:38:35 +090019#include "symtab.h"
20
Shinichiro Hamajid18c4272016-02-09 17:35:28 +090021#ifdef ENABLE_TID_CHECK
22#include <pthread.h>
23#endif
Shinichiro Hamajie7992752015-06-29 18:38:35 +090024#include <string.h>
25
26#include <unordered_map>
27
28#include "log.h"
29#include "strutil.h"
Shinichiro Hamajic9b9e5e2016-02-18 18:18:54 +090030#include "var.h"
31
32struct SymbolData {
33 SymbolData()
34 : gv(kUndefined) {
35 }
36
37 Var* gv;
38};
Shinichiro Hamajie7992752015-06-29 18:38:35 +090039
Shinichiro Hamajiba2ccdb2015-07-17 05:55:42 +090040vector<string*>* g_symbols;
Shinichiro Hamajic9b9e5e2016-02-18 18:18:54 +090041static vector<SymbolData> g_symbol_data;
Shinichiro Hamajie7992752015-06-29 18:38:35 +090042
Shinichiro Hamaji43defe02015-07-11 07:06:43 +090043Symbol kEmptySym = Symbol(Symbol::IsUninitialized());
Shinichiro Hamaji94d6f2a2015-07-05 05:32:25 +090044Symbol kShellSym = Symbol(Symbol::IsUninitialized());
45
Shinichiro Hamajie7992752015-06-29 18:38:35 +090046Symbol::Symbol(int v)
47 : v_(v) {
48}
49
Shinichiro Hamajic9b9e5e2016-02-18 18:18:54 +090050Var* 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
62void 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
79ScopedGlobalVar::ScopedGlobalVar(Symbol name, Var* var)
80 : name_(name), orig_(NULL) {
81 orig_ = name.GetGlobalVar();
82 g_symbol_data[name_.val()].gv = var;
83}
84
85ScopedGlobalVar::~ScopedGlobalVar() {
86 g_symbol_data[name_.val()].gv = orig_;
87}
88
Shinichiro Hamajie7992752015-06-29 18:38:35 +090089class Symtab {
90 public:
91 Symtab() {
Shinichiro Hamajid18c4272016-02-09 17:35:28 +090092#ifdef ENABLE_TID_CHECK
93 tid_ = pthread_self();
94#endif
95
Shinichiro Hamajie7992752015-06-29 18:38:35 +090096 CHECK(g_symbols == NULL);
97 g_symbols = &symbols_;
Shinichiro Hamaji82aeb272015-06-30 02:24:36 +090098
99 Symbol s = InternImpl("");
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900100 CHECK(s.v_ == 0);
101 CHECK(Intern("") == s);
Shinichiro Hamaji82aeb272015-06-30 02:24:36 +0900102 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 Hamaji94d6f2a2015-07-05 05:32:25 +0900109
Shinichiro Hamaji43defe02015-07-11 07:06:43 +0900110 kEmptySym = Intern("");
Shinichiro Hamaji94d6f2a2015-07-05 05:32:25 +0900111 kShellSym = Intern("SHELL");
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900112 }
113
Shinichiro Hamajiba2ccdb2015-07-17 05:55:42 +0900114 ~Symtab() {
Shinichiro Hamaji9f127b22015-10-28 18:08:47 +0900115 LOG_STAT("%zu symbols", symbols_.size());
Shinichiro Hamajiba2ccdb2015-07-17 05:55:42 +0900116 for (string* s : symbols_)
117 delete s;
118 }
119
Shinichiro Hamaji82aeb272015-06-30 02:24:36 +0900120 Symbol InternImpl(StringPiece s) {
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900121 auto found = symtab_.find(s);
122 if (found != symtab_.end()) {
123 return found->second;
124 }
Shinichiro Hamajiba2ccdb2015-07-17 05:55:42 +0900125 symbols_.push_back(new string(s.data(), s.size()));
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900126 Symbol sym = Symbol(symtab_.size());
Shinichiro Hamajiba2ccdb2015-07-17 05:55:42 +0900127 bool ok = symtab_.emplace(*symbols_.back(), sym).second;
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900128 CHECK(ok);
129 return sym;
130 }
131
Shinichiro Hamaji82aeb272015-06-30 02:24:36 +0900132 Symbol Intern(StringPiece s) {
Shinichiro Hamajid18c4272016-02-09 17:35:28 +0900133#ifdef ENABLE_TID_CHECK
134 if (tid_ != pthread_self())
135 abort();
136#endif
137
Shinichiro Hamaji82aeb272015-06-30 02:24:36 +0900138 if (s.size() <= 1) {
139 return Symbol(s.empty() ? 0 : (unsigned char)s[0]);
140 }
141 return InternImpl(s);
142 }
143
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900144 private:
145 unordered_map<StringPiece, Symbol> symtab_;
Shinichiro Hamajiba2ccdb2015-07-17 05:55:42 +0900146 vector<string*> symbols_;
Shinichiro Hamajid18c4272016-02-09 17:35:28 +0900147#ifdef ENABLE_TID_CHECK
148 pthread_t tid_;
149#endif
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900150};
151
152static Symtab* g_symtab;
153
154void InitSymtab() {
155 g_symtab = new Symtab;
156}
157
158void QuitSymtab() {
159 delete g_symtab;
160}
161
162Symbol Intern(StringPiece s) {
163 return g_symtab->Intern(s);
164}
165
166string 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}