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