blob: 455d9676e070add95faffee7fab4534ef325f0ac [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#ifndef SYMTAB_H_
16#define SYMTAB_H_
17
Sasha Smundak8174f9b2018-08-13 11:07:30 -070018#include <bitset>
Shinichiro Hamajie7992752015-06-29 18:38:35 +090019#include <string>
20#include <vector>
21
22#include "string_piece.h"
23
24using namespace std;
25
Shinichiro Hamajiba2ccdb2015-07-17 05:55:42 +090026extern vector<string*>* g_symbols;
Shinichiro Hamajie7992752015-06-29 18:38:35 +090027
28class Symtab;
Shinichiro Hamajic9b9e5e2016-02-18 18:18:54 +090029class Var;
Shinichiro Hamajie7992752015-06-29 18:38:35 +090030
31class Symbol {
32 public:
Sasha Smundak8174f9b2018-08-13 11:07:30 -070033 explicit Symbol() : v_(-1) {}
Shinichiro Hamaji94d6f2a2015-07-05 05:32:25 +090034
Dan Willemsen3ce083f2017-10-11 22:17:48 -070035 const string& str() const { return *((*g_symbols)[v_]); }
Shinichiro Hamajie7992752015-06-29 18:38:35 +090036
Dan Willemsen3ce083f2017-10-11 22:17:48 -070037 const char* c_str() const { return str().c_str(); }
Shinichiro Hamajie7992752015-06-29 18:38:35 +090038
39 bool empty() const { return !v_; }
40
41 int val() const { return v_; }
42
43 char get(size_t i) const {
44 const string& s = str();
45 if (i >= s.size())
46 return 0;
47 return s[i];
48 }
49
Shinichiro Hamajia7984ad2015-09-11 16:33:16 +090050 bool IsValid() const { return v_ >= 0; }
51
Dan Willemsenff90ea32017-11-21 13:22:26 -080052 Var* PeekGlobalVar() const;
Shinichiro Hamajic9b9e5e2016-02-18 18:18:54 +090053 Var* GetGlobalVar() const;
Dan Willemsen3ce083f2017-10-11 22:17:48 -070054 void SetGlobalVar(Var* v,
55 bool is_override = false,
56 bool* readonly = nullptr) const;
Shinichiro Hamajic9b9e5e2016-02-18 18:18:54 +090057
Shinichiro Hamajie7992752015-06-29 18:38:35 +090058 private:
59 explicit Symbol(int v);
60
61 int v_;
62
63 friend class Symtab;
Sasha Smundak8174f9b2018-08-13 11:07:30 -070064 friend class SymbolSet;
65};
66
67/* A set of symbols represented as bitmap indexed by Symbol's ordinal value. */
68class SymbolSet {
69 public:
Dan Willemsenee57a3f2018-11-05 16:18:44 -080070 SymbolSet() : low_(0), high_(0) {}
Sasha Smundak8174f9b2018-08-13 11:07:30 -070071
72 /* Returns true if Symbol belongs to this set. */
73 bool exists(Symbol sym) const {
74 size_t bit_nr = static_cast<size_t>(sym.val());
75 return sym.IsValid() && bit_nr >= low_ && bit_nr < high_ &&
Dan Willemsenee57a3f2018-11-05 16:18:44 -080076 bits_[(bit_nr - low_) / 64][(bit_nr - low_) % 64];
Sasha Smundak8174f9b2018-08-13 11:07:30 -070077 }
78
79 /* Adds Symbol to this set. */
80 void insert(Symbol sym) {
81 if (!sym.IsValid()) {
82 return;
83 }
84 size_t bit_nr = static_cast<size_t>(sym.val());
85 if (bit_nr < low_ || bit_nr >= high_) {
Dan Willemsenee57a3f2018-11-05 16:18:44 -080086 resize(bit_nr);
Sasha Smundak8174f9b2018-08-13 11:07:30 -070087 }
88 bits_[(bit_nr - low_) / 64][(bit_nr - low_) % 64] = true;
89 }
90
91 /* Returns the number of Symbol's in this set. */
92 size_t size() const {
93 size_t n = 0;
94 for (auto const& bitset : bits_) {
95 n += bitset.count();
96 }
97 return n;
98 }
99
100 /* Allow using foreach.
101 * E.g.,
102 * SymbolSet symbol_set;
103 * for (auto const& symbol: symbol_set) { ... }
104 */
105 class iterator {
106 const SymbolSet* bitset_;
107 size_t pos_;
108
109 iterator(const SymbolSet* bitset, size_t pos)
Dan Willemsenee57a3f2018-11-05 16:18:44 -0800110 : bitset_(bitset), pos_(pos) {}
Sasha Smundak8174f9b2018-08-13 11:07:30 -0700111
112 /* Proceed to the next Symbol. */
113 void next() {
114 size_t bit_nr = (pos_ > bitset_->low_) ? pos_ - bitset_->low_ : 0;
115 while (bit_nr < (bitset_->high_ - bitset_->low_)) {
116 if ((bit_nr % 64) == 0 && !bitset_->bits_[bit_nr / 64].any()) {
117 bit_nr += 64;
118 continue;
119 }
120 if (bitset_->bits_[bit_nr / 64][bit_nr % 64]) {
121 break;
122 }
123 ++bit_nr;
124 }
125 pos_ = bitset_->low_ + bit_nr;
126 }
127
128 public:
129 iterator& operator++() {
130 if (pos_ < bitset_->high_) {
131 ++pos_;
132 next();
133 }
134 return *this;
135 }
136
137 bool operator==(iterator other) const {
138 return bitset_ == other.bitset_ && pos_ == other.pos_;
139 }
140
Dan Willemsenee57a3f2018-11-05 16:18:44 -0800141 bool operator!=(iterator other) const { return !(*this == other); }
Sasha Smundak8174f9b2018-08-13 11:07:30 -0700142
Dan Willemsenee57a3f2018-11-05 16:18:44 -0800143 Symbol operator*() { return Symbol(pos_); }
Sasha Smundak8174f9b2018-08-13 11:07:30 -0700144
145 friend class SymbolSet;
146 };
147
148 iterator begin() const {
149 iterator it(this, low_);
150 it.next();
151 return it;
152 }
153
Dan Willemsenee57a3f2018-11-05 16:18:44 -0800154 iterator end() const { return iterator(this, high_); }
Sasha Smundak8174f9b2018-08-13 11:07:30 -0700155
156 private:
157 friend class iterator;
158
159 /* Ensure that given bit number is in [low_, high_) */
160 void resize(size_t bit_nr) {
161 size_t new_low = bit_nr & ~63;
162 size_t new_high = (bit_nr + 64) & ~63;
163 if (bits_.empty()) {
164 high_ = low_ = new_low;
165 }
166 if (new_low > low_) {
167 new_low = low_;
168 }
169 if (new_high <= high_) {
170 new_high = high_;
171 }
172 if (new_low == low_) {
173 bits_.resize((new_high - new_low) / 64);
174 } else {
Dan Willemsenee57a3f2018-11-05 16:18:44 -0800175 std::vector<std::bitset<64> > newbits((new_high - new_low) / 64);
176 std::copy(bits_.begin(), bits_.end(),
177 newbits.begin() + (low_ - new_low) / 64);
Sasha Smundak8174f9b2018-08-13 11:07:30 -0700178 bits_.swap(newbits);
179 }
180 low_ = new_low;
181 high_ = new_high;
182 }
183
184 /* Keep only the (aligned) range where at least one bit has been set.
185 * E.g., if we only ever set bits 65 and 141, |low_| will be 64, |high_|
186 * will be 192, and |bits_| will have 2 elements.
187 */
188 size_t low_;
189 size_t high_;
190 std::vector<std::bitset<64> > bits_;
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900191};
192
Shinichiro Hamajic9b9e5e2016-02-18 18:18:54 +0900193class ScopedGlobalVar {
194 public:
195 ScopedGlobalVar(Symbol name, Var* var);
196 ~ScopedGlobalVar();
197
198 private:
199 Symbol name_;
200 Var* orig_;
201};
202
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900203inline bool operator==(const Symbol& x, const Symbol& y) {
204 return x.val() == y.val();
205}
206
Dan Willemsenb248caa2015-10-01 16:07:48 -0700207inline bool operator<(const Symbol& x, const Symbol& y) {
Shinichiro Hamaji675ecf32015-10-03 10:57:31 +0900208 return x.val() < y.val();
Dan Willemsenb248caa2015-10-01 16:07:48 -0700209}
210
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900211namespace std {
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700212template <>
213struct hash<Symbol> {
214 size_t operator()(const Symbol& s) const { return s.val(); }
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900215};
Dan Willemsen3ce083f2017-10-11 22:17:48 -0700216} // namespace std
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900217
Shinichiro Hamaji43defe02015-07-11 07:06:43 +0900218extern Symbol kEmptySym;
Shinichiro Hamaji94d6f2a2015-07-05 05:32:25 +0900219extern Symbol kShellSym;
Sasha Smundak8174f9b2018-08-13 11:07:30 -0700220extern Symbol kKatiReadonlySym;
Shinichiro Hamaji94d6f2a2015-07-05 05:32:25 +0900221
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900222void InitSymtab();
223void QuitSymtab();
224Symbol Intern(StringPiece s);
225
226string JoinSymbols(const vector<Symbol>& syms, const char* sep);
227
228#endif // SYMTAB_H_