summaryrefslogtreecommitdiff
path: root/src/lang/token.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/lang/token.cc')
-rw-r--r--src/lang/token.cc268
1 files changed, 268 insertions, 0 deletions
diff --git a/src/lang/token.cc b/src/lang/token.cc
new file mode 100644
index 0000000..5bee9ca
--- /dev/null
+++ b/src/lang/token.cc
@@ -0,0 +1,268 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <lang/token.h>
21#include <algorithm>
22using namespace std;
23
24///////////////////////////////////////////////////////////////////
25
26const unsigned tok_t::CONSTANT=1;
27const unsigned tok_t::RESTRICT=2;
28const unsigned tok_t::NORMAL=4;
29const unsigned tok_t::SYSONLY=8;
30const unsigned tok_t::INIT=16;
31const unsigned tok_t::RUNNABLE=32;
32const unsigned tok_t::FUNCTION=64;
33const unsigned tok_t::BINARY=128;
34const unsigned tok_t::REFERENCE=256;
35const unsigned tok_t::DBREF=512;
36const unsigned tok_t::CRON=1024;
37const unsigned tok_t::PRIVATE=NORMAL|SYSONLY;
38const unsigned tok_t::PUBLIC=RESTRICT|PRIVATE;
39const unsigned tok_t::XMODES=PUBLIC|INIT;
40
41///////////////////////////////////////////////////////////////////
42
43uniheap<sizeof(tok_t)> tok_t::tree;
44void* tok_t::operator new(size_t n) { return tree.push(); }
45void tok_t::operator delete(void* p) { tree.pop(p); }
46
47uniheap<sizeof(reference_t)> reference_t::tree;
48void* reference_t::operator new(size_t n) { return tree.push(); }
49void reference_t::operator delete(void* p) { tree.pop(p); }
50
51uniheap<sizeof(dbref_t)> dbref_t::tree;
52void* dbref_t::operator new(size_t n) { return tree.push(); }
53void dbref_t::operator delete(void* p) { tree.pop(p); }
54
55uniheap<sizeof(runnable_t)> runnable_t::tree;
56void* runnable_t::operator new(size_t n) { return tree.push(); }
57void runnable_t::operator delete(void* p) { tree.pop(p); }
58
59uniheap<sizeof(func_t)> func_t::tree;
60void* func_t::operator new(size_t n) { return tree.push(); }
61void func_t::operator delete(void* p) { tree.pop(p); }
62
63uniheap<sizeof(cron_t)> cron_t::tree;
64void* cron_t::operator new(size_t n) { return tree.push(); }
65void cron_t::operator delete(void* p) { tree.pop(p); }
66
67uniheap<sizeof(binary_t)> binary_t::tree;
68void* binary_t::operator new(size_t n) { return tree.push(); }
69void binary_t::operator delete(void* p) { tree.pop(p); }
70
71///////////////////////////////////////////////////////////////////
72
73mstring uscore2dot(const char* s) {
74 mstring t=s; int p; while((p=t.find('_'))>=0) t[p]='.'; return t;
75}
76
77///////////////////////////////////////////////////////////////////
78
79tok_t::~tok_t() {}
80
81///////////////////////////////////////////////////////////////////
82
83void tokmap::clear()
84{
85 for(iterator p=list.begin();p!=list.end();p++) delete *p;
86 list.clear();
87}
88
89tok_t* tokmap::get_this(const sref& t)
90{
91 pair<iterator,iterator> p=equal_range(list.begin(),list.end(),(val_t)0,comp_t(t));
92 return p.first!=p.second?*p.first:0;
93}
94
95const tok_t* tokmap::get_this(const sref& t) const
96{
97 pair<const_iterator,const_iterator> p=
98 equal_range(list.begin(),list.end(),(val_t)0,comp_t(t));
99 return p.first!=p.second?*p.first:0;
100}
101
102const tok_t* tokmap::get(const sref& t) const
103{
104 const tok_t* p=get_this(t); return p?p:up?up->get(t):0;
105}
106
107tok_t* tokmap::get(const sref& t)
108{
109 tok_t* p=get_this(t); return p?p:up?up->get(t):0;
110}
111
112tok_t* tokmap::set(tok_t* tok,int replace,int force) throw(merror_t)
113{
114 pair<iterator,iterator> p=
115 equal_range(list.begin(),list.end(),(val_t)0,comp_t(tok->name));
116 if(p.first!=p.second) {
117 if(!(*p.first)->is_replaceable(*tok)) {
118 delete tok;
119 THROW("token: Could not set "<<(*p.first)->name<<" - protected");
120 return 0;
121 }
122 else if((*p.first)->is_const()&&!replace) {
123 delete tok;
124 if(force) THROW("token: Could not set "<<(*p.first)->name<<" - constant");
125 return 0;
126 }
127 else { delete *p.first; return *p.first=tok; }
128 }
129 else if(up) return up->set(tok,replace,force);
130 else {
131 mstring name=tok->name;
132 delete tok;
133 if(force) THROW("token: Could not set "<<name<<" - not found");
134 return 0;
135 }
136}
137
138tok_t* tokmap::add(tok_t* tok,int replace,int force) throw(merror_t)
139{
140 tok_t* old=get(tok->name);
141 if(old) {
142 if(!old->is_replaceable(*tok)) {
143 delete tok;
144 THROW("token: Could not add "<<old->name<<" - protected");
145 return 0;
146 }
147 else if(old->is_const()&&!replace) {
148 delete tok;
149 if(force) THROW("token: Could not add "<<old->name<<" - constant");
150 return 0;
151 }
152 }
153 pair<iterator,iterator> p=
154 equal_range(list.begin(),list.end(),(val_t)0,comp_t(tok->name));
155 if(p.first!=p.second) { delete *p.first; return *p.first=tok; }
156 else return *list.insert(p.second,tok);
157}
158
159///////////////////////////////////////////////////////////////////
160
161static void Check(const sref& s) throw(merror_t)
162{
163 if(!is_tokname(s)) THROW("token: bad name ("<<s<<")");
164}
165
166static void CheckArg(const sref& s) throw(merror_t)
167{
168 if(!is_arglist(s)) THROW("ftok: bad argspec ("<<s<<")");
169}
170
171///////////////////////////////////////////////////////////////////
172
173tok_t* Cond(tokmap& map,const sref& s,const sref& b,unsigned m) throw(merror_t)
174{
175 Check(s);
176 return map.add(new tok_t(s,b,m),0,0);
177}
178
179tok_t* Global(tokmap& map,const sref& s,const sref& b,unsigned m,int rpl) throw(merror_t)
180{
181 Check(s);
182 return map.add(new tok_t(s,b,m),rpl,1);
183}
184
185tok_t* Const(tokmap& map,const sref& s,const sref& b,unsigned m,int rpl) throw(merror_t)
186{
187 Check(s);
188 return map.add(new tok_t(s,b,m|tok_t::CONSTANT),rpl,1);
189}
190
191func_t* Func(tokmap& map,const sref& s,const sref& b,
192 unsigned m,const sref& a,int rpl) throw(merror_t)
193{
194 Check(s);
195 CheckArg(a);
196 return (func_t*)map.add(new func_t(s,b,m,a),rpl,1);
197}
198
199cron_t* Cron(tokmap& map,const sref& s,const sref& b,
200 unsigned m,int i,int rpl) throw(merror_t)
201{
202 Check(s);
203 return (cron_t*)map.add(new cron_t(s,b,m,i),rpl,1);
204}
205
206binary_t* Binary(tokmap& map,const sref& s,const sref& b,
207 unsigned m,const sref& a,s_func_t f,int rpl) throw(merror_t)
208{
209 Check(s);
210 CheckArg(a);
211 return (binary_t*)map.add(new binary_t(s,b,m,a,f),rpl,1);
212}
213
214reference_t* Reference(tokmap& map,const sref& s,
215 const sref& b,unsigned m,int rpl) throw(merror_t)
216{
217 Check(s);
218 return (reference_t*)map.add(new reference_t(s,b,m),rpl,1);
219}
220
221dbref_t* DBRef(tokmap& map,const sref& s,
222 const sref& b,unsigned m,int rpl) throw(merror_t)
223{
224 Check(s);
225 return (dbref_t*)map.add(new dbref_t(s,b,m),rpl,1);
226}
227
228void ClearToken(tokmap& map,const sref& s) throw(merror_t)
229{
230 if(s.nempty()) {
231 tokmap::iterator p=map.begin();
232 while(p<map.end()) {
233 if((*p)->name.left(s.size())==s) p=map.erase(p); else p++;
234 }
235 }
236}
237
238///////////////////////////////////////////////////////////////
239
240mstream& operator<<(mstream& out,const runnable_t& ftok)
241{
242 out<<"\\"<<ftok.name;
243 for(const char* p=ftok.arg.begin();p!=ftok.arg.end();p++) out.put('{').put(*p).put('}');
244 return out;
245}
246
247mstring Mode(const tok_t& tok)
248{
249 mstring m;
250 for(int i=11;i>=0;i--) { if(tok.mod&(1<<i)) m+='1'; else m+='0'; }
251 return m;
252}
253
254mstring Desc(const tok_t& tok)
255{
256 mstring m;
257 sref first,rest=tok.body;
258 while(Splitln(first,rest)) {
259 first=first.right_first_not_of(cset_ws);
260 if(*first=='%') {
261 first=first.popf().right_first_not_of(cset_ws);
262 m+=first;
263 m+='\n';
264 }
265 }
266 return m;
267}
268