blob: edb6752d2bd420924ed708a2d5cf71aa80c67afb [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
Stefan Becker29b9b742016-04-07 13:29:23 +030021#include <iostream>
22
Shinichiro Hamajid18c4272016-02-09 17:35:28 +090023#ifdef ENABLE_TID_CHECK
24#include <pthread.h>
25#endif
Shinichiro Hamajie7992752015-06-29 18:38:35 +090026#include <string.h>
27
28#include <unordered_map>
29
30#include "log.h"
31#include "strutil.h"
Shinichiro Hamajic9b9e5e2016-02-18 18:18:54 +090032#include "var.h"
33
34struct SymbolData {
35 SymbolData()
36 : gv(kUndefined) {
37 }
38
39 Var* gv;
40};
Shinichiro Hamajie7992752015-06-29 18:38:35 +090041
Shinichiro Hamajiba2ccdb2015-07-17 05:55:42 +090042vector<string*>* g_symbols;
Shinichiro Hamajic9b9e5e2016-02-18 18:18:54 +090043static vector<SymbolData> g_symbol_data;
Shinichiro Hamajie7992752015-06-29 18:38:35 +090044
Shinichiro Hamaji43defe02015-07-11 07:06:43 +090045Symbol kEmptySym = Symbol(Symbol::IsUninitialized());
Shinichiro Hamaji94d6f2a2015-07-05 05:32:25 +090046Symbol kShellSym = Symbol(Symbol::IsUninitialized());
47
Shinichiro Hamajie7992752015-06-29 18:38:35 +090048Symbol::Symbol(int v)
49 : v_(v) {
50}
51
Shinichiro Hamajic9b9e5e2016-02-18 18:18:54 +090052Var* Symbol::GetGlobalVar() const {
53 if (static_cast<size_t>(v_) >= g_symbol_data.size()) {
54 g_symbol_data.resize(v_ + 1);
55 }
56 Var* v = g_symbol_data[v_].gv;
57 if (v->Origin() == VarOrigin::ENVIRONMENT ||
58 v->Origin() == VarOrigin::ENVIRONMENT_OVERRIDE) {
59 Vars::add_used_env_vars(*this);
60 }
61 return v;
62}
63
Stefan Becker29b9b742016-04-07 13:29:23 +030064void Symbol::SetGlobalVar(Var* v, bool is_override) const {
Shinichiro Hamajic9b9e5e2016-02-18 18:18:54 +090065 if (static_cast<size_t>(v_) >= g_symbol_data.size()) {
66 g_symbol_data.resize(v_ + 1);
67 }
68 Var* orig = g_symbol_data[v_].gv;
Stefan Becker29b9b742016-04-07 13:29:23 +030069 if (!is_override &&
70 (orig->Origin() == VarOrigin::OVERRIDE ||
71 orig->Origin() == VarOrigin::ENVIRONMENT_OVERRIDE)) {
Shinichiro Hamajic9b9e5e2016-02-18 18:18:54 +090072 return;
73 }
74 if (orig->Origin() == VarOrigin::AUTOMATIC) {
75 ERROR("overriding automatic variable is not implemented yet");
76 }
77 if (orig->IsDefined())
78 delete orig;
79 g_symbol_data[v_].gv = v;
80}
81
82ScopedGlobalVar::ScopedGlobalVar(Symbol name, Var* var)
83 : name_(name), orig_(NULL) {
84 orig_ = name.GetGlobalVar();
85 g_symbol_data[name_.val()].gv = var;
86}
87
88ScopedGlobalVar::~ScopedGlobalVar() {
89 g_symbol_data[name_.val()].gv = orig_;
90}
91
Shinichiro Hamajie7992752015-06-29 18:38:35 +090092class Symtab {
93 public:
94 Symtab() {
Shinichiro Hamajid18c4272016-02-09 17:35:28 +090095#ifdef ENABLE_TID_CHECK
96 tid_ = pthread_self();
97#endif
98
Shinichiro Hamajie7992752015-06-29 18:38:35 +090099 CHECK(g_symbols == NULL);
100 g_symbols = &symbols_;
Shinichiro Hamaji82aeb272015-06-30 02:24:36 +0900101
102 Symbol s = InternImpl("");
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900103 CHECK(s.v_ == 0);
104 CHECK(Intern("") == s);
Shinichiro Hamaji82aeb272015-06-30 02:24:36 +0900105 char b[2];
106 b[1] = 0;
107 for (int i = 1; i < 256; i++) {
108 b[0] = i;
109 s = InternImpl(b);
110 CHECK(s.val() == i);
111 }
Shinichiro Hamaji94d6f2a2015-07-05 05:32:25 +0900112
Shinichiro Hamaji43defe02015-07-11 07:06:43 +0900113 kEmptySym = Intern("");
Shinichiro Hamaji94d6f2a2015-07-05 05:32:25 +0900114 kShellSym = Intern("SHELL");
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900115 }
116
Shinichiro Hamajiba2ccdb2015-07-17 05:55:42 +0900117 ~Symtab() {
Shinichiro Hamaji9f127b22015-10-28 18:08:47 +0900118 LOG_STAT("%zu symbols", symbols_.size());
Shinichiro Hamajiba2ccdb2015-07-17 05:55:42 +0900119 for (string* s : symbols_)
120 delete s;
121 }
122
Shinichiro Hamaji82aeb272015-06-30 02:24:36 +0900123 Symbol InternImpl(StringPiece s) {
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900124 auto found = symtab_.find(s);
125 if (found != symtab_.end()) {
126 return found->second;
127 }
Shinichiro Hamajiba2ccdb2015-07-17 05:55:42 +0900128 symbols_.push_back(new string(s.data(), s.size()));
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900129 Symbol sym = Symbol(symtab_.size());
Shinichiro Hamajiba2ccdb2015-07-17 05:55:42 +0900130 bool ok = symtab_.emplace(*symbols_.back(), sym).second;
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900131 CHECK(ok);
132 return sym;
133 }
134
Shinichiro Hamaji82aeb272015-06-30 02:24:36 +0900135 Symbol Intern(StringPiece s) {
Shinichiro Hamajid18c4272016-02-09 17:35:28 +0900136#ifdef ENABLE_TID_CHECK
137 if (tid_ != pthread_self())
138 abort();
139#endif
140
Shinichiro Hamaji82aeb272015-06-30 02:24:36 +0900141 if (s.size() <= 1) {
142 return Symbol(s.empty() ? 0 : (unsigned char)s[0]);
143 }
144 return InternImpl(s);
145 }
146
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900147 private:
148 unordered_map<StringPiece, Symbol> symtab_;
Shinichiro Hamajiba2ccdb2015-07-17 05:55:42 +0900149 vector<string*> symbols_;
Shinichiro Hamajid18c4272016-02-09 17:35:28 +0900150#ifdef ENABLE_TID_CHECK
151 pthread_t tid_;
152#endif
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900153};
154
155static Symtab* g_symtab;
156
157void InitSymtab() {
158 g_symtab = new Symtab;
159}
160
161void QuitSymtab() {
162 delete g_symtab;
163}
164
165Symbol Intern(StringPiece s) {
166 return g_symtab->Intern(s);
167}
168
169string JoinSymbols(const vector<Symbol>& syms, const char* sep) {
170 vector<string> strs;
171 for (Symbol s : syms) {
172 strs.push_back(s.str());
173 }
174 return JoinStrings(strs, sep);
175}