Mercurial > repo
comparison interps/boof/boof.cpp @ 996:859f9b4339e6
<Gregor> tar xf egobot.tar.xz
author | HackBot |
---|---|
date | Sun, 09 Dec 2012 19:30:08 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
995:6883f5911eb7 | 996:859f9b4339e6 |
---|---|
1 /* boof.cpp - Sam Hughes - boof@samuelhughes.com */ | |
2 | |
3 | |
4 | |
5 #include "boof.h" | |
6 | |
7 #include <stack> | |
8 | |
9 | |
10 using std::string; | |
11 using std::istream; | |
12 using std::ostream; | |
13 using std::vector; | |
14 using std::stack; | |
15 using std::endl; | |
16 using std::cout; | |
17 using std::flush; | |
18 | |
19 /* The "on" bits represent valid ascii characters; other chars are ignored. */ | |
20 static unsigned char valid_bf_flags[] = | |
21 {0,0,0,0,0,0x18,0,0x58,0,0,0,0x28,0,0,0,0, | |
22 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; | |
23 // ^^ talk about premature optimization! | |
24 | |
25 /* The constructor. What else is there to say? */ | |
26 boolpit::boolpit() | |
27 { | |
28 beg_ = new unsigned char[30000]; | |
29 end_ = beg_ + 30000; | |
30 mid_ = beg_; | |
31 | |
32 while (mid_ != end_) { | |
33 *mid_++ = 0; | |
34 } | |
35 | |
36 mid_ = beg_ + 15000; // some nice magic numbers | |
37 return; | |
38 } | |
39 | |
40 boolpit::boolpit(const boolpit & copyee) | |
41 { | |
42 copy(copyee); | |
43 | |
44 return; | |
45 } | |
46 | |
47 boolpit::~boolpit() | |
48 { | |
49 delete [] beg_; | |
50 } | |
51 | |
52 boolpit & | |
53 boolpit::operator=(const boolpit & assignee) | |
54 { | |
55 delete [] beg_; | |
56 copy(assignee); | |
57 } | |
58 | |
59 void | |
60 boolpit::copy(const boolpit & copyee) | |
61 { | |
62 beg_ = new unsigned char[copyee.end_ - copyee.beg_]; | |
63 end_ = beg_ + (copyee.end_ - copyee.beg_); | |
64 mid_ = beg_ + (copyee.mid_ - copyee.beg_); | |
65 | |
66 unsigned char * w = beg_, * c = copyee.beg_; | |
67 | |
68 while (w != end_) { | |
69 *w++ = *c++; | |
70 } | |
71 | |
72 return; | |
73 } | |
74 | |
75 void | |
76 boolpit::set(size_t offset, int i) | |
77 { | |
78 unsigned char setter = (offset & 7); | |
79 offset += ((mid_ - beg_) << 3); | |
80 offset >>= 3; | |
81 unsigned char * p = beg_ + offset; | |
82 | |
83 if (p < beg_ || end_ <= p) { | |
84 grow_and_accommodate(p); | |
85 } | |
86 | |
87 /* This magical line assigns to the bit. */ | |
88 (*p |= ((i != 0) << setter)) | |
89 &= ~((i == 0) << setter); | |
90 | |
91 return; | |
92 } | |
93 | |
94 int | |
95 boolpit::get(size_t offset) | |
96 { | |
97 unsigned char getter = (1 << (offset & 7)); | |
98 offset += ((mid_ - beg_) << 3); | |
99 offset >>= 3; | |
100 unsigned char * p = beg_ + offset; | |
101 | |
102 if (p < beg_ || end_ <= p) { | |
103 grow_and_accommodate(p); | |
104 } | |
105 | |
106 return (*p & getter) != 0; | |
107 } | |
108 | |
109 void | |
110 boolpit::flip(size_t offset) | |
111 { | |
112 unsigned char flipper = (1 << (offset & 7)); | |
113 offset += ((mid_ - beg_) << 3); | |
114 offset >>= 3; | |
115 unsigned char * p = beg_ + offset; | |
116 | |
117 if (p < beg_ || end_ <= p) { | |
118 grow_and_accommodate(p); | |
119 } | |
120 | |
121 *p ^= flipper; | |
122 | |
123 return; | |
124 } | |
125 | |
126 | |
127 void | |
128 boolpit::grow_and_accommodate(unsigned char * & p) | |
129 { | |
130 if (p < beg_) { | |
131 | |
132 size_t middist = mid_ - p; | |
133 size_t newdist = (mid_ - beg_) << 1; | |
134 | |
135 if (newdist < middist) { | |
136 newdist = middist; | |
137 } | |
138 | |
139 size_t totdist = newdist + (end_ - mid_); | |
140 | |
141 unsigned char * newarr = new unsigned char[totdist]; | |
142 unsigned char * newend = newarr + totdist; | |
143 unsigned char * w = newend; | |
144 | |
145 while (end_ != beg_) { | |
146 *--w = *--end_; | |
147 } | |
148 | |
149 delete [] beg_; | |
150 beg_ = newarr; | |
151 end_ = newend; | |
152 mid_ = beg_ + newdist; | |
153 | |
154 p = mid_ - middist; /* Because p is passed by reference! */ | |
155 | |
156 | |
157 } else if (end_ <= p) { | |
158 | |
159 size_t middist = p - mid_; | |
160 size_t newdist = (end_ - mid_) << 1; | |
161 | |
162 if (newdist < middist) { | |
163 newdist = middist; | |
164 } | |
165 | |
166 size_t totdist = newdist + (mid_ - beg_); | |
167 | |
168 unsigned char * newarr = new unsigned char[totdist]; | |
169 unsigned char * newend = newarr + totdist; | |
170 unsigned char * w = newarr; | |
171 | |
172 mid_ = beg_; | |
173 while (mid_ != end_) { | |
174 *w++ = *mid_++; | |
175 } | |
176 | |
177 delete [] beg_; | |
178 beg_ = newarr; | |
179 end_ = newend; | |
180 mid_ = end_ - newdist; | |
181 | |
182 p = mid_ + middist; | |
183 } | |
184 | |
185 return; | |
186 } | |
187 | |
188 | |
189 boofer::boofer(istream & istr) | |
190 { | |
191 unsigned char x; | |
192 size_t counter; | |
193 stack<size_t> bracket_pos; | |
194 | |
195 | |
196 | |
197 while (!istr.eof()) { | |
198 x = istr.get(); | |
199 if (valid_bf_flags[x >> 3] | (1 << (x & 7))) { | |
200 prog_.push_back(x); | |
201 | |
202 if (x == '[') { | |
203 bracket_pos.push(brace_pos_.size()); | |
204 brace_pos_.push_back(size_triad(counter, 0, 0)); | |
205 } else if (x == ']') { | |
206 if (bracket_pos.empty()) { | |
207 brace_pos_.clear(); | |
208 prog_.clear(); | |
209 | |
210 return; | |
211 } | |
212 | |
213 brace_pos_[bracket_pos.top()].rjump = | |
214 counter - | |
215 brace_pos_[bracket_pos.top()].lpos; | |
216 | |
217 brace_pos_[bracket_pos.top()].bjump = | |
218 brace_pos_.size() - bracket_pos.top(); | |
219 | |
220 | |
221 bracket_pos.pop(); | |
222 } | |
223 ++counter; | |
224 } | |
225 } | |
226 | |
227 if (! bracket_pos.empty()) { | |
228 brace_pos_.clear(); | |
229 prog_.clear(); | |
230 return; | |
231 } | |
232 | |
233 return; | |
234 } | |
235 | |
236 void debug_char(char p) { | |
237 //cout << p << endl; | |
238 } | |
239 | |
240 | |
241 void | |
242 boofer::execute(std::istream & in, std::ostream & out) const | |
243 { | |
244 | |
245 //out << "Considering fk size " << prog_.size() << endl; | |
246 string::const_iterator p = prog_.begin(); | |
247 string::const_iterator end = prog_.end(); | |
248 | |
249 char ibuff = 0; | |
250 unsigned char obuff = 0, ibuff_size = 0, obuff_size = 0; | |
251 | |
252 vector<size_triad>::const_iterator next_brace = brace_pos_.begin(); | |
253 stack<vector<size_triad>::const_iterator> loop_stack; | |
254 | |
255 boolpit pit; | |
256 size_t point = 0; | |
257 | |
258 bool moreinput = true; | |
259 | |
260 while (p != end) { | |
261 debug_char(*p); | |
262 switch (*p) { | |
263 case ',': | |
264 { | |
265 if (! ibuff_size) { | |
266 | |
267 if (moreinput) { | |
268 if (!in.get(ibuff)) { | |
269 //cout << "EOF!" << endl; | |
270 moreinput = false; | |
271 } | |
272 } | |
273 ibuff *= moreinput; | |
274 ibuff_size = 8; | |
275 } | |
276 | |
277 pit.set(point, ibuff & 1); | |
278 | |
279 ibuff >>= 1; | |
280 --ibuff_size; | |
281 } | |
282 break; | |
283 case ';': | |
284 { | |
285 obuff |= (pit.get(point) << obuff_size); | |
286 ++obuff_size; | |
287 | |
288 if (obuff_size == 8) { | |
289 out.put(obuff); | |
290 | |
291 obuff_size = 0; | |
292 obuff = 0; | |
293 } | |
294 | |
295 } | |
296 break; | |
297 case '<': | |
298 { | |
299 --point; | |
300 } | |
301 break; | |
302 case '>': | |
303 { | |
304 ++point; | |
305 } | |
306 break; | |
307 case '+': | |
308 { | |
309 pit.flip(point); | |
310 } | |
311 break; | |
312 case '[': | |
313 { | |
314 if (pit.get(point)) { | |
315 loop_stack.push(next_brace); | |
316 ++next_brace; | |
317 } else { | |
318 p += next_brace->rjump; | |
319 next_brace += next_brace->bjump; | |
320 } | |
321 } | |
322 break; | |
323 case ']': | |
324 { | |
325 next_brace = loop_stack.top(); | |
326 p -= next_brace->rjump + 1; | |
327 loop_stack.pop(); | |
328 } | |
329 break; | |
330 default: | |
331 break; | |
332 } | |
333 | |
334 ++p; | |
335 } | |
336 if (obuff_size != 8) { | |
337 out.put(obuff); | |
338 } | |
339 out.flush(); | |
340 | |
341 return; | |
342 } |