1 // -*- related-file-name: "../include/click/lexer.hh" -*-
2 /*
3 * lexer.{cc,hh} -- parses Click language files, produces Router objects
4 * Eddie Kohler
5 *
6 * Copyright (c) 1999-2012 Eddie Kohler
7 * Copyright (c) 1999-2000 Massachusetts Institute of Technology
8 * Copyright (c) 2000 Mazu Networks, Inc.
9 * Copyright (c) 2001-2003 International Computer Science Institute
10 * Copyright (c) 2004-2011 Regents of the University of California
11 * Copyright (c) 2008-2012 Meraki, Inc.
12 * Copyright (c) 2010 Intel Corporation
13 * Copyright (c) 2012-2016 Eddie Kohler
14 *
15 * Permission is hereby granted, free of charge, to any person obtaining a
16 * copy of this software and associated documentation files (the "Software"),
17 * to deal in the Software without restriction, subject to the conditions
18 * listed in the Click LICENSE file. These conditions include: you must
19 * preserve this copyright notice, and you cannot mention the copyright
20 * holders in advertising related to the Software without their permission.
21 * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
22 * notice is a summary of the Click LICENSE file; the license in that file is
23 * legally binding.
24 */
25
26 #include <click/config.h>
27 #include <click/lexer.hh>
28 #include <click/router.hh>
29 #include <click/error.hh>
30 #include <click/confparse.hh>
31 #include <click/args.hh>
32 #include <click/glue.hh>
33 #include <click/straccum.hh>
34 #include <click/variableenv.hh>
35 #include <click/bitvector.hh>
36 #include <click/standard/errorelement.hh>
37 #if CLICK_USERLEVEL
38 # include <click/userutils.hh>
39 #endif
40 CLICK_DECLS
41
42 #ifdef CLICK_LINUXMODULE
43 # define ADD_ELEMENT_TYPE(name, factory, thunk, scoped) \
44 add_element_type((name), (factory), (thunk), 0, (scoped))
45 #else
46 # define ADD_ELEMENT_TYPE(name, factory, thunk, scoped) \
47 add_element_type((name), (factory), (thunk), (scoped))
48 #endif
49
50 static const char * const port_names[2] = {"input", "output"};
51
52 static void
redeclaration_error(ErrorHandler * errh,const char * what,String name,const String & landmark,const String & old_landmark)53 redeclaration_error(ErrorHandler *errh, const char *what, String name, const String &landmark, const String &old_landmark)
54 {
55 if (!what)
56 what = "";
57 const char *sp = (strlen(what) ? " " : "");
58 errh->lerror(landmark, "redeclaration of %s%s%<%s%>", what, sp, name.c_str());
59 errh->lerror(old_landmark, "%<%s%> previously declared here", name.c_str());
60 }
61
62 //
63 // ELEMENT FACTORIES
64 //
65
66 static Element *
error_element_factory(uintptr_t)67 error_element_factory(uintptr_t)
68 {
69 return new ErrorElement;
70 }
71
72 static Element *
compound_element_factory(uintptr_t)73 compound_element_factory(uintptr_t)
74 {
75 assert(0);
76 return 0;
77 }
78
79 //
80 // CLASS LEXER::TUNNELEND
81 //
82
83 class Lexer::TunnelEnd {
84
85 Router::Port _port;
86 Vector<Router::Port> _correspond;
87 int8_t _expanded;
88 bool _isoutput;
89 TunnelEnd *_other;
90 TunnelEnd *_next;
91
92 friend class Lexer;
93
94 public:
95
TunnelEnd(const Router::Port & port,bool isoutput,TunnelEnd * next)96 TunnelEnd(const Router::Port &port, bool isoutput, TunnelEnd *next)
97 : _port(port), _expanded(0), _isoutput(isoutput), _other(0), _next(next) {
98 }
99
port() const100 const Router::Port &port() const { return _port; }
isoutput() const101 bool isoutput() const { return _isoutput; }
next() const102 TunnelEnd *next() const { return _next; }
other() const103 TunnelEnd *other() const { return _other; }
104
pair_with(TunnelEnd * d)105 void pair_with(TunnelEnd *d) {
106 assert(!_other && !d->_other && _isoutput == !d->_isoutput
107 && _port.port == d->_port.port);
108 _other = d;
109 d->_other = this;
110 }
111
112 void expand(Lexer *, Vector<Router::Port> &);
113
114 };
115
116 //
117 // CLASS LEXER::COMPOUND
118 //
119
120 class Lexer::Compound : public Element { public:
121
122 Compound(const String &, const String &, VariableEnvironment *parent);
123
name() const124 const String &name() const { return _name; }
125 const char *printable_name_c_str();
landmark() const126 const String &landmark() const { return _landmark; }
nformals() const127 int nformals() const { return _nformals; }
scope() const128 const VariableEnvironment &scope() const { return _scope; }
scope()129 VariableEnvironment &scope() { return _scope; }
130 inline void define(const String &fname, const String &ftype, bool isformal, Lexer *);
depth() const131 int depth() const { return _scope.depth(); }
132
landmark_string(const String & filename,unsigned lineno)133 static String landmark_string(const String &filename, unsigned lineno) {
134 if (!lineno)
135 return filename;
136 else if (filename && (filename.back() == ':' || isspace((unsigned char) filename.back())))
137 return filename + String(lineno);
138 else
139 return filename + ":" + String(lineno);
140 }
141
element_landmark(int e) const142 String element_landmark(int e) const {
143 return landmark_string(_element_filenames[e], _element_linenos[e]);
144 }
145
146 int check_pseudoelement(int e, bool isoutput, const char *name, ErrorHandler *errh) const;
147 void finish(ErrorHandler *errh);
148
149 inline int assign_arguments(const Vector<String> &args, Vector<String> *values) const;
150 int resolve(Lexer *, int etype, int ninputs, int noutputs, Vector<String> &, ErrorHandler *, const String &landmark);
151 void expand_into(Lexer *, int, VariableEnvironment &);
152 void connect(int from_idx, int from_port, int to_idx, int to_port);
153
154 String deanonymize_element_name(int eidx);
155
class_name() const156 const char *class_name() const { return _name.c_str(); }
157 void *cast(const char *);
clone() const158 Compound *clone() const { return 0; }
159
set_overload_type(int t)160 void set_overload_type(int t) { _overload_type = t; }
161 inline Compound *overload_compound(Lexer *) const;
162
163 String signature() const;
164 static String signature(const String &name, const Vector<String> *formal_types, int nargs, int ninputs, int noutputs);
165
166 private:
167
168 String _name;
169 String _landmark;
170 int _overload_type;
171
172 VariableEnvironment _scope;
173 int _nformals;
174 int _ninputs;
175 int _noutputs;
176 bool _scope_order_error : 1;
177
178 HashTable<String, int> _element_map;
179 Vector<int> _elements;
180 Vector<String> _element_names;
181 Vector<String> _element_configurations;
182 Vector<String> _element_filenames;
183 Vector<unsigned> _element_linenos;
184 Vector<int> _element_nports[2];
185 int _anonymous_offset;
186
187 Vector<Router::Connection> _conn;
188
189 friend class Lexer;
190
191 };
192
Compound(const String & name,const String & lm,VariableEnvironment * parent)193 Lexer::Compound::Compound(const String &name, const String &lm, VariableEnvironment *parent)
194 : _name(name), _landmark(lm), _overload_type(-1),
195 _scope(parent),
196 _nformals(0), _ninputs(0), _noutputs(0), _scope_order_error(false),
197 _element_map(-1), _anonymous_offset(0)
198 {
199 }
200
201 const char *
printable_name_c_str()202 Lexer::Compound::printable_name_c_str()
203 {
204 if (_name)
205 return _name.c_str();
206 else
207 return "<anonymous>";
208 }
209
210 void *
cast(const char * s)211 Lexer::Compound::cast(const char *s)
212 {
213 if (strcmp(s, "Lexer::Compound") == 0 || _name == s)
214 return this;
215 else
216 return 0;
217 }
218
219 inline void
define(const String & name,const String & value,bool isformal,Lexer * l)220 Lexer::Compound::define(const String &name, const String &value, bool isformal, Lexer *l)
221 {
222 assert(!isformal || _nformals == _scope.size());
223 if (!_scope.define(name, value, false))
224 l->lerror("parameter %<$%s%> multiply defined", name.c_str());
225 else if (isformal) {
226 _nformals = _scope.size();
227 if (value)
228 for (int i = 0; i < _scope.size() - 1; i++)
229 if (_scope.value(i) == value) {
230 l->lerror("repeated keyword parameter %<%s%> in compound element", value.c_str());
231 break;
232 }
233 if (!_scope_order_error && _nformals > 1
234 && ((!value && _scope.value(_nformals - 2))
235 || _scope.value(_nformals - 2) == "__REST__")) {
236 l->lerror("compound element parameters out of order\n(The correct order is %<[positional], [keywords], [__REST__]%>.)");
237 _scope_order_error = true;
238 }
239 }
240 }
241
242 void
connect(int from_idx,int from_port,int to_idx,int to_port)243 Lexer::Compound::connect(int from_idx, int from_port, int to_idx, int to_port)
244 {
245 if (from_port < 0)
246 from_port = 0;
247 if (to_port < 0)
248 to_port = 0;
249 _conn.push_back(Router::Connection(from_idx, from_port, to_idx, to_port));
250 if (_element_nports[0][to_idx] <= to_port)
251 _element_nports[0][to_idx] = to_port + 1;
252 if (_element_nports[1][from_idx] <= from_port)
253 _element_nports[1][from_idx] = from_port + 1;
254 }
255
256 int
check_pseudoelement(int which,bool isoutput,const char * name,ErrorHandler * errh) const257 Lexer::Compound::check_pseudoelement(int which, bool isoutput, const char *name, ErrorHandler *errh) const
258 {
259 Bitvector used(_element_nports[1-isoutput][which]);
260 for (const Connection *it = _conn.begin(); it != _conn.end(); ++it)
261 if ((*it)[1-isoutput].idx == which)
262 used[(*it)[1-isoutput].port] = true;
263 if (_element_nports[isoutput][which])
264 errh->error("%<%s%> pseudoelement %<%s%> may only be used as %s", name, port_names[isoutput], port_names[1-isoutput]);
265 for (int i = 0; i < used.size(); i++)
266 if (!used[i])
267 errh->error("%<%s%> %s %d missing", name, port_names[isoutput], i);
268 return used.size();
269 }
270
271 void
finish(ErrorHandler * errh)272 Lexer::Compound::finish(ErrorHandler *errh)
273 {
274 assert(_element_names[0] == "input" && _element_names[1] == "output");
275 LandmarkErrorHandler lerrh(errh, _landmark);
276 _ninputs = check_pseudoelement(0, false, printable_name_c_str(), &lerrh);
277 _noutputs = check_pseudoelement(1, true, printable_name_c_str(), &lerrh);
278
279 // deanonymize element names
280 for (int i = 0; i < _elements.size(); i++)
281 if (_element_names[i][0] == ';')
282 deanonymize_element_name(i);
283 }
284
285 inline Lexer::Compound *
overload_compound(Lexer * lexer) const286 Lexer::Compound::overload_compound(Lexer *lexer) const
287 {
288 if (_overload_type >= 0 && lexer->_element_types[_overload_type].factory == compound_element_factory)
289 return (Compound *) lexer->_element_types[_overload_type].thunk;
290 else
291 return 0;
292 }
293
294 inline int
assign_arguments(const Vector<String> & args,Vector<String> * values) const295 Lexer::Compound::assign_arguments(const Vector<String> &args, Vector<String> *values) const
296 {
297 return cp_assign_arguments(args, _scope.values().begin(), _scope.values().begin() + _nformals, values);
298 }
299
300 int
resolve(Lexer * lexer,int etype,int ninputs,int noutputs,Vector<String> & args,ErrorHandler * errh,const String & landmark)301 Lexer::Compound::resolve(Lexer *lexer, int etype, int ninputs, int noutputs, Vector<String> &args, ErrorHandler *errh, const String &landmark)
302 {
303 // Try to return an element class, even if it is wrong -- the error messages
304 // are friendlier
305 Compound *ct = this;
306 int closest_etype = -1;
307 int nct = 0;
308
309 while (ct) {
310 nct++;
311 if (ct->_ninputs == ninputs && ct->_noutputs == noutputs
312 && ct->assign_arguments(args, &args) >= 0)
313 return etype;
314 else if (ct->assign_arguments(args, 0) >= 0)
315 closest_etype = etype;
316
317 if (Compound *next = ct->overload_compound(lexer)) {
318 etype = ct->_overload_type;
319 ct = next;
320 } else if (ct->_overload_type >= 0)
321 return ct->_overload_type;
322 else
323 break;
324 }
325
326 if (nct != 1 || closest_etype < 0) {
327 errh->lerror(landmark, "no match for %<%s%>", signature(name(), 0, args.size(), ninputs, noutputs).c_str());
328 ContextErrorHandler cerrh(errh, "candidates are:");
329 for (ct = this; ct; ct = ct->overload_compound(lexer))
330 cerrh.lmessage(ct->landmark(), "%s", ct->signature().c_str());
331 }
332 ct = (closest_etype >= 0 ? (Compound *) lexer->_element_types[closest_etype].thunk : 0);
333 if (ct)
334 ct->assign_arguments(args, &args);
335 return closest_etype;
336 }
337
338 String
signature(const String & name,const Vector<String> * formal_types,int nargs,int ninputs,int noutputs)339 Lexer::Compound::signature(const String &name, const Vector<String> *formal_types, int nargs, int ninputs, int noutputs)
340 {
341 StringAccum sa;
342 sa << (name ? name : String("<anonymous>"));
343
344 if (formal_types && formal_types->size()) {
345 sa << '(';
346 for (int i = 0; i < formal_types->size(); i++) {
347 if (i)
348 sa << ", ";
349 if ((*formal_types)[i] == "")
350 sa << "<arg>";
351 else if ((*formal_types)[i] == "__REST__")
352 sa << "...";
353 else
354 sa << (*formal_types)[i];
355 }
356 sa << ')';
357 }
358
359 const char *pl_args = (nargs == 1 ? " argument, " : " arguments, ");
360 const char *pl_ins = (ninputs == 1 ? " input, " : " inputs, ");
361 const char *pl_outs = (noutputs == 1 ? " output" : " outputs");
362 sa << '[';
363 if (!formal_types && nargs > 0)
364 sa << nargs << pl_args;
365 sa << ninputs << pl_ins << noutputs << pl_outs;
366 sa << ']';
367
368 return sa.take_string();
369 }
370
371 String
signature() const372 Lexer::Compound::signature() const
373 {
374 return signature(_name, &scope().values(), -1, _ninputs, _noutputs);
375 }
376
377 void
expand_into(Lexer * lexer,int which,VariableEnvironment & ve)378 Lexer::Compound::expand_into(Lexer *lexer, int which, VariableEnvironment &ve)
379 {
380 assert(_element_names[0] == "input" && _element_names[1] == "output");
381
382 ErrorHandler *errh = lexer->_errh;
383 String ename = lexer->_c->_element_names[which];
384
385 lexer->_c->_elements[which] = TUNNEL_TYPE;
386 int eidexes[3];
387 lexer->add_tunnels(ename, eidexes);
388
389 Vector<int> eidx_map;
390 eidx_map.push_back(eidexes[1]);
391 eidx_map.push_back(eidexes[2]);
392
393 // 'name_slash' is 'name' constrained to end with a slash
394 String ename_slash = ename + "/";
395 for (int i = 2; i < _elements.size(); ++i) {
396 String cname = ename_slash + _element_names[i];
397 int eidx = lexer->_c->_element_map[cname];
398 if (eidx >= 0) {
399 redeclaration_error(errh, "element", cname, lexer->element_landmark(which), lexer->element_landmark(eidx));
400 eidx_map.push_back(-1);
401 continue;
402 }
403 if (lexer->element_type(cname) >= 0)
404 errh->lerror(lexer->element_landmark(which), "%<%s%> is an element class", cname.c_str());
405 if (_elements[i] == TUNNEL_TYPE) {
406 eidx_map.resize(eidx_map.size() + 3);
407 // probably should assert() next 2 elements are tunnel type and
408 // have the expected names
409 lexer->add_tunnels(cname, eidx_map.end() - 3);
410 i += 2;
411 } else {
412 eidx = lexer->get_element(cname, _elements[i], cp_expand(_element_configurations[i], ve), _element_filenames[i], _element_linenos[i]);
413 eidx_map.push_back(eidx);
414 }
415 }
416
417 // now copy hookups
418 for (const Connection *cp = _conn.begin(); cp != _conn.end(); ++cp)
419 if (eidx_map[(*cp)[0].idx] >= 0 && eidx_map[(*cp)[0].idx] >= 0)
420 lexer->_c->connect(eidx_map[(*cp)[1].idx], (*cp)[1].port,
421 eidx_map[(*cp)[0].idx], (*cp)[0].port);
422
423 // now expand those
424 for (int i = 2; i < eidx_map.size(); i++)
425 if (eidx_map[i] >= 0)
426 lexer->expand_compound_element(eidx_map[i], ve);
427 }
428
429 //
430 // LEXER
431 //
432
433 // "elements" and "last_elements" list all elements and port references.
434 // Each vector is a concatenated series of groups, each of which looks like:
435 // group[0] element index
436 // group[1] number of input ports
437 // group[2] number of output ports
438 // group[3...3+group[1]] input ports
439 // group[3+group[1]...3+group[1]+group[2]] output ports
440
441 struct Lexer::ParseState {
442 enum {
443 s_statement, s_first_element, s_element, s_next_element,
444 s_connector, s_connection_done,
445 s_compound_element, s_compound_type, s_compound_elementclass,
446 s_stopped
447 };
448 enum {
449 t_file, t_compound, t_group
450 };
451
452 int state;
453 int _type;
454
455 Vector<int> last_elements;
456 int connector;
457
458 ElementState *_head;
459 ElementState *_tail;
460 bool any_implicit;
461 bool any_ports;
462 bool last_connection_ends_output;
463 Vector<int> elements;
464 int cur_epos;
465
466 String _element_name;
467
468 HashTable<String, int> _saved_type_map;
469 Compound *_saved_compound;
470 Compound *_compound_first;
471 Compound *_compound_last;
472 int _compound_extension;
473
474 ParseState *_parent;
475 int _depth;
476
ParseStateLexer::ParseState477 ParseState(int type, ParseState *parent)
478 : state(s_statement), _type(type), connector(0),
479 last_connection_ends_output(true),
480 _parent(parent), _depth(parent ? parent->_depth + 1 : 0) {
481 }
482
enter_element_stateLexer::ParseState483 void enter_element_state() {
484 _head = _tail = 0;
485 any_implicit = any_ports = false;
486 elements.clear();
487 state = s_element;
488 }
first_element_setLexer::ParseState489 bool first_element_set() const {
490 return last_elements.empty();
491 }
492
start_elementLexer::ParseState493 void start_element() {
494 cur_epos = elements.size();
495 elements.push_back(-1);
496 elements.push_back(0);
497 elements.push_back(0);
498 }
nportsLexer::ParseState499 int nports(bool isoutput) const {
500 return elements[cur_epos + 1 + isoutput];
501 }
clear_portsLexer::ParseState502 void clear_ports(bool isoutput) {
503 assert(isoutput || elements[cur_epos + 2] == 0);
504 elements.resize(elements.size() - elements[cur_epos + 1 + isoutput]);
505 elements[cur_epos + 1 + isoutput] = 0;
506 }
push_back_portLexer::ParseState507 void push_back_port(bool isoutput, int port) {
508 assert(isoutput || elements[cur_epos + 2] == 0);
509 elements.push_back(port);
510 ++elements[cur_epos + 1 + isoutput];
511 }
512 };
513
FileState(const String & data,const String & filename)514 Lexer::FileState::FileState(const String &data, const String &filename)
515 : _big_string(data), _end(data.end()), _pos(data.begin()),
516 _filename(filename ? filename : String::make_stable("config", 6)),
517 _original_filename(_filename), _lineno(1)
518 {
519 }
520
Lexer()521 Lexer::Lexer()
522 : _file(String(), String()), _lextra(0), _unlex_pos(0),
523 _element_type_map(-1),
524 _last_element_type(ET_NULL), _free_element_type(-1),
525 _global_scope(0), _c(0), _ps(0),
526 _errh(ErrorHandler::default_handler())
527 {
528 end_parse(ET_NULL); // clear private state
529 ADD_ELEMENT_TYPE("<tunnel>", error_element_factory, 0, false);
530 ADD_ELEMENT_TYPE("Error", error_element_factory, 0, false);
531 assert(element_type("<tunnel>") == TUNNEL_TYPE && element_type("Error") == ERROR_TYPE);
532 }
533
~Lexer()534 Lexer::~Lexer()
535 {
536 end_parse(ET_NULL);
537
538 // get rid of nonscoped element types
539 for (int t = 0; t < _element_types.size(); t++)
540 if (_element_types[t].factory == compound_element_factory) {
541 Lexer::Compound *compound = (Lexer::Compound *) _element_types[t].thunk;
542 delete compound;
543 }
544 }
545
546 int
begin_parse(const String & data,const String & filename,LexerExtra * lextra,ErrorHandler * errh)547 Lexer::begin_parse(const String &data, const String &filename,
548 LexerExtra *lextra, ErrorHandler *errh)
549 {
550 _file = FileState(data, filename);
551 _compact_config = false;
552
553 _c = new Compound("", "", 0);
554 _ps = new ParseState(ParseState::t_file, 0);
555
556 _lextra = lextra;
557 _errh = (errh ? errh : ErrorHandler::default_handler());
558
559 return lexical_scoping_in();
560 }
561
562 void
end_parse(int cookie)563 Lexer::end_parse(int cookie)
564 {
565 lexical_scoping_out(cookie);
566
567 for (TunnelEnd **tep = _tunnels.begin(); tep != _tunnels.end(); ++tep)
568 while (TunnelEnd *t = *tep) {
569 *tep = t->next();
570 delete t;
571 }
572 _tunnels.clear();
573
574 delete _c;
575 _c = 0;
576 delete _ps;
577 _ps = 0;
578
579 _requirements.clear();
580 _libraries.clear();
581
582 _file = FileState(String(), String());
583 _lextra = 0;
584
585 // also free out Strings held in the _unlex buffer
586 for (int i = 0; i < UNLEX_SIZE; ++i)
587 _unlex[i] = Lexeme();
588 _unlex_pos = 0;
589
590 _errh = ErrorHandler::default_handler();
591 }
592
593
594 // LEXING: LOWEST LEVEL
595
596 String
remaining_text() const597 Lexer::remaining_text() const
598 {
599 return _file._big_string.substring(_file._pos, _file._big_string.end());
600 }
601
602 void
set_remaining_text(const String & s)603 Lexer::set_remaining_text(const String &s)
604 {
605 _file._big_string = s;
606 _file._pos = s.begin();
607 _file._end = s.end();
608 }
609
610 const char *
skip_line(const char * s)611 Lexer::FileState::skip_line(const char *s)
612 {
613 _lineno++;
614 for (; s < _end; s++)
615 if (*s == '\n')
616 return s + 1;
617 else if (*s == '\r') {
618 if (s + 1 < _end && s[1] == '\n')
619 return s + 2;
620 else
621 return s + 1;
622 }
623 _lineno--;
624 return s;
625 }
626
627 const char *
skip_slash_star(const char * s)628 Lexer::FileState::skip_slash_star(const char *s)
629 {
630 for (; s < _end; s++)
631 if (*s == '\n')
632 _lineno++;
633 else if (*s == '\r') {
634 if (s + 1 < _end && s[1] == '\n')
635 s++;
636 _lineno++;
637 } else if (*s == '*' && s + 1 < _end && s[1] == '/')
638 return s + 2;
639 return _end;
640 }
641
642 const char *
skip_backslash_angle(const char * s)643 Lexer::FileState::skip_backslash_angle(const char *s)
644 {
645 for (; s < _end; s++)
646 if (*s == '\n')
647 _lineno++;
648 else if (*s == '\r') {
649 if (s + 1 < _end && s[1] == '\n')
650 s++;
651 _lineno++;
652 } else if (*s == '/' && s + 1 < _end) {
653 if (s[1] == '/')
654 s = skip_line(s + 2) - 1;
655 else if (s[1] == '*')
656 s = skip_slash_star(s + 2) - 1;
657 } else if (*s == '>')
658 return s + 1;
659 return _end;
660 }
661
662 const char *
skip_quote(const char * s,char endc)663 Lexer::FileState::skip_quote(const char *s, char endc)
664 {
665 for (; s < _end; s++)
666 if (*s == '\n')
667 _lineno++;
668 else if (*s == '\r') {
669 if (s + 1 < _end && s[1] == '\n')
670 s++;
671 _lineno++;
672 } else if (*s == '\\' && endc == '\"' && s + 1 < _end) {
673 if (s[1] == '<')
674 s = skip_backslash_angle(s + 2) - 1;
675 else
676 s++;
677 } else if (*s == endc)
678 return s + 1;
679 return _end;
680 }
681
682 const char *
process_line_directive(const char * s,Lexer * lexer)683 Lexer::FileState::process_line_directive(const char *s, Lexer *lexer)
684 {
685 for (s++; s < _end && (*s == ' ' || *s == '\t'); s++)
686 /* nada */;
687 if (s + 4 < _end && *s == 'l' && s[1] == 'i'
688 && s[2] == 'n' && s[3] == 'e'
689 && (s[4] == ' ' || s[4] == '\t')) {
690 for (s += 5; s < _end && (*s == ' ' || *s == '\t'); s++)
691 /* nada */;
692 }
693 if (s >= _end || !isdigit((unsigned char) *s)) {
694 // complain about bad directive
695 lexer->lerror("unknown preprocessor directive");
696 return skip_line(s);
697 }
698
699 // parse line number
700 for (_lineno = 0; s < _end && isdigit((unsigned char) *s); s++)
701 _lineno = _lineno * 10 + *s - '0';
702 _lineno--; // account for extra line
703
704 for (; s < _end && (*s == ' ' || *s == '\t'); s++)
705 /* nada */;
706 if (s < _end && *s == '\"') {
707 // parse filename
708 const char *first_in_filename = s;
709 for (s++; s < _end && *s != '\"' && *s != '\n' && *s != '\r'; s++)
710 if (*s == '\\' && s + 1 < _end && s[1] != '\n' && s[1] != '\r')
711 s++;
712 _filename = cp_unquote(_big_string.substring(first_in_filename, s) + "\"");
713 // an empty filename means return to the input file's name
714 if (!_filename)
715 _filename = _original_filename;
716 }
717
718 // reach end of line
719 for (; s < _end && *s != '\n' && *s != '\r'; s++)
720 /* nada */;
721 if (s + 1 < _end && *s == '\r' && s[1] == '\n')
722 s++;
723 return s;
724 }
725
726 Lexeme
next_lexeme(Lexer * lexer)727 Lexer::FileState::next_lexeme(Lexer *lexer)
728 {
729 const char *s = _pos;
730 while (true) {
731 while (s < _end && isspace((unsigned char) *s)) {
732 if (*s == '\n')
733 _lineno++;
734 else if (*s == '\r') {
735 if (s + 1 < _end && s[1] == '\n')
736 s++;
737 _lineno++;
738 }
739 s++;
740 }
741 if (s >= _end) {
742 _pos = _end;
743 return Lexeme();
744 } else if (*s == '/' && s + 1 < _end) {
745 if (s[1] == '/')
746 s = skip_line(s + 2);
747 else if (s[1] == '*')
748 s = skip_slash_star(s + 2);
749 else
750 break;
751 } else if (*s == '#' && (s == _big_string.begin() || s[-1] == '\n' || s[-1] == '\r'))
752 s = process_line_directive(s, lexer);
753 else
754 break;
755 }
756
757 const char *word_pos = s;
758
759 // find length of current word
760 if (isalnum((unsigned char) *s) || *s == '_' || *s == '@') {
761 more_word_characters:
762 s++;
763 while (s < _end && (isalnum((unsigned char) *s) || *s == '_' || *s == '@'))
764 s++;
765 if (s + 1 < _end && *s == '/' && (isalnum((unsigned char) s[1]) || s[1] == '_' || s[1] == '@'))
766 goto more_word_characters;
767 _pos = s;
768 String word = _big_string.substring(word_pos, s);
769 if (word.equals("elementclass", 12))
770 return Lexeme(lexElementclass, word);
771 else if (word.equals("require", 7))
772 return Lexeme(lexRequire, word);
773 else if (word.equals("provide", 7))
774 return Lexeme(lexProvide, word);
775 else if (word.equals("define", 6))
776 return Lexeme(lexDefine, word);
777 else
778 return Lexeme(lexIdent, word, lexer->_compact_config);
779 }
780
781 // check for variable
782 if (*s == '$') {
783 s++;
784 while (s < _end && (isalnum((unsigned char) *s) || *s == '_'))
785 s++;
786 if (s + 1 > word_pos) {
787 _pos = s;
788 return Lexeme(lexVariable, _big_string.substring(word_pos + 1, s), lexer->_compact_config);
789 } else
790 s--;
791 }
792
793 if (s + 1 < _end) {
794 if (*s == '-' && s[1] == '>') {
795 _pos = s + 2;
796 return Lexeme(lexArrow, _big_string.substring(s, s + 2));
797 } else if (*s == '=' && s[1] == '>') {
798 _pos = s + 2;
799 return Lexeme(lex2Arrow, _big_string.substring(s, s + 2));
800 } else if (*s == ':' && s[1] == ':') {
801 _pos = s + 2;
802 return Lexeme(lex2Colon, _big_string.substring(s, s + 2));
803 } else if (*s == '|' && s[1] == '|') {
804 _pos = s + 2;
805 return Lexeme(lex2Bar, _big_string.substring(s, s + 2));
806 }
807 }
808 if (s + 2 < _end && *s == '.' && s[1] == '.' && s[2] == '.') {
809 _pos = s + 3;
810 return Lexeme(lex3Dot, _big_string.substring(s, s + 3));
811 }
812
813 _pos = s + 1;
814 return Lexeme(*s, _big_string.substring(s, s + 1));
815 }
816
817 String
lex_config(Lexer * lexer)818 Lexer::FileState::lex_config(Lexer *lexer)
819 {
820 const char *config_pos = _pos;
821 const char *s = _pos;
822 unsigned paren_depth = 1;
823
824 String r;
825 for (; s < _end; s++)
826 if (*s == '(')
827 paren_depth++;
828 else if (*s == ')') {
829 paren_depth--;
830 if (!paren_depth)
831 break;
832 } else if (*s == '\n')
833 _lineno++;
834 else if (*s == '\r') {
835 if (s + 1 < _end && s[1] == '\n')
836 s++;
837 _lineno++;
838 } else if (*s == '#' && (s[-1] == '\n' || s[-1] == '\r')) {
839 r.append(config_pos, s - config_pos);
840 s = process_line_directive(s, lexer) - 1;
841 config_pos = s + 1;
842 } else if (*s == '/' && s + 1 < _end) {
843 if (s[1] == '/')
844 s = skip_line(s + 2) - 1;
845 else if (s[1] == '*')
846 s = skip_slash_star(s + 2) - 1;
847 } else if (*s == '\'' || *s == '\"')
848 s = skip_quote(s + 1, *s) - 1;
849 else if (*s == '\\' && s + 1 < _end && s[1] == '<')
850 s = skip_backslash_angle(s + 2) - 1;
851
852 _pos = s;
853 r += _big_string.substring(config_pos, s);
854 return lexer->_compact_config ? r.compact() : r;
855 }
856
857 String
lexeme_string(int kind)858 Lexer::lexeme_string(int kind)
859 {
860 static const char names[] = "identifier\0variable\0'->'\0'=>'\0"
861 "'::'\0'||'\0'...'\0'elementclass'\0'require'\0'provide'\0"
862 "'define'";
863 static const uint8_t offsets[] = {
864 0, 11, 20, 25, 30, 35, 40, 46, 61, 71, 81, 90
865 };
866 static_assert(sizeof(names) == 90, "names screwup.");
867
868 char buf[14];
869 if (kind >= lexIdent && kind < lexIdent + (int) sizeof(offsets) - 1) {
870 const uint8_t *op = offsets + (kind - lexIdent);
871 return String::make_stable(names + op[0], op[1] - op[0] - 1);
872 } else if (kind >= 32 && kind < 127) {
873 sprintf(buf, "'%c'", kind);
874 return buf;
875 } else {
876 sprintf(buf, "'\\%03d'", kind);
877 return buf;
878 }
879 }
880
881
882 // LEXING: MIDDLE LEVEL (WITH PUSHBACK)
883
884 bool
expect(int kind,bool no_error)885 Lexer::expect(int kind, bool no_error)
886 {
887 if (_unlex_pos) {
888 if (_unlex[_unlex_pos - 1].is(kind)) {
889 --_unlex_pos;
890 return true;
891 }
892 } else {
893 // Never adds to _unlex, which requires a nonobvious implementation.
894 String old_filename = _file._filename;
895 unsigned old_lineno = _file._lineno;
896 const char *old_pos = _file._pos;
897 if (lex().is(kind))
898 return true;
899 _file._filename = old_filename;
900 _file._lineno = old_lineno;
901 _file._pos = old_pos;
902 }
903 if (!no_error)
904 lerror("expected %s", lexeme_string(kind).c_str());
905 return false;
906 }
907
908
909 // ERRORS
910
911 String
landmark() const912 Lexer::FileState::landmark() const
913 {
914 return Compound::landmark_string(_filename, _lineno);
915 }
916
917 int
lerror(const char * format,...)918 Lexer::lerror(const char *format, ...)
919 {
920 va_list val;
921 va_start(val, format);
922 _errh->xmessage(_file.landmark(), ErrorHandler::e_error, format, val);
923 va_end(val);
924 return -1;
925 }
926
927 int
lerror_syntax(const Lexeme & t)928 Lexer::lerror_syntax(const Lexeme &t)
929 {
930 return lerror("syntax error near %<%#s%>", t.string().c_str());
931 }
932
933
934 // ELEMENT TYPES
935
936 int
add_element_type(const String & name,ElementFactory factory,uintptr_t thunk,struct module * module,bool scoped)937 Lexer::add_element_type(const String &name, ElementFactory factory, uintptr_t thunk,
938 #ifdef CLICK_LINUXMODULE
939 struct module *module,
940 #endif
941 bool scoped)
942 {
943 assert(factory); // 3.Sep.2003: anonymous compounds have name ""
944 int tid;
945 if (_free_element_type < 0) {
946 tid = _element_types.size();
947 _element_types.push_back(ElementType());
948 } else {
949 tid = _free_element_type;
950 _free_element_type = _element_types[tid].next;
951 }
952 _element_types[tid].factory = factory;
953 _element_types[tid].thunk = thunk;
954 #ifdef CLICK_LINUXMODULE
955 _element_types[tid].module = module;
956 #endif
957 _element_types[tid].name = name;
958 _element_types[tid].next = _last_element_type | (scoped ? (int)ET_SCOPED : 0);
959 if (name)
960 _element_type_map.set(name, tid);
961 _last_element_type = tid;
962 return tid;
963 }
964
965 int
force_element_type(String name,bool report_error)966 Lexer::force_element_type(String name, bool report_error)
967 {
968 int ftid = element_type(name);
969 if (ftid >= 0)
970 return ftid;
971 if (report_error)
972 lerror("unknown element class %<%s%>", name.c_str());
973 return ADD_ELEMENT_TYPE(name, error_element_factory, 0, true);
974 }
975
976 int
lexical_scoping_in() const977 Lexer::lexical_scoping_in() const
978 {
979 return _last_element_type;
980 }
981
982 void
lexical_scoping_out(int last)983 Lexer::lexical_scoping_out(int last)
984 {
985 int *prev = &_last_element_type;
986 while (*prev != last && *prev != ET_NULL) {
987 assert(!(*prev & ET_SCOPED));
988 int *next = &_element_types[*prev].next;
989 if (*next & ET_SCOPED)
990 remove_element_type(*prev, prev);
991 else
992 prev = next;
993 }
994 }
995
996 int
remove_element_type(int removed,int * prev_hint)997 Lexer::remove_element_type(int removed, int *prev_hint)
998 {
999 // exit early if trying to remove bad type
1000 if (removed < 0 || removed >= _element_types.size() || _element_types[removed].factory == 0)
1001 return -1;
1002
1003 // fix _element_type_next chain
1004 if (!prev_hint || (int)(*prev_hint & ET_TMASK) != removed)
1005 for (prev_hint = &_last_element_type;
1006 (*prev_hint & ET_TMASK) != ET_NULL && (int)(*prev_hint & ET_TMASK) != removed;
1007 prev_hint = &_element_types[*prev_hint & ET_TMASK].next)
1008 /* nada */;
1009 assert(prev_hint);
1010 if ((int)(*prev_hint & ET_TMASK) == removed)
1011 *prev_hint = (*prev_hint & ~ET_TMASK) | (_element_types[removed].next & ET_TMASK);
1012
1013 // fix up element type name map
1014 const String &name = _element_types[removed].name;
1015 if (name && element_type(name) == removed) {
1016 int trav;
1017 for (trav = _element_types[removed].next & ET_TMASK;
1018 trav != ET_NULL && _element_types[trav].name != name;
1019 trav = _element_types[trav].next & ET_TMASK)
1020 /* nada */;
1021 if (trav == ET_NULL)
1022 _element_type_map.erase(name);
1023 else
1024 _element_type_map.set(name, trav);
1025 }
1026
1027 // remove stuff
1028 if (_element_types[removed].factory == compound_element_factory) {
1029 Lexer::Compound *compound = (Lexer::Compound *) _element_types[removed].thunk;
1030 delete compound;
1031 }
1032 _element_types[removed].factory = 0;
1033 _element_types[removed].name = String();
1034 _element_types[removed].next = _free_element_type;
1035 _free_element_type = removed;
1036
1037 return 0;
1038 }
1039
1040 void
element_type_names(Vector<String> & v) const1041 Lexer::element_type_names(Vector<String> &v) const
1042 {
1043 for (HashTable<String, int>::const_iterator i = _element_type_map.begin(); i.live(); i++)
1044 if (i.value() >= 0 && i.key() != "<tunnel>")
1045 v.push_back(i.key());
1046 }
1047
1048
1049 // PORT TUNNELS
1050
1051 void
add_tunnels(String name,int * eidxes)1052 Lexer::add_tunnels(String name, int *eidxes)
1053 {
1054 String names[4];
1055 names[0] = names[3] = name;
1056 names[1] = name + "/" + port_names[0];
1057 names[2] = name + "/" + port_names[1];
1058
1059 Port ports[4];
1060 bool ok = true;
1061 for (int i = 0; i < 3; ++i) {
1062 ports[i].idx = eidxes[i] = get_element(names[i], TUNNEL_TYPE);
1063 ports[i].port = 0;
1064 if (_c->_elements[eidxes[i]] != TUNNEL_TYPE) {
1065 redeclaration_error(_errh, "element", names[i], _file.landmark(), _c->element_landmark(ports[i].idx));
1066 ok = false;
1067 }
1068 }
1069 ports[3] = ports[0];
1070
1071 if (ok && _c->depth() == 0) {
1072 TunnelEnd *tes[4];
1073 for (int i = 0; i < 4; ++i) {
1074 tes[i] = find_tunnel(ports[i], i % 2, true);
1075 if (tes[i]->other()) {
1076 redeclaration_error(_errh, "connection tunnel", names[i], _file.landmark(), _c->element_landmark(ports[i].idx));
1077 ok = false;
1078 }
1079 }
1080 if (ok) {
1081 tes[0]->pair_with(tes[1]);
1082 tes[2]->pair_with(tes[3]);
1083 }
1084 }
1085 }
1086
1087 // ELEMENTS
1088
1089 int
get_element(String name,int etype,const String & conf,const String & filename,unsigned lineno)1090 Lexer::get_element(String name, int etype, const String &conf,
1091 const String &filename, unsigned lineno)
1092 {
1093 assert(name && etype >= 0 && etype < _element_types.size());
1094
1095 // if an element 'name' already exists return it
1096 if (_c->_element_map[name] >= 0)
1097 return _c->_element_map[name];
1098
1099 int eid = _c->_elements.size();
1100 _c->_element_map.set(name, eid);
1101
1102 // check 'name' for validity
1103 for (int i = 0; i < name.length(); i++) {
1104 bool ok = false;
1105 for (; i < name.length() && name[i] != '/'; i++)
1106 if (!isdigit((unsigned char) name[i]))
1107 ok = true;
1108 if (!ok) {
1109 lerror("element name %<%s%> has all-digit component", name.c_str());
1110 break;
1111 }
1112 }
1113
1114 _c->_element_names.push_back(name);
1115 _c->_element_configurations.push_back(conf);
1116 if (!filename && !lineno) {
1117 _c->_element_filenames.push_back(_file._filename);
1118 _c->_element_linenos.push_back(_file._lineno);
1119 } else {
1120 _c->_element_filenames.push_back(filename);
1121 _c->_element_linenos.push_back(lineno);
1122 }
1123 _c->_elements.push_back(etype);
1124 _c->_element_nports[0].push_back(0);
1125 _c->_element_nports[1].push_back(0);
1126 return eid;
1127 }
1128
1129 String
anon_element_name(const String & class_name) const1130 Lexer::anon_element_name(const String &class_name) const
1131 {
1132 int anonymizer = _c->_elements.size() - _c->_anonymous_offset + 1;
1133 return ";" + class_name + "@" + String(anonymizer);
1134 }
1135
1136 String
deanonymize_element_name(int eidx)1137 Lexer::Compound::deanonymize_element_name(int eidx)
1138 {
1139 // This function uses _element_map.
1140 String name = _element_names[eidx].substring(1);
1141 if (_element_map[name] >= 0) {
1142 int at_pos = name.find_right('@');
1143 assert(at_pos >= 0);
1144 String prefix = name.substring(0, at_pos + 1);
1145 const char *abegin = name.begin() + at_pos + 1, *aend = abegin;
1146 while (aend < name.end() && isdigit((unsigned char) *aend))
1147 ++aend;
1148 int anonymizer = 0;
1149 IntArg(10).parse(name.substring(abegin, aend), anonymizer);
1150 do {
1151 anonymizer++;
1152 name = prefix + String(anonymizer);
1153 } while (_element_map[name] >= 0);
1154 }
1155 _element_map.set(name, eidx);
1156 _element_names[eidx] = name;
1157 return name;
1158 }
1159
1160 String
element_name(int eid) const1161 Lexer::element_name(int eid) const
1162 {
1163 if (eid < 0 || eid >= _c->_elements.size())
1164 return "##no-such-element##";
1165 else if (_c->_element_names[eid])
1166 return _c->_element_names[eid];
1167 else {
1168 char buf[100];
1169 sprintf(buf, "@%d", eid);
1170 int t = _c->_elements[eid];
1171 if (t == TUNNEL_TYPE)
1172 return "<tunnel" + String(buf) + ">";
1173 else if (!_element_types[t].factory)
1174 return "<null" + String(buf) + ">";
1175 else
1176 return _element_types[t].name + String(buf);
1177 }
1178 }
1179
1180 String
element_landmark(int eid) const1181 Lexer::element_landmark(int eid) const
1182 {
1183 if (eid < 0 || eid >= _c->_elements.size())
1184 return String::make_stable("##no-such-element##");
1185 else if (String s = _c->element_landmark(eid))
1186 return s;
1187 else
1188 return String::make_stable("<unknown>");
1189 }
1190
1191
1192 // PARSING
1193
1194 void
yport(bool isoutput)1195 Lexer::yport(bool isoutput)
1196 {
1197 if (!expect('[', true))
1198 return;
1199 int last_port = -1;
1200 bool dash = false;
1201
1202 while (1) {
1203 Lexeme t = lex();
1204 if (t.is(lexIdent)) {
1205 int port;
1206 if (!IntArg().parse(t.string(), port)) {
1207 lerror("syntax error: port number should be integer");
1208 port = 0;
1209 }
1210 if (dash) {
1211 for (++last_port; last_port <= port; ++last_port)
1212 _ps->push_back_port(isoutput, last_port);
1213 } else {
1214 _ps->push_back_port(isoutput, port);
1215 last_port = port;
1216 }
1217 } else if (t.is(']')) {
1218 if (_ps->nports(isoutput) == 0)
1219 _ps->push_back_port(isoutput, 0);
1220 _ps->push_back_port(isoutput, -1);
1221 break;
1222 } else {
1223 lerror("syntax error: expected port number");
1224 unlex(t);
1225 break;
1226 }
1227
1228 t = lex();
1229 if (t.is(']'))
1230 break;
1231 else if (t.is('-') && !dash)
1232 dash = true;
1233 else if (t.is(','))
1234 dash = false;
1235 else {
1236 lerror("syntax error: expected %<,%>");
1237 unlex(t);
1238 }
1239 }
1240 }
1241
1242
1243 struct Lexer::ElementState {
1244 String name;
1245 int type;
1246 int decl_type;
1247 bool bare;
1248 String configuration;
1249 String filename;
1250 unsigned lineno;
1251 ElementState *next;
1252
ElementStateLexer::ElementState1253 ElementState(const String &name_, int type_, bool bare_,
1254 const String &filename_, unsigned lineno_,
1255 ParseState *ps)
1256 : name(name_), type(type_), decl_type(-1), bare(bare_),
1257 filename(filename_), lineno(lineno_), next(0) {
1258 (ps->_tail ? ps->_tail->next : ps->_head) = this;
1259 ps->_tail = this;
1260 }
1261 };
1262
1263
1264 // Configuration parsing, formerly recursive descent, has changed to a
1265 // hand-built state machine. (Linux kernel threads have very small stacks; the
1266 // recursive descent could overflow those stacks.)
1267 //
1268 // The current state of the machine is stored in Lexer::_ps, a pointer to a
1269 // ParseState object. There's a stack of ParseStates, linked by
1270 // ParseState::_parent. The current parse state is _ps->state. The current
1271 // type of parse is _ps->_type, which can be either ParseState::t_file,
1272 // ParseState::t_group, or ParseState::t_compound.
1273 //
1274 // A basic connection is parsed by the following functions:
1275 //
1276 // ... [port] element :: Class (config) [port]
1277 // ^^^^^^^^^^^^^^ ^^^^^^^^ ^^^^^^^^^^^^^^^ ^^
1278 // yelement_name() yelement_type() yelement_config() yelement_next()
1279 // s_element s_element_next
1280 //
1281 // The s_element state parses an element declaration or reference. But
1282 // "element" can be a compound element or group, and "Class" can be a compound
1283 // element. These require recursive parsing. So yelement_name() can call
1284 // ycompound() or ygroup(), which push a new ParseState on the stack; when
1285 // done, the parser will call yelement_type() with the result. Similarly,
1286 // yelement_type() can call ycompound(), which, when complete, will call
1287 // yelement_config().
1288 //
1289 // The yelement_next() function parses either another element reference
1290 // (indicated by a comma), or a connection (indicated by an arrow -- state
1291 // s_connector). It can also stop parsing the current connection.
1292 //
1293 // Groups are pretty simple; ygroup() starts a group, ygroup_end() finishes
1294 // it. Compounds are less simple. ycompound() starts a compound.
1295 // ycompound_next() parses a new compound, by creating a new ParseState and
1296 // Compound. ycompound_end() might parse an overriding compound or pop the
1297 // current compound off the stack.
1298
1299 void
yelement_name()1300 Lexer::yelement_name()
1301 {
1302 assert(_ps->state == _ps->s_element);
1303 _ps->start_element();
1304
1305 // initial port
1306 yport(false);
1307
1308 // element name or class
1309 bool this_implicit = false;
1310 bool this_ident = false;
1311
1312 {
1313 Lexeme t = lex();
1314 if (t.is(lexIdent)) {
1315 _ps->_element_name = t.string();
1316 this_ident = true;
1317 } else if (t.is('{')) {
1318 _ps->_element_name = String();
1319 _ps->state = ParseState::s_compound_element;
1320 ycompound();
1321 return;
1322 } else if (t.is('(')) {
1323 _ps->_element_name = anon_element_name("");
1324 ygroup();
1325 return;
1326 } else {
1327 bool nested = _c->depth() || _ps->_parent;
1328 if (nested && (t.is(lexArrow) || t.is(lex2Arrow))) {
1329 this_implicit = _ps->first_element_set()
1330 && (_ps->nports(false) || !_ps->cur_epos);
1331 if (this_implicit && !_ps->nports(false)
1332 && !_ps->last_connection_ends_output)
1333 _errh->lwarning(_file.landmark(), "suggest %<input %s%> or %<[0] %s%> to start connection", t.string().c_str(), t.string().c_str());
1334 } else if (nested && t.is(','))
1335 this_implicit = !!_ps->nports(false);
1336 else if (nested && !t.is(lex2Colon))
1337 this_implicit = !_ps->first_element_set()
1338 && (_ps->nports(false) || !_ps->cur_epos);
1339 if (this_implicit) {
1340 _ps->_element_name = port_names[!_ps->first_element_set()];
1341 _ps->any_implicit = true;
1342 if (_ps->first_element_set()) // swap inputs and outputs
1343 click_swap(_ps->elements[_ps->cur_epos + 1], _ps->elements[_ps->cur_epos + 2]);
1344 unlex(t);
1345 } else {
1346 if (_ps->nports(false))
1347 lerror("stranded port ignored");
1348 _ps->elements.resize(_ps->cur_epos);
1349 if (_ps->cur_epos == 0) {
1350 if (nested && _ps->first_element_set())
1351 unlex(t);
1352 else
1353 lerror_syntax(t);
1354 _ps->state = _ps->s_connection_done;
1355 } else
1356 _ps->state = _ps->s_next_element;
1357 return;
1358 }
1359 }
1360 }
1361
1362 yelement_type(element_type(_ps->_element_name), this_ident, this_implicit);
1363 }
1364
1365 void
yelement_type(int type,bool this_ident,bool this_implicit)1366 Lexer::yelement_type(int type, bool this_ident, bool this_implicit)
1367 {
1368 ElementState *e = new ElementState(_ps->_element_name, type, this_ident, _file._filename, _file._lineno, _ps);
1369
1370 // ":: CLASS" declaration
1371 {
1372 Lexeme t = lex();
1373 if (t.is(lex2Colon) && !this_implicit) {
1374 e->bare = false;
1375 t = lex();
1376 if (t.is(lexIdent)) {
1377 e->decl_type = force_element_type(t.string());
1378 t = lex();
1379 } else if (t.is('{')) {
1380 _ps->_element_name = String();
1381 _ps->state = ParseState::s_compound_type;
1382 ycompound();
1383 return;
1384 } else {
1385 lerror("missing element type in declaration");
1386 e->decl_type = force_element_type(e->name);
1387 }
1388 }
1389 unlex(t);
1390 }
1391
1392 yelement_config(e, this_implicit);
1393 }
1394
1395 void
yelement_config(ElementState * e,bool this_implicit)1396 Lexer::yelement_config(ElementState *e, bool this_implicit)
1397 {
1398 // configuration string
1399 Lexeme t = lex();
1400 if (t.is('(') && !this_implicit) {
1401 if (_c->_element_map[e->name] >= 0)
1402 lerror("configuration string ignored on element reference");
1403 e->configuration = lex_config();
1404 expect(')');
1405 e->bare = false;
1406 t = lex();
1407 }
1408
1409 // final port
1410 unlex(t);
1411 if (t.is('[') && !this_implicit) {
1412 _ps->clear_ports(true); // delete any implied ports
1413 yport(true);
1414 }
1415
1416 if (_ps->nports(false) || _ps->nports(true))
1417 _ps->any_ports = true;
1418 _ps->state = ParseState::s_next_element;
1419 }
1420
1421 void
yelement_next()1422 Lexer::yelement_next()
1423 {
1424 assert(_ps->state == _ps->s_next_element);
1425
1426 // parse lists of names (which might include classes)
1427 Lexeme t = lex();
1428 if (t.is(',')) {
1429 _ps->state = _ps->s_element;
1430 return;
1431 }
1432 unlex(t);
1433
1434 // maybe complain about implicits
1435 if (_ps->any_implicit && !_ps->first_element_set() && (t.is(lexArrow) || t.is(lex2Arrow)))
1436 lerror("implicit ports used in the middle of a chain");
1437
1438 // maybe spread class and configuration for standalone
1439 // multiple-element declaration
1440 if (_ps->_head->next && _ps->first_element_set()
1441 && !(t.is(lexArrow) || t.is(lex2Arrow))
1442 && !_ps->any_ports && !_ps->any_implicit) {
1443 ElementState *last = _ps->_head;
1444 while (last->next && last->bare)
1445 last = last->next;
1446 if (!last->next && last->decl_type)
1447 for (ElementState *e = _ps->_head; e->next; e = e->next) {
1448 e->decl_type = last->decl_type;
1449 e->configuration = last->configuration;
1450 }
1451 }
1452
1453 // add elements
1454 int *resp = _ps->elements.begin();
1455 while (ElementState *e = _ps->_head) {
1456 if (e->type >= 0 || (*resp = _c->_element_map[e->name]) < 0) {
1457 if (e->decl_type >= 0 && e->type >= 0)
1458 _errh->lerror(Compound::landmark_string(e->filename, e->lineno), "class %<%s%> used as element name", e->name.c_str());
1459 else if (e->decl_type < 0 && e->type < 0) {
1460 _errh->lerror(Compound::landmark_string(e->filename, e->lineno), "undeclared element %<%s%>", e->name.c_str());
1461 e->type = force_element_type(e->name, false);
1462 }
1463 if (e->type >= 0)
1464 e->name = anon_element_name(e->name);
1465 *resp = get_element(e->name, e->type >= 0 ? e->type : e->decl_type, e->configuration, e->filename, e->lineno);
1466 } else if (e->decl_type >= 0) {
1467 _errh->lerror(Compound::landmark_string(e->filename, e->lineno), "redeclaration of element %<%s%>", e->name.c_str());
1468 if (_c->_elements[*resp] != TUNNEL_TYPE)
1469 _errh->lerror(_c->element_landmark(*resp), "element %<%s%> previously declared here", e->name.c_str());
1470 }
1471
1472 resp += 3 + resp[1] + resp[2];
1473 _ps->_head = e->next;
1474 delete e;
1475 }
1476
1477 _ps->state = ParseState::s_connector;
1478 }
1479
1480 void
yconnection_check_useless(const Vector<int> & x,bool isoutput)1481 Lexer::yconnection_check_useless(const Vector<int> &x, bool isoutput)
1482 {
1483 for (const int *it = x.begin(); it != x.end(); it += 3 + it[1] + it[2])
1484 if (it[isoutput ? 2 : 1] > 0) {
1485 lerror(isoutput ? "output ports ignored at end of chain" : "input ports ignored at start of chain");
1486 break;
1487 }
1488 }
1489
1490 void
yconnection_analyze_ports(const Vector<int> & x,bool isoutput,int & min_ports,int & expandable)1491 Lexer::yconnection_analyze_ports(const Vector<int> &x, bool isoutput,
1492 int &min_ports, int &expandable)
1493 {
1494 min_ports = expandable = 0;
1495 for (const int *it = x.begin(); it != x.end(); it += 3 + it[1] + it[2]) {
1496 int n = it[isoutput ? 2 : 1];
1497 if (n <= 1)
1498 min_ports += 1;
1499 else if (it[3 + (isoutput ? it[1] : 0) + n - 1] == -1) {
1500 min_ports += n - 1;
1501 ++expandable;
1502 } else
1503 min_ports += n;
1504 }
1505 }
1506
1507 void
yconnection_connect_all(Vector<int> & outputs,Vector<int> & inputs,int connector)1508 Lexer::yconnection_connect_all(Vector<int> &outputs, Vector<int> &inputs,
1509 int connector)
1510 {
1511 int minp[2];
1512 int expandable[2];
1513 yconnection_analyze_ports(outputs, true, minp[1], expandable[1]);
1514 yconnection_analyze_ports(inputs, false, minp[0], expandable[0]);
1515
1516 if (expandable[0] + expandable[1] > 1) {
1517 lerror("at most one expandable port allowed per connection");
1518 expandable[minp[0] < minp[1]] = 0;
1519 }
1520
1521 if (connector == lex2Arrow)
1522 // '=>' can interpret missing ports as expandable ports
1523 for (int k = 0; k < 2; ++k) {
1524 Vector<int> &myvec(k ? outputs : inputs);
1525 if (minp[k] == 1 && minp[1-k] > 1 && myvec[1+k] == 0)
1526 expandable[k] = 1;
1527 }
1528
1529 bool step[2];
1530 int nexpandable[2];
1531 for (int k = 0; k < 2; ++k) {
1532 step[k] = minp[k] > 1 || expandable[k];
1533 nexpandable[k] = expandable[k] ? minp[1-k] - minp[k] : 0;
1534 }
1535
1536 if (step[0] && step[1]) {
1537 if (connector != lex2Arrow)
1538 lerror("syntax error: many-to-many connections require %<=>%>");
1539 if (!expandable[0] && !expandable[1] && minp[0] != minp[1])
1540 lerror("connection mismatch: %d outputs connected to %d inputs", minp[1], minp[0]);
1541 else if (!expandable[0] && minp[0] < minp[1])
1542 lerror("connection mismatch: %d or more outputs connected to %d inputs", minp[1], minp[0]);
1543 else if (!expandable[1] && minp[1] < minp[0])
1544 lerror("connection mismatch: %d outputs connected to %d or more inputs", minp[1], minp[0]);
1545 } else if (!step[0] && !step[1])
1546 step[0] = true;
1547
1548 const int *it[2] = {inputs.begin(), outputs.begin()};
1549 int ppos[2] = {0, 0}, port[2] = {-1, -1};
1550 while (it[0] != inputs.end() && it[1] != outputs.end()) {
1551 for (int k = 0; k < 2; ++k)
1552 if (port[k] < 0) {
1553 int np = it[k][1+k];
1554 port[k] = np ? it[k][3 + (k ? it[k][1] : 0)] : 0;
1555 }
1556
1557 _c->connect(it[1][0], port[1], it[0][0], port[0]);
1558
1559 for (int k = 0; k < 2; ++k)
1560 if (step[k]) {
1561 int np = it[k][1+k];
1562 const int *pvec = it[k] + 3 + (k ? it[k][1] : 0);
1563 ++ppos[k];
1564 if (ppos[k] < np && pvec[ppos[k]] >= 0)
1565 // port list
1566 port[k] = pvec[ppos[k]];
1567 else if (np && pvec[np-1] == -1 && nexpandable[k] > 0) {
1568 // expandable port
1569 port[k] = pvec[np-2] + ppos[k] - (np-2);
1570 --nexpandable[k];
1571 } else if (np == 0 && minp[k] == 1 && nexpandable[k] > 0) {
1572 // missing port interpreted as expandable port
1573 port[k] = ppos[k];
1574 --nexpandable[k];
1575 } else {
1576 // next element in comma-separated list
1577 port[k] = -1;
1578 ppos[k] = 0;
1579 it[k] += 3 + it[k][1] + it[k][2];
1580 }
1581 }
1582 }
1583 }
1584
1585 void
yconnection_connector()1586 Lexer::yconnection_connector()
1587 {
1588 assert(_ps->state == _ps->s_connector);
1589 if (_ps->first_element_set())
1590 yconnection_check_useless(_ps->elements, false);
1591 else
1592 yconnection_connect_all(_ps->last_elements, _ps->elements, _ps->connector);
1593 _ps->last_elements.swap(_ps->elements);
1594
1595 Lexeme t;
1596 relex:
1597 t = lex();
1598 switch (t.kind()) {
1599
1600 case ',':
1601 case lex2Colon:
1602 lerror_syntax(t);
1603 goto relex;
1604
1605 case lexArrow:
1606 case lex2Arrow:
1607 // have 'x ->'
1608 _ps->connector = t.kind();
1609 _ps->state = ParseState::s_first_element;
1610 break;
1611
1612 case lexIdent:
1613 case '{':
1614 case '}':
1615 case '[':
1616 case ')':
1617 case lex2Bar:
1618 case lexElementclass:
1619 case lexRequire:
1620 case lexProvide:
1621 case lexDefine:
1622 unlex(t);
1623 // FALLTHRU
1624 case ';':
1625 case lexEOF:
1626 _ps->state = ParseState::s_connection_done;
1627 break;
1628
1629 default:
1630 lerror_syntax(t);
1631 if (t.kind() >= lexIdent) // save meaningful tokens
1632 unlex(t);
1633 _ps->state = ParseState::s_connection_done;
1634 break;
1635
1636 }
1637 }
1638
1639 void
yelementclass()1640 Lexer::yelementclass()
1641 {
1642 Lexeme tname = lex();
1643 String name;
1644 if (tname.is(lexIdent))
1645 name = tname.string();
1646 else {
1647 unlex(tname);
1648 lerror("expected element type name");
1649 }
1650
1651 Lexeme tnext = lex();
1652 if (tnext.is('{')) {
1653 _ps->_element_name = name;
1654 _ps->state = ParseState::s_compound_elementclass;
1655 ycompound();
1656
1657 } else if (tnext.is(lexIdent)) {
1658 // define synonym type
1659 int t = force_element_type(tnext.string());
1660 ADD_ELEMENT_TYPE(name, _element_types[t].factory, _element_types[t].thunk, true);
1661
1662 } else {
1663 lerror_syntax(tnext);
1664 ADD_ELEMENT_TYPE(name, error_element_factory, 0, true);
1665 }
1666 }
1667
1668 void
ycompound_arguments(Compound * comptype)1669 Lexer::ycompound_arguments(Compound *comptype)
1670 {
1671 Lexeme t1, t2;
1672
1673 while (1) {
1674 String vartype, varname;
1675
1676 // read "IDENTIFIER $VARIABLE" or "$VARIABLE"
1677 t1 = lex();
1678 if (t1.is(lexIdent)) {
1679 t2 = lex();
1680 if (t2.is(lexVariable)) {
1681 vartype = t1.string();
1682 varname = t2.string();
1683 } else {
1684 if (comptype->scope().size() > 0)
1685 lerror("expected variable");
1686 unlex(t2);
1687 unlex(t1);
1688 break;
1689 }
1690 } else if (t1.is(lexVariable))
1691 varname = t1.string();
1692 else if (t1.is('|'))
1693 break;
1694 else {
1695 if (comptype->nformals() > 0)
1696 lerror("expected variable");
1697 unlex(t1);
1698 break;
1699 }
1700
1701 comptype->define(varname, vartype, true, this);
1702
1703 Lexeme tsep = lex();
1704 if (tsep.is('|'))
1705 break;
1706 else if (!tsep.is(',')) {
1707 lerror("expected %<,%> or %<|%>");
1708 unlex(tsep);
1709 break;
1710 }
1711 }
1712 }
1713
1714 void
ycompound()1715 Lexer::ycompound()
1716 {
1717 _ps->_saved_type_map = _element_type_map;
1718 _ps->_saved_compound = _c;
1719 _ps->_compound_first = _ps->_compound_last = 0;
1720 _ps->_compound_extension = -1;
1721
1722 ycompound_next();
1723 }
1724
1725 void
ycompound_next()1726 Lexer::ycompound_next()
1727 {
1728 Lexeme t = lex();
1729 if (t.is(lex3Dot)) {
1730 // '...' marks an extension type
1731 String name = _ps->_element_name;
1732 if (element_type(name) < 0) {
1733 lerror("cannot extend unknown element class %<%s%>", name.c_str());
1734 ADD_ELEMENT_TYPE(name, error_element_factory, 0, true);
1735 }
1736 _ps->_compound_extension = element_type(name);
1737
1738 t = lex();
1739 if (!_ps->_compound_first || !t.is('}'))
1740 lerror("%<...%> should occur last, after one or more compounds");
1741 unlex(t);
1742
1743 } else {
1744 // create a compound
1745 _c = new Compound(_ps->_element_name, _file.landmark(), &_ps->_saved_compound->_scope);
1746 _ps = new ParseState(ParseState::t_compound, _ps);
1747 get_element("input", TUNNEL_TYPE);
1748 get_element("output", TUNNEL_TYPE);
1749 _c->_anonymous_offset = 2;
1750
1751 unlex(t);
1752 ycompound_arguments(_c);
1753 _ps->state = ParseState::s_statement;
1754
1755 if (_ps->_depth >= max_depth) {
1756 lerror("maximum compound element nesting depth exceeded");
1757 ycompound_end(Lexeme());
1758 }
1759 }
1760 }
1761
1762 void
ycompound_end(const Lexeme & t)1763 Lexer::ycompound_end(const Lexeme &t)
1764 {
1765 ParseState *new_ps = _ps;
1766 Compound *new_c = _c;
1767
1768 _ps = _ps->_parent;
1769 _element_type_map = _ps->_saved_type_map;
1770 _c = _ps->_saved_compound;
1771
1772 new_c->finish(_errh);
1773 delete new_ps;
1774
1775 if (_ps->_compound_last) {
1776 int type = ADD_ELEMENT_TYPE(_ps->_element_name, compound_element_factory, (uintptr_t) new_c, true);
1777 _ps->_compound_last->set_overload_type(type);
1778 } else
1779 _ps->_compound_first = new_c;
1780 _ps->_compound_last = new_c;
1781
1782 // check for overloads to come
1783 if (t.is(lex2Bar))
1784 return;
1785
1786 // otherwise, end of compound
1787 _ps->_compound_last->set_overload_type(_ps->_compound_extension);
1788 int type = ADD_ELEMENT_TYPE(_ps->_element_name, compound_element_factory, (uintptr_t) _ps->_compound_first, true);
1789
1790 if (_ps->state == ParseState::s_compound_element) {
1791 _ps->_element_name = _element_types[type].name;
1792 yelement_type(type, false, false);
1793 } else if (_ps->state == ParseState::s_compound_type) {
1794 ElementState *e = _ps->_tail;
1795 e->decl_type = type;
1796 yelement_config(e, false);
1797 } else {
1798 assert(_ps->state == ParseState::s_compound_elementclass);
1799 _ps->state = ParseState::s_statement;
1800 }
1801 }
1802
1803 void
ygroup()1804 Lexer::ygroup()
1805 {
1806 int eidexes[3];
1807 add_tunnels(_ps->_element_name, eidexes);
1808
1809 _ps->elements.push_back(_c->_element_map["input"]);
1810 _ps->elements.push_back(_c->_element_map["output"]);
1811 _c->_element_map["input"] = eidexes[1];
1812 _c->_element_map["output"] = eidexes[2];
1813 _ps = new ParseState(ParseState::t_group, _ps);
1814
1815 if (_ps->_depth >= max_depth) {
1816 lerror("maximum element group nesting depth exceeded");
1817 ygroup_end();
1818 }
1819 }
1820
1821 void
ygroup_end()1822 Lexer::ygroup_end()
1823 {
1824 ParseState *new_ps = _ps;
1825 _ps = _ps->_parent;
1826 delete new_ps;
1827
1828 // count inputs & outputs, check that all inputs and outputs are used
1829 LandmarkErrorHandler lerrh(_errh, _file.landmark());
1830 const char *printable_name = (_ps->_element_name[0] == ';' ? "<anonymous group>" : _ps->_element_name.c_str());
1831 int group_nports[2];
1832 group_nports[0] = _c->check_pseudoelement(_c->_element_map["input"], false, printable_name, &lerrh);
1833 group_nports[1] = _c->check_pseudoelement(_c->_element_map["output"], true, printable_name, &lerrh);
1834
1835 _c->_element_map["input"] = _ps->elements[_ps->elements.size() - 2];
1836 _c->_element_map["output"] = _ps->elements[_ps->elements.size() - 1];
1837 _ps->elements.resize(_ps->elements.size() - 2);
1838
1839 // an anonymous group has implied, overridable port
1840 // specifications on both sides for all inputs & outputs
1841 for (int k = 0; k < 2; ++k)
1842 if (_ps->elements[_ps->cur_epos + 1 + k] == 0) {
1843 _ps->elements[_ps->cur_epos + 1 + k] = group_nports[k];
1844 for (int i = 0; i < group_nports[k]; ++i)
1845 _ps->elements.push_back(i);
1846 }
1847
1848 yelement_type(-1, false, false);
1849 }
1850
1851 void
yrequire_library(const String & value)1852 Lexer::yrequire_library(const String &value)
1853 {
1854 #if CLICK_USERLEVEL
1855 assert(!_unlex_pos);
1856 if (_c->depth()) {
1857 lerror("%<require library%> must be used at file scope");
1858 return;
1859 }
1860
1861 String dir = _file._filename;
1862 int pos = dir.find_right('/');
1863 if (pos > 0)
1864 dir = dir.substring(0, pos);
1865 else
1866 dir = ".";
1867 String fn = clickpath_find_file(value, "conf", dir, 0);
1868 if (!fn) {
1869 lerror("library %<%#s%> not found in CLICKPATH/conf", value.c_str());
1870 return;
1871 }
1872
1873 for (String *it = _libraries.begin(); it != _libraries.end(); ++it)
1874 if (*it == fn)
1875 return;
1876 _libraries.push_back(fn);
1877
1878 LandmarkErrorHandler lerrh(_errh, _file.landmark());
1879 int before = lerrh.nerrors();
1880 String data = file_string(fn, &lerrh);
1881 if (lerrh.nerrors() != before)
1882 return;
1883
1884 FileState old_file(_file);
1885 _file = FileState(data, fn);
1886 ParseState *old_ps = _ps;
1887 _ps = new ParseState(ParseState::t_file, 0);
1888
1889 while (!ydone())
1890 ystep();
1891
1892 _file = old_file;
1893 _ps = old_ps;
1894 #else
1895 (void) value;
1896 lerror("%<require library%> may not be used in this driver");
1897 #endif
1898 }
1899
1900 void
yrequire()1901 Lexer::yrequire()
1902 {
1903 if (!expect('('))
1904 return;
1905
1906 String requirement = lex_config();
1907 expect(')');
1908 // pre-read ';' to make it easier to write parsing extensions
1909 expect(';', true);
1910
1911 Vector<String> args;
1912 cp_argvec(requirement, args);
1913
1914 String compact_config_str = String::make_stable("compact_config", 14);
1915 String package_str = String::make_stable("package", 7);
1916 String library_str = String::make_stable("library", 7);
1917
1918 for (int i = 0; i < args.size(); i++) {
1919 Vector<String> words;
1920 cp_spacevec(args[i], words);
1921 if (words.size() == 0)
1922 continue; // do nothing
1923
1924 String type, value;
1925 (void) WordArg::parse(words[0], type);
1926 // "require(UNKNOWN)" means "require(package UNKNOWN)"
1927 if (type && type != compact_config_str && type != package_str
1928 && type != library_str && words.size() == 1) {
1929 words.push_back(type);
1930 type = package_str;
1931 }
1932
1933 if (type == compact_config_str && words.size() == 1) {
1934 _compact_config = true;
1935 type = compact_config_str;
1936 } else if (type == package_str && words.size() == 2
1937 && StringArg::parse(words[1], value))
1938 /* OK */;
1939 else if (type == library_str && words.size() == 2
1940 && StringArg::parse(words[1], value)) {
1941 yrequire_library(value);
1942 continue;
1943 } else {
1944 lerror("syntax error at requirement");
1945 continue;
1946 }
1947
1948 if (_lextra)
1949 _lextra->require(type, value, _errh);
1950 _requirements.push_back(type);
1951 _requirements.push_back(value);
1952 }
1953 }
1954
1955 void
yvar()1956 Lexer::yvar()
1957 {
1958 if (expect('(')) {
1959 String requirement = lex_config();
1960 expect(')');
1961
1962 Vector<String> args;
1963 String word;
1964 cp_argvec(requirement, args);
1965 for (int i = 0; i < args.size(); i++)
1966 if (args[i]) {
1967 String var = cp_shift_spacevec(args[i]);
1968 const char *s = var.begin();
1969 if (s != var.end() && *s == '$')
1970 for (s++; s != var.end() && (isalnum((unsigned char) *s) || *s == '_'); s++)
1971 /* nada */;
1972 if (var.length() < 2 || s != var.end())
1973 lerror("bad %<define%> declaration: not a variable");
1974 else {
1975 var = var.substring(1);
1976 _c->define(var, args[i], false, this);
1977 }
1978 }
1979 }
1980 }
1981
1982 void
ystatement()1983 Lexer::ystatement()
1984 {
1985 Lexeme t = lex();
1986 switch (t.kind()) {
1987
1988 case lexIdent:
1989 case '[':
1990 case '{':
1991 case '(':
1992 case lexArrow:
1993 case lex2Arrow:
1994 unlex(t);
1995 _ps->state = _ps->s_first_element;
1996 break;
1997
1998 case lexElementclass:
1999 yelementclass();
2000 break;
2001
2002 case lexRequire:
2003 yrequire();
2004 break;
2005
2006 case lexDefine:
2007 yvar();
2008 break;
2009
2010 case ';':
2011 break;
2012
2013 case '}':
2014 case lex2Bar:
2015 if (_ps->_type == ParseState::t_compound)
2016 ycompound_end(t);
2017 else {
2018 lerror_syntax(t);
2019 if (_ps->_type == ParseState::t_group) {
2020 unlex(t);
2021 ygroup_end();
2022 }
2023 }
2024 break;
2025
2026 case ')':
2027 if (_ps->_type == ParseState::t_group)
2028 ygroup_end();
2029 else
2030 goto syntax_error;
2031 break;
2032
2033 case lexEOF:
2034 if (_ps->_type == ParseState::t_group) {
2035 lerror("expected %<)%>");
2036 ygroup_end();
2037 } else if (_ps->_type == ParseState::t_compound) {
2038 lerror("expected %<}%>");
2039 ycompound_end(t);
2040 } else {
2041 assert(_ps->_type == ParseState::t_file && !_ps->_parent);
2042 delete _ps;
2043 _ps = 0;
2044 }
2045 break;
2046
2047 default:
2048 syntax_error:
2049 lerror_syntax(t);
2050 break;
2051 }
2052 }
2053
2054 void
ystep()2055 Lexer::ystep()
2056 {
2057 switch (_ps->state) {
2058 case ParseState::s_statement:
2059 ystatement();
2060 break;
2061
2062 case ParseState::s_first_element:
2063 _ps->enter_element_state();
2064 break;
2065
2066 case ParseState::s_element:
2067 yelement_name();
2068 break;
2069
2070 case ParseState::s_next_element:
2071 yelement_next();
2072 break;
2073
2074 case ParseState::s_connector:
2075 yconnection_connector();
2076 break;
2077
2078 case ParseState::s_connection_done:
2079 yconnection_check_useless(_ps->last_elements, true);
2080 // last_... becomes true only if we saw exactly one element at
2081 // the end of the chain, and it was "output".
2082 _ps->last_connection_ends_output = _ps->last_elements.size() > 0
2083 && _ps->last_elements.size() == 3 + _ps->last_elements[1] + _ps->last_elements[2]
2084 && _ps->last_elements[0] == _c->_element_map["output"];
2085 _ps->last_elements.clear();
2086 _ps->state = ParseState::s_statement;
2087 break;
2088
2089 case ParseState::s_compound_element:
2090 case ParseState::s_compound_type:
2091 case ParseState::s_compound_elementclass:
2092 ycompound_next();
2093 break;
2094 }
2095 }
2096
2097
2098 // COMPLETION
2099
2100 void
add_router_connections(int c,const Vector<int> & router_id)2101 Lexer::add_router_connections(int c, const Vector<int> &router_id)
2102 {
2103 Vector<Port> hfrom;
2104 expand_connection(_c->_conn[c][1], true, hfrom);
2105 Vector<Port> hto;
2106 expand_connection(_c->_conn[c][0], false, hto);
2107 for (int f = 0; f < hfrom.size(); f++) {
2108 int eidx = router_id[hfrom[f].idx];
2109 if (eidx >= 0)
2110 for (int t = 0; t < hto.size(); t++) {
2111 int tidx = router_id[hto[t].idx];
2112 if (tidx >= 0)
2113 _c->connect(hfrom[f].idx, hfrom[f].port, hto[t].idx, hto[t].port);
2114 }
2115 }
2116 }
2117
2118 void
expand_compound_element(int which,VariableEnvironment & ve)2119 Lexer::expand_compound_element(int which, VariableEnvironment &ve)
2120 {
2121 String name = _c->_element_names[which];
2122 int etype = _c->_elements[which];
2123 assert(name);
2124
2125 // deanonymize element name if necessary
2126 if (name[0] == ';')
2127 name = _c->deanonymize_element_name(which);
2128
2129 // avoid TUNNEL_TYPE
2130 if (etype == TUNNEL_TYPE)
2131 return;
2132
2133 // expand config string
2134 _c->_element_configurations[which] = cp_expand(_c->_element_configurations[which], ve);
2135
2136 // exit if not compound
2137 if (_element_types[etype].factory != compound_element_factory)
2138 return;
2139 Compound *c = (Compound *) _element_types[etype].thunk;
2140
2141 // find right version
2142 Vector<String> args;
2143 cp_argvec(_c->_element_configurations[which], args);
2144 int inputs_used = _c->_element_nports[0][which];
2145 int outputs_used = _c->_element_nports[1][which];
2146
2147 int found_type = c->resolve(this, etype, inputs_used, outputs_used, args, _errh, _file.landmark());
2148
2149 // check for error or non-compound, or expand compound
2150 if (found_type < 0)
2151 _c->_elements[which] = ERROR_TYPE;
2152 else if (_element_types[found_type].factory != compound_element_factory)
2153 _c->_elements[which] = found_type;
2154 else {
2155 Compound *found_comp = (Compound *) _element_types[found_type].thunk;
2156
2157 VariableEnvironment new_ve(ve.parent_of(found_comp->depth()));
2158 for (int i = 0; i < found_comp->nformals(); i++)
2159 new_ve.define(found_comp->scope().name(i), args[i], true);
2160 for (int i = found_comp->nformals(); i < found_comp->scope().size(); i++)
2161 new_ve.define(found_comp->scope().name(i), cp_expand(found_comp->scope().value(i), new_ve), true);
2162
2163 found_comp->expand_into(this, which, new_ve);
2164 }
2165 }
2166
2167 Router *
create_router(Master * master)2168 Lexer::create_router(Master *master)
2169 {
2170 Router *router = new Router(_file._big_string, master);
2171 if (!router)
2172 return 0;
2173
2174 // expand compounds
2175 for (int i = 0; i < _global_scope.size(); i++)
2176 _c->scope().define(_global_scope.name(i), _global_scope.value(i), true);
2177 int initial_elements_size = _c->_elements.size();
2178 for (int i = 0; i < initial_elements_size; i++)
2179 expand_compound_element(i, _c->scope());
2180
2181 // add elements to router
2182 Vector<int> router_id;
2183 for (int i = 0; i < _c->_elements.size(); i++) {
2184 int etype = _c->_elements[i];
2185 if (etype == TUNNEL_TYPE)
2186 router_id.push_back(-1);
2187 #if CLICK_LINUXMODULE
2188 else if (_element_types[etype].module && router->add_module_ref(_element_types[etype].module) < 0) {
2189 _errh->lerror(_c->element_landmark(i), "module for element type %<%s%> unloaded", _element_types[etype].name.c_str());
2190 router_id.push_back(-1);
2191 }
2192 #endif
2193 else if (Element *e = (*_element_types[etype].factory)(_element_types[etype].thunk)) {
2194 int ei = router->add_element(e, _c->_element_names[i], _c->_element_configurations[i], _c->_element_filenames[i], _c->_element_linenos[i]);
2195 router_id.push_back(ei);
2196 } else {
2197 _errh->lerror(_c->element_landmark(i), "failed to create element %<%s%>", _c->_element_names[i].c_str());
2198 router_id.push_back(-1);
2199 }
2200 }
2201
2202 // first-level connection expansion
2203 if (_tunnels.size()) {
2204 for (const Connection *cp = _c->_conn.begin(); cp != _c->_conn.end(); ++cp)
2205 for (int isoutput = 0; isoutput < 2; ++isoutput)
2206 if (router_id[(*cp)[isoutput].idx] < 0)
2207 if (TunnelEnd *te = find_tunnel((*cp)[isoutput], isoutput, false))
2208 te->other()->_correspond.push_back((*cp)[!isoutput]);
2209 }
2210
2211 // expand connections to router
2212 int pre_expanded_nc = _c->_conn.size();
2213 for (int i = 0; i < pre_expanded_nc; i++) {
2214 int fromi = router_id[ _c->_conn[i][1].idx ];
2215 int toi = router_id[ _c->_conn[i][0].idx ];
2216 if (fromi < 0 || toi < 0)
2217 add_router_connections(i, router_id);
2218 }
2219
2220 // use router element numbers
2221 for (Connection *cp = _c->_conn.begin(); cp != _c->_conn.end(); ++cp) {
2222 (*cp)[0].idx = router_id[(*cp)[0].idx];
2223 (*cp)[1].idx = router_id[(*cp)[1].idx];
2224 }
2225
2226 // sort and add connections to router
2227 click_qsort(_c->_conn.begin(), _c->_conn.size());
2228 for (Connection *cp = _c->_conn.begin(); cp != _c->_conn.end(); ++cp)
2229 if ((*cp)[0].idx >= 0 && (*cp)[1].idx >= 0)
2230 router->add_connection((*cp)[1].idx, (*cp)[1].port, (*cp)[0].idx, (*cp)[0].port);
2231
2232 // add requirements to router
2233 for (int i = 0; i < _requirements.size(); i += 2)
2234 router->add_requirement(_requirements[i], _requirements[i+1]);
2235
2236 return router;
2237 }
2238
2239
2240 //
2241 // LEXEREXTRA
2242 //
2243
2244 void
require(String,String,ErrorHandler *)2245 LexerExtra::require(String, String, ErrorHandler *)
2246 {
2247 }
2248
2249
2250 //
2251 // LEXER::TUNNELEND RELATED STUFF
2252 //
2253
2254 Lexer::TunnelEnd *
find_tunnel(const Port & h,bool isoutput,bool insert)2255 Lexer::find_tunnel(const Port &h, bool isoutput, bool insert)
2256 {
2257 // binary search for tunnel
2258 unsigned l = 0, r = _tunnels.size();
2259 while (l < r) {
2260 unsigned m = l + (r - l) / 2;
2261 if (h.idx < _tunnels[m]->_port.idx)
2262 r = m;
2263 else if (h.idx > _tunnels[m]->_port.idx)
2264 l = m + 1;
2265 else {
2266 l = m;
2267 r = m + 1;
2268 break;
2269 }
2270 }
2271
2272 // insert space if necessary
2273 if (l >= r && insert) {
2274 _tunnels.insert(_tunnels.begin() + l, 0);
2275 ++r;
2276 } else if (l >= r)
2277 return 0;
2278
2279 // find match
2280 TunnelEnd *match = 0;
2281 for (TunnelEnd *te = _tunnels[l]; te; te = te->next())
2282 if (te->isoutput() == isoutput && te->port().port == h.port)
2283 return te;
2284 else if (te->isoutput() == isoutput && te->port().port == 0)
2285 match = te;
2286
2287 // add new end if necessary
2288 if (match && !insert) {
2289 TunnelEnd *te = new TunnelEnd(h, isoutput, _tunnels[l]);
2290 _tunnels[l] = te;
2291 TunnelEnd *ote = find_tunnel(Port(match->other()->port().idx, h.port), !isoutput, true);
2292 te->pair_with(ote);
2293 return te;
2294 } else if (insert) {
2295 TunnelEnd *te = new TunnelEnd(h, isoutput, _tunnels[l]);
2296 _tunnels[l] = te;
2297 return te;
2298 } else
2299 return 0;
2300 }
2301
2302 void
expand(Lexer * lexer,Vector<Router::Port> & into)2303 Lexer::TunnelEnd::expand(Lexer *lexer, Vector<Router::Port> &into)
2304 {
2305 if (_expanded == 1)
2306 return;
2307
2308 if (_expanded == 0) {
2309 _expanded = 1;
2310
2311 // _correspond contains the first cut at corresponding ports
2312 Vector<Router::Port> connections;
2313 connections.swap(_correspond);
2314
2315 // give good errors for unused or nonexistent compound element ports
2316 if (!connections.size()) {
2317 Port inh = (_isoutput ? _other->_port : _port);
2318 Port outh = (_isoutput ? _port : _other->_port);
2319 String in_name = lexer->element_name(inh.idx);
2320 String out_name = lexer->element_name(outh.idx);
2321 if (in_name + "/input" == out_name) {
2322 const char *message = (_isoutput ? "%<%s%> input %d unused"
2323 : "%<%s%> has no input %d");
2324 lexer->errh()->lerror(lexer->element_landmark(inh.idx), message,
2325 in_name.c_str(), inh.port);
2326 } else if (in_name == out_name + "/output") {
2327 const char *message = (_isoutput ? "%<%s%> has no output %d"
2328 : "%<%s%> output %d unused");
2329 lexer->errh()->lerror(lexer->element_landmark(outh.idx), message,
2330 out_name.c_str(), outh.port);
2331 } else {
2332 lexer->errh()->lerror(lexer->element_landmark(_other->_port.idx),
2333 "tunnel %<%s -> %s%> %s %d unused",
2334 in_name.c_str(), out_name.c_str(),
2335 port_names[_isoutput], _port.idx);
2336 }
2337 }
2338
2339 for (int i = 0; i < connections.size(); i++)
2340 lexer->expand_connection(connections[i], _isoutput, _correspond);
2341
2342 _expanded = 2;
2343 }
2344
2345 for (int i = 0; i < _correspond.size(); i++)
2346 into.push_back(_correspond[i]);
2347 }
2348
2349 void
expand_connection(const Port & this_end,bool is_out,Vector<Port> & into)2350 Lexer::expand_connection(const Port &this_end, bool is_out, Vector<Port> &into)
2351 {
2352 if (_c->_elements[this_end.idx] != TUNNEL_TYPE)
2353 into.push_back(this_end);
2354 else if (TunnelEnd *dp = find_tunnel(this_end, is_out, false))
2355 dp->expand(this, into);
2356 else if (find_tunnel(this_end, !is_out, false))
2357 _errh->lerror(_c->element_landmark(this_end.idx), "%<%s%> used as %s",
2358 element_name(this_end.idx).c_str(), port_names[is_out]);
2359 }
2360
2361 CLICK_ENDDECLS
2362