blob: 3d49f2e0839f4156296b25e553d38fc73bd6e931 [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 {
Sasha Smundakae1d58c2018-08-22 09:39:42 -070033 SymbolData() : gv(Var::Undefined()) {}
Shinichiro Hamajic9b9e5e2016-02-18 18:18:54 +090034
35 Var* gv;
36};
Shinichiro Hamajie7992752015-06-29 18:38:35 +090037
Shinichiro Hamajiba2ccdb2015-07-17 05:55:42 +090038vector<string*>* g_symbols;
Shinichiro Hamajic9b9e5e2016-02-18 18:18:54 +090039static vector<SymbolData> g_symbol_data;
Shinichiro Hamajie7992752015-06-29 18:38:35 +090040
Sasha Smundak8174f9b2018-08-13 11:07:30 -070041Symbol kEmptySym;
42Symbol kShellSym;
43Symbol kKatiReadonlySym;
Shinichiro Hamaji94d6f2a2015-07-05 05:32:25 +090044
Dan Willemsen3ce083f2017-10-11 22:17:48 -070045Symbol::Symbol(int v) : v_(v) {}
Shinichiro Hamajie7992752015-06-29 18:38:35 +090046
Dan Willemsenff90ea32017-11-21 13:22:26 -080047Var* Symbol::PeekGlobalVar() const {
48 if (static_cast<size_t>(v_) >= g_symbol_data.size()) {
Sasha Smundakae1d58c2018-08-22 09:39:42 -070049 return Var::Undefined();
Dan Willemsenff90ea32017-11-21 13:22:26 -080050 }
51 return g_symbol_data[v_].gv;
52}
53
Shinichiro Hamajic9b9e5e2016-02-18 18:18:54 +090054Var* Symbol::GetGlobalVar() const {
55 if (static_cast<size_t>(v_) >= g_symbol_data.size()) {
56 g_symbol_data.resize(v_ + 1);
57 }
58 Var* v = g_symbol_data[v_].gv;
59 if (v->Origin() == VarOrigin::ENVIRONMENT ||
60 v->Origin() == VarOrigin::ENVIRONMENT_OVERRIDE) {
61 Vars::add_used_env_vars(*this);
62 }
63 return v;
64}
65
Dan Willemsenf87d49e2016-09-29 20:09:47 -070066void Symbol::SetGlobalVar(Var* v, bool is_override, bool* readonly) const {
Shinichiro Hamajic9b9e5e2016-02-18 18:18:54 +090067 if (static_cast<size_t>(v_) >= g_symbol_data.size()) {
68 g_symbol_data.resize(v_ + 1);
69 }
70 Var* orig = g_symbol_data[v_].gv;
Dan Willemsenf87d49e2016-09-29 20:09:47 -070071 if (orig->ReadOnly()) {
72 if (readonly != nullptr)
73 *readonly = true;
74 else
75 ERROR("*** cannot assign to readonly variable: %s", c_str());
76 return;
77 } else if (readonly != nullptr) {
78 *readonly = false;
79 }
Dan Willemsen3ce083f2017-10-11 22:17:48 -070080 if (!is_override && (orig->Origin() == VarOrigin::OVERRIDE ||
81 orig->Origin() == VarOrigin::ENVIRONMENT_OVERRIDE)) {
Shinichiro Hamajic9b9e5e2016-02-18 18:18:54 +090082 return;
83 }
Po Hu6957e9a2016-06-24 20:05:43 +080084 if (orig->Origin() == VarOrigin::COMMAND_LINE &&
Dan Willemsen3ce083f2017-10-11 22:17:48 -070085 v->Origin() == VarOrigin::FILE) {
Po Hu6957e9a2016-06-24 20:05:43 +080086 return;
87 }
Shinichiro Hamajic9b9e5e2016-02-18 18:18:54 +090088 if (orig->Origin() == VarOrigin::AUTOMATIC) {
89 ERROR("overriding automatic variable is not implemented yet");
90 }
91 if (orig->IsDefined())
92 delete orig;
93 g_symbol_data[v_].gv = v;
94}
95
96ScopedGlobalVar::ScopedGlobalVar(Symbol name, Var* var)
97 : name_(name), orig_(NULL) {
98 orig_ = name.GetGlobalVar();
99 g_symbol_data[name_.val()].gv = var;
100}
101
102ScopedGlobalVar::~ScopedGlobalVar() {
103 g_symbol_data[name_.val()].gv = orig_;
104}
105
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900106class Symtab {
107 public:
108 Symtab() {
Shinichiro Hamajid18c4272016-02-09 17:35:28 +0900109#ifdef ENABLE_TID_CHECK
110 tid_ = pthread_self();
111#endif
112
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900113 CHECK(g_symbols == NULL);
114 g_symbols = &symbols_;
Shinichiro Hamaji82aeb272015-06-30 02:24:36 +0900115
116 Symbol s = InternImpl("");
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900117 CHECK(s.v_ == 0);
118 CHECK(Intern("") == s);
Shinichiro Hamaji82aeb272015-06-30 02:24:36 +0900119 char b[2];
120 b[1] = 0;
121 for (int i = 1; i < 256; i++) {
122 b[0] = i;
123 s = InternImpl(b);
124 CHECK(s.val() == i);
125 }
Shinichiro Hamaji94d6f2a2015-07-05 05:32:25 +0900126
Shinichiro Hamaji43defe02015-07-11 07:06:43 +0900127 kEmptySym = Intern("");
Shinichiro Hamaji94d6f2a2015-07-05 05:32:25 +0900128 kShellSym = Intern("SHELL");
Sasha Smundak8174f9b2018-08-13 11:07:30 -0700129 kKatiReadonlySym = Intern(".KATI_READONLY");
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900130 }
131
Shinichiro Hamajiba2ccdb2015-07-17 05:55:42 +0900132 ~Symtab() {
Shinichiro Hamaji9f127b22015-10-28 18:08:47 +0900133 LOG_STAT("%zu symbols", symbols_.size());
Shinichiro Hamajiba2ccdb2015-07-17 05:55:42 +0900134 for (string* s : symbols_)
135 delete s;
136 }
137
Shinichiro Hamaji82aeb272015-06-30 02:24:36 +0900138 Symbol InternImpl(StringPiece s) {
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900139 auto found = symtab_.find(s);
140 if (found != symtab_.end()) {
141 return found->second;
142 }
Shinichiro Hamajiba2ccdb2015-07-17 05:55:42 +0900143 symbols_.push_back(new string(s.data(), s.size()));
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900144 Symbol sym = Symbol(symtab_.size());
Shinichiro Hamajiba2ccdb2015-07-17 05:55:42 +0900145 bool ok = symtab_.emplace(*symbols_.back(), sym).second;
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900146 CHECK(ok);
147 return sym;
148 }
149
Shinichiro Hamaji82aeb272015-06-30 02:24:36 +0900150 Symbol Intern(StringPiece s) {
Shinichiro Hamajid18c4272016-02-09 17:35:28 +0900151#ifdef ENABLE_TID_CHECK
152 if (tid_ != pthread_self())
153 abort();
154#endif
155
Shinichiro Hamaji82aeb272015-06-30 02:24:36 +0900156 if (s.size() <= 1) {
157 return Symbol(s.empty() ? 0 : (unsigned char)s[0]);
158 }
159 return InternImpl(s);
160 }
161
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900162 private:
163 unordered_map<StringPiece, Symbol> symtab_;
Shinichiro Hamajiba2ccdb2015-07-17 05:55:42 +0900164 vector<string*> symbols_;
Shinichiro Hamajid18c4272016-02-09 17:35:28 +0900165#ifdef ENABLE_TID_CHECK
166 pthread_t tid_;
167#endif
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900168};
169
170static Symtab* g_symtab;
171
172void InitSymtab() {
173 g_symtab = new Symtab;
174}
175
176void QuitSymtab() {
177 delete g_symtab;
178}
179
180Symbol Intern(StringPiece s) {
181 return g_symtab->Intern(s);
182}
183
184string JoinSymbols(const vector<Symbol>& syms, const char* sep) {
185 vector<string> strs;
186 for (Symbol s : syms) {
187 strs.push_back(s.str());
188 }
189 return JoinStrings(strs, sep);
190}