1 // -*- related-file-name: "../include/click/args.hh" -*-
2 /*
3  * args.{cc,hh} -- type-safe argument & configuration string parsing
4  * Eddie Kohler
5  *
6  * Copyright (c) 2011 Regents of the University of California
7  * Copyright (c) 2012-2013 Eddie Kohler
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining a
10  * copy of this software and associated documentation files (the "Software"),
11  * to deal in the Software without restriction, subject to the conditions
12  * listed in the Click LICENSE file. These conditions include: you must
13  * preserve this copyright notice, and you cannot mention the copyright
14  * holders in advertising related to the Software without their permission.
15  * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
16  * notice is a summary of the Click LICENSE file; the license in that file is
17  * legally binding.
18  */
19 
20 #include <click/config.h>
21 #include <click/glue.hh>
22 #include <click/args.hh>
23 #include <click/error.hh>
24 #include <click/bigint.hh>
25 #if !CLICK_TOOL
26 # include <click/router.hh>
27 # include <click/nameinfo.hh>
28 # include <click/packet_anno.hh>
29 #endif
30 #if CLICK_USERLEVEL || CLICK_TOOL
31 # include <pwd.h>
32 #endif
33 #include <stdarg.h>
34 CLICK_DECLS
35 
36 const ArgContext blank_args;
37 
38 inline void
initialize(const Vector<String> * conf)39 Args::initialize(const Vector<String> *conf)
40 {
41     static_assert(has_trivial_copy<int>::value && !has_trivial_copy<String>::value, "has_trivial_copy problems");
42 
43     _conf = conf ? new Vector<String>(*conf) : 0;
44     _slots = 0;
45     _simple_slotbuf[0] = 0;
46     _my_conf = !!_conf;
47 #if CLICK_DEBUG_ARGS_USAGE
48     _consumed = false;
49 #endif
50     _status = true;
51     _simple_slotpos = 0;
52     if (_conf)
53         reset();
54 }
55 
Args(ErrorHandler * errh)56 Args::Args(ErrorHandler *errh)
57     : ArgContext(errh)
58 {
59     initialize(0);
60 }
61 
Args(const Vector<String> & conf,ErrorHandler * errh)62 Args::Args(const Vector<String> &conf, ErrorHandler *errh)
63     : ArgContext(errh)
64 {
65     initialize(&conf);
66 }
67 
68 #if !CLICK_TOOL
Args(const Element * context,ErrorHandler * errh)69 Args::Args(const Element *context, ErrorHandler *errh)
70     : ArgContext(context, errh)
71 {
72     initialize(0);
73 }
74 
Args(const Vector<String> & conf,const Element * context,ErrorHandler * errh)75 Args::Args(const Vector<String> &conf,
76            const Element *context, ErrorHandler *errh)
77     : ArgContext(context, errh)
78 {
79     initialize(&conf);
80 }
81 #endif
82 
Args(const Args & x)83 Args::Args(const Args &x)
84     : ArgContext(x),
85       _my_conf(false), _simple_slotpos(0), _conf(0), _slots(0)
86 {
87 #if CLICK_DEBUG_ARGS_USAGE
88     _consumed = true;
89 #endif
90     _simple_slotbuf[0] = 0;
91     *this = x;
92 }
93 
~Args()94 Args::~Args()
95 {
96 #if CLICK_DEBUG_ARGS_USAGE
97     if (_my_conf && _consumed && errh())
98         errh()->warning("Args::consume() did nothing; did you mean Args(this, errh).bind(conf)?");
99 #endif
100     if (_my_conf)
101         delete _conf;
102     while (Slot *s = _slots) {
103         _slots = s->_next;
104         delete s;
105     }
106 }
107 
108 Args &
operator =(const Args & x)109 Args::operator=(const Args &x)
110 {
111     if (&x != this) {
112         if ((_slots || _simple_slotbuf[0] || x._slots || x._simple_slotbuf[0])
113             && _errh)
114             _errh->warning("internal warning: ignoring assignment of Args slots");
115 
116         if (_my_conf)
117             delete _conf;
118         if (x._my_conf) {
119             _conf = new Vector<String>(*x._conf);
120             _my_conf = true;
121         } else {
122             _conf = x._conf;
123             _my_conf = false;
124         }
125         _kwpos = x._kwpos;
126 #if !CLICK_TOOL
127         _context = x._context;
128 #endif
129         _errh = x._errh;
130 
131         _arg_keyword = x._arg_keyword;
132         _read_status = x._read_status;
133         _status = x._status;
134 #if CLICK_DEBUG_ARGS_USAGE
135         _consumed = x._consumed;
136 #endif
137     }
138     return *this;
139 }
140 
141 void
reset_from(int i)142 Args::reset_from(int i)
143 {
144     _kwpos.resize(i);
145     if (_conf) {
146         _kwpos.reserve(_conf->size());
147         for (String *it = _conf->begin() + i; it != _conf->end(); ++it) {
148             const char *s = it->begin(), *ends = it->end();
149             if (s != ends && (isalpha((unsigned char) *s) || *s == '_')) {
150                 do {
151                     ++s;
152                 } while (s != ends &&
153                          (isalnum((unsigned char) *s) || *s == '_'
154                           || *s == ':' || *s == '.' || *s == '?' || *s == '!'));
155             }
156             const char *t = s;
157             while (t != ends && isspace((unsigned char) *t))
158                 ++t;
159             if (s == it->begin() || s == t || t == ends)
160                 _kwpos.push_back(0);
161             else
162                 _kwpos.push_back(s - it->begin());
163         }
164 #if CLICK_DEBUG_ARGS_USAGE
165         _consumed = false;
166 #endif
167     }
168 }
169 
170 Args &
bind(Vector<String> & conf)171 Args::bind(Vector<String> &conf)
172 {
173     if (_my_conf)
174         delete _conf;
175     _conf = &conf;
176     _my_conf = false;
177 #if CLICK_DEBUG_ARGS_USAGE
178     _consumed = false;
179 #endif
180     return reset();
181 }
182 
183 Args &
push_back(const String & arg)184 Args::push_back(const String &arg)
185 {
186     if (!_conf) {
187         _conf = new Vector<String>();
188         _my_conf = true;
189     }
190     if (_conf) {
191         int old_size = _conf->size();
192         _conf->push_back(arg);
193         reset_from(old_size);
194     }
195     return *this;
196 }
197 
198 Args &
push_back_args(const String & str)199 Args::push_back_args(const String &str)
200 {
201     if (!_conf) {
202         _conf = new Vector<String>();
203         _my_conf = true;
204     }
205     if (_conf) {
206         int old_size = _conf->size();
207         cp_argvec(str, *_conf);
208         reset_from(old_size);
209     }
210     return *this;
211 }
212 
213 Args &
push_back_words(const String & str)214 Args::push_back_words(const String &str)
215 {
216     if (!_conf) {
217         _conf = new Vector<String>();
218         _my_conf = true;
219     }
220     if (_conf) {
221         int old_size = _conf->size();
222         cp_spacevec(str, *_conf);
223         reset_from(old_size);
224     }
225     return *this;
226 }
227 
228 inline int
simple_slot_size(int size)229 Args::simple_slot_size(int size)
230 {
231 #if HAVE_INDIFFERENT_ALIGNMENT
232     return 1 + size + SIZEOF_VOID_P;
233 #else
234     if (size & (size - 1))
235         // not power of 2, assume no alignment
236         size = 1 + size;
237     else
238         size = size + size;
239     if (size & (SIZEOF_VOID_P - 1))
240         size += SIZEOF_VOID_P - (size & (SIZEOF_VOID_P - 1));
241     return size + SIZEOF_VOID_P;
242 #endif
243 }
244 
245 inline void
simple_slot_info(int offset,int size,void * & slot,void ** & pointer)246 Args::simple_slot_info(int offset, int size, void *&slot, void **&pointer)
247 {
248 #if HAVE_INDIFFERENT_ALIGNMENT
249     slot = &_simple_slotbuf[offset + 1];
250     pointer = reinterpret_cast<void **>(&_simple_slotbuf[offset + 1 + size]);
251 #else
252     if (size & (size - 1))
253         offset += 1;
254     else
255         offset += size;
256     slot = &_simple_slotbuf[offset];
257     offset += size;
258     if (offset & (SIZEOF_VOID_P - 1))
259         offset += SIZEOF_VOID_P - (offset & (SIZEOF_VOID_P - 1));
260     pointer = reinterpret_cast<void **>(&_simple_slotbuf[offset]);
261 #endif
262 }
263 
264 void *
simple_slot(void * ptr,size_t size)265 Args::simple_slot(void *ptr, size_t size)
266 {
267     int offset = _simple_slotpos;
268     while (offset < simple_slotbuf_size && _simple_slotbuf[offset] != 0)
269         offset += simple_slot_size(_simple_slotbuf[offset]);
270 
271     if (size < (size_t) simple_slotbuf_size) {
272         int new_offset = offset + simple_slot_size((int) size);
273         if (new_offset <= simple_slotbuf_size) {
274             void *slot, **pointer;
275             simple_slot_info(offset, (int) size, slot, pointer);
276             _simple_slotbuf[offset] = (int) size;
277             *pointer = ptr;
278             if (new_offset < simple_slotbuf_size)
279                 _simple_slotbuf[new_offset] = 0;
280             return slot;
281         }
282     }
283 
284     BytesSlot *store = new BytesSlot(ptr, size);
285     if (store && store->_slot) {
286         store->_next = _slots;
287         _slots = store;
288         return store->_slot;
289     } else {
290         delete store;
291         error("out of memory");
292         return 0;
293     }
294 }
295 
296 String
error_prefix() const297 ArgContext::error_prefix() const
298 {
299     return _arg_keyword ? String(_arg_keyword) + ": " : String();
300 }
301 
302 void
error(const char * fmt,...) const303 ArgContext::error(const char *fmt, ...) const
304 {
305     va_list val;
306     va_start(val, fmt);
307     xmessage(ErrorHandler::e_error, fmt, val);
308     va_end(val);
309 }
310 
311 void
warning(const char * fmt,...) const312 ArgContext::warning(const char *fmt, ...) const
313 {
314     va_list val;
315     va_start(val, fmt);
316     xmessage(ErrorHandler::e_warning_annotated, fmt, val);
317     va_end(val);
318 }
319 
320 void
message(const char * fmt,...) const321 ArgContext::message(const char *fmt, ...) const
322 {
323     va_list val;
324     va_start(val, fmt);
325     xmessage(ErrorHandler::e_info, fmt, val);
326     va_end(val);
327 }
328 
329 void
xmessage(const String & anno,const String & str) const330 ArgContext::xmessage(const String &anno, const String &str) const
331 {
332     PrefixErrorHandler perrh(_errh, error_prefix());
333     perrh.xmessage(anno, str);
334     if (perrh.nerrors())
335         _read_status = false;
336 }
337 
338 void
xmessage(const String & anno,const char * fmt,va_list val) const339 ArgContext::xmessage(const String &anno, const char *fmt, va_list val) const
340 {
341     PrefixErrorHandler perrh(_errh, error_prefix());
342     perrh.xmessage(anno, fmt, val);
343     if (perrh.nerrors())
344         _read_status = false;
345 }
346 
347 
348 String
find(const char * keyword,int flags,Slot * & slot_status)349 Args::find(const char *keyword, int flags, Slot *&slot_status)
350 {
351     _arg_keyword = keyword;
352     _read_status = true;
353 #if CLICK_DEBUG_ARGS_USAGE
354     _consumed = false;
355 #endif
356     slot_status = _slots;
357 
358     // Check for common errors.
359     // Note that we don't check the whole keyword for validity; there are
360     // sometimes good reasons to pass something like "BADSRC*", which can only
361     // match a positional argument (no keyword will ever match) but still
362     // looks helpful in error messages.
363     if (keyword && isdigit((unsigned char) *keyword))
364         error("keywords must start with a letter or underscore");
365 
366     // Find matching keyword -- normally last, sometimes first.
367     int keyword_length = keyword ? strlen(keyword) : 0;
368     int got = -1, got_kwpos = -1, position = -1;
369     for (int i = 0; i < _kwpos.size(); ++i) {
370         if (position == -1 && _kwpos[i] != -1)
371             position = (_kwpos[i] >= 0 ? i : -2);
372         if (_kwpos[i] == keyword_length
373             && memcmp((*_conf)[i].data(), keyword, keyword_length) == 0) {
374             got = i;
375             got_kwpos = _kwpos[i];
376             _kwpos[i] = -2;
377             if (flags & firstmatch)
378                 break;
379         }
380     }
381 
382     // Check positional arguments.
383     // If the current argument lacks a keyword, assign it to this position.
384     // But if the requested keyword is mandatory but so far lacking, take the
385     // current argument even if it appears to have a keyword.
386     if ((flags & positional) && position >= 0 && _kwpos[position] >= 0
387         && ((got < 0 && (flags & mandatory)) || _kwpos[position] == 0)
388         && (!(flags & firstmatch) || got < 0 || position < got)) {
389         _kwpos[position] = -1;
390         if ((flags & firstmatch) && position < got)
391             _kwpos[got] = keyword_length;
392         if ((flags & firstmatch) || got < position) {
393             got = position;
394             got_kwpos = 0;
395         }
396     }
397 
398     if (got < 0) {
399         if (flags & mandatory) {
400             error("required argument missing");
401             _status = false;
402         }
403         _read_status = false;
404         return String();
405     }
406     if (flags & deprecated)
407         warning("argument deprecated");
408 
409     if (got_kwpos) {
410         const char *s = (*_conf)[got].begin() + got_kwpos,
411             *ends = (*_conf)[got].end();
412         while (s < ends && isspace((unsigned char) *s))
413             ++s;
414         return (*_conf)[got].substring(s, ends);
415     } else
416         return (*_conf)[got];
417 }
418 
419 void
postparse(bool ok,Slot * slot_status)420 Args::postparse(bool ok, Slot *slot_status)
421 {
422     if (!ok && _read_status) {
423         error("parse error");
424         _read_status = false;
425     }
426     _arg_keyword = 0;
427 
428     if (ok) {
429         while (_simple_slotpos < simple_slotbuf_size
430                && _simple_slotbuf[_simple_slotpos] != 0)
431             _simple_slotpos +=
432                 simple_slot_size(_simple_slotbuf[_simple_slotpos]);
433     } else {
434         _status = false;
435         if (_simple_slotpos < simple_slotbuf_size)
436             _simple_slotbuf[_simple_slotpos] = 0;
437         while (_slots != slot_status) {
438             Slot *slot = _slots;
439             _slots = _slots->_next;
440             delete slot;
441         }
442     }
443 }
444 
445 Args &
strip()446 Args::strip()
447 {
448     int delta = 0;
449     for (int i = 0; i < _kwpos.size(); ++i)
450         if (_kwpos[i] < 0)
451             ++delta;
452         else if (delta > 0) {
453             (*_conf)[i - delta] = (*_conf)[i];
454             _kwpos[i - delta] = _kwpos[i];
455         }
456     if (_conf)
457         _conf->resize(_kwpos.size() - delta);
458     _kwpos.resize(_kwpos.size() - delta);
459     return *this;
460 }
461 
462 void
check_complete()463 Args::check_complete()
464 {
465     bool too_many_positional = false;
466     for (int i = 0; i < _kwpos.size(); ++i)
467         if (_kwpos[i] == 0) {
468             too_many_positional = true;
469             _status = false;
470         } else if (_kwpos[i] > 0) {
471             if (_errh)
472                 _errh->error("%.*s: unknown argument", _kwpos[i], (*_conf)[i].data());
473             _status = false;
474         }
475     if (too_many_positional && _errh)
476         _errh->error("too many arguments");
477 }
478 
479 int
execute()480 Args::execute()
481 {
482     if (!_status)
483         return -EINVAL;
484     while (Slot *s = _slots) {
485         _slots = s->_next;
486         s->store();
487         delete s;
488     }
489     for (int offset = 0; offset < _simple_slotpos;
490          offset += simple_slot_size(_simple_slotbuf[offset])) {
491         void *slot, **pointer;
492         simple_slot_info(offset, _simple_slotbuf[offset], slot, pointer);
493         memcpy(*pointer, slot, _simple_slotbuf[offset]);
494     }
495     _simple_slotpos = _simple_slotbuf[0] = 0;
496     return 0;
497 }
498 
499 int
consume()500 Args::consume()
501 {
502     strip();
503 #if CLICK_DEBUG_ARGS_USAGE
504     _consumed = true;
505 #endif
506     return execute();
507 }
508 
509 int
complete()510 Args::complete()
511 {
512     check_complete();
513     return execute();
514 }
515 
516 
517 const char *
span(const char * begin,const char * end,bool is_signed,int & b)518 IntArg::span(const char *begin, const char *end, bool is_signed, int &b)
519 {
520     const char *s = begin;
521     if (s != end && ((is_signed && *s == '-') || *s == '+'))
522         ++s;
523 
524     if ((b == 0 || b == 16) && s + 2 < end
525         && *s == '0' && (s[1] == 'x' || s[1] == 'X')) {
526         s += 2;
527         b = 16;
528     } else if (b == 0 && s + 2 < end
529                && *s == '0' && (s[1] == 'b' || s[1] == 'B')) {
530         s += 2;
531         b = 2;
532     } else if (b == 0 && s != end && *s == '0')
533         b = 8;
534     else if (b == 0)
535         b = 10;
536 
537     int ndigits = (b > 10 ? 10 : b), nletters = (b > 10 ? b - 10 : 0);
538     const char *firstdigit = s, *lastdigit = s - 1;
539     for (; s != end; ++s) {
540         if (*s == '_' && lastdigit == s)
541             /* allow underscores between digits */;
542         else if ((*s >= '0' && *s < '0' + ndigits)
543                  || (*s >= 'A' && *s < 'A' + nletters)
544                  || (*s >= 'a' && *s < 'a' + nletters))
545             lastdigit = s + 1;
546         else
547             break;
548     }
549 
550     if (s != firstdigit)
551         return lastdigit;
552     else if (firstdigit > begin + 1)
553         // Happens in cases like "0x!" or "+0x": parse the initial "0".
554         return firstdigit - 1;
555     else
556         return begin;
557 }
558 
559 const char *
parse(const char * begin,const char * end,bool is_signed,int size,limb_type * value,int nlimb)560 IntArg::parse(const char *begin, const char *end, bool is_signed, int size,
561               limb_type *value, int nlimb)
562 {
563     int b = base;
564     const char *xend = span(begin, end, is_signed, b);
565     if (b < 2 || b > 36 || xend == begin) {
566         status = status_inval;
567         return begin;
568     }
569 
570     constexpr limb_type threshold = integer_traits<limb_type>::const_max / 36;
571     uint32_t v0 = 0;
572     memset(value, 0, sizeof(limb_type) * nlimb);
573     int nletters = (b > 10 ? b - 10 : 0);
574     status = status_ok;
575     for (const char *s = begin; s != xend; ++s) {
576         int digit;
577         if (*s >= '0' && *s <= '9')
578             digit = *s - '0';
579         else if (*s >= 'A' && *s < 'A' + nletters)
580             digit = *s - 'A' + 10;
581         else if (*s >= 'a' && *s < 'a' + nletters)
582             digit = *s - 'a' + 10;
583         else
584             continue;
585         if (v0 < threshold)
586             value[0] = v0 = v0 * b + digit;
587         else if (Bigint<limb_type>::multiply_half(value, value, nlimb, b, digit))
588             status = status_range;
589     }
590 
591     bool negative = is_signed && *begin == '-';
592     int bitsize = size * 8 - is_signed;
593     constexpr int limb_bits = int(sizeof(limb_type)) * 8;
594 
595     int bpos = 0;
596     for (limb_type *x = value; x != value + nlimb && status == status_ok;
597          ++x, bpos += limb_bits)
598         if ((bpos >= bitsize && *x != 0)
599             || (bpos < bitsize && bitsize < bpos + limb_bits
600                 && *x >= (1U << (bitsize - bpos)) + negative))
601             status = status_range;
602 
603     if (status == status_range) {
604         memset(value, negative ? 0 : 255, size);
605         if (is_signed)
606             value[bitsize / limb_bits] ^= 1U << (bitsize & (limb_bits - 1));
607     }
608 
609     if (negative) {
610         limb_type *first_zero = value + nlimb;
611         for (limb_type *x = value; x != value + nlimb; ++x)
612             if ((*x = -*x))
613                 first_zero = x + 1;
614         for (limb_type *x = first_zero; x != value + nlimb; ++x)
615             --*x;
616     }
617 
618     return xend;
619 }
620 
621 void
range_error(const ArgContext & args,bool is_signed,click_intmax_t value)622 IntArg::range_error(const ArgContext &args, bool is_signed,
623                     click_intmax_t value)
624 {
625     status = status_range;
626     if (is_signed)
627         args.error("out of range, bound %" CLICK_ERRHdMAX, value);
628     else
629         args.error("out of range, bound %" CLICK_ERRHuMAX, click_uintmax_t(value));
630 }
631 
632 
633 namespace {
634 typedef click_uintmax_t value_type;
635 typedef click_intmax_t signed_value_type;
636 
637 const char *
preparse_fraction(const char * begin,const char * end,bool is_signed,int & integer_digits)638 preparse_fraction(const char *begin, const char *end, bool is_signed,
639                   int &integer_digits)
640 {
641     const char *s = begin;
642     if (s != end && ((is_signed && *s == '-') || *s == '+'))
643         ++s;
644 
645     const char *firstdigit = s, *lastdigit = firstdigit - 1;
646     bool decimalpoint = false;
647     for (; s != end; ++s) {
648         if (*s == '_' && lastdigit == s)
649             /* OK */;
650         else if (*s == '.' && !decimalpoint
651                  && (lastdigit == s || firstdigit == s))
652             decimalpoint = true;
653         else if (*s >= '0' && *s <= '9') {
654             if (!decimalpoint)
655                 ++integer_digits;
656             lastdigit = s + 1;
657         } else
658             break;
659     }
660 
661     // error if no digits at all
662     if (lastdigit == firstdigit - 1)
663         return begin;
664 
665     // optional exponent
666     if (s != end && (*s == 'E' || *s == 'e') && s + 1 != end) {
667         const char *echar = s;
668         s += (s[1] == '-' || s[1] == '+' ? 2 : 1);
669         if (s != end && isdigit((unsigned char) *s)) {
670             int exponent = *s - '0';
671             // XXX overflow
672             for (++s; s != end && isdigit((unsigned char) *s); ++s)
673                 exponent = 10 * exponent + *s - '0';
674             integer_digits += (echar[1] == '-' ? -exponent : exponent);
675         } else
676             s = echar;
677     }
678 
679     return s;
680 }
681 
682 const char *
parse_integer_portion(const char * s,const char * end,int integer_digits,value_type & ivalue,int & status)683 parse_integer_portion(const char *s, const char *end, int integer_digits,
684                       value_type &ivalue, int &status)
685 {
686     constexpr value_type thresh = integer_traits<value_type>::const_max / 10;
687     constexpr int thresh_digit = integer_traits<value_type>::const_max - thresh * 10;
688     ivalue = 0;
689     while (integer_digits > 0) {
690         int digit;
691         if (s == end || *s == 'E' || *s == 'e')
692             digit = 0;
693         else if (*s >= '0' && *s <= '9') {
694             digit = *s - '0';
695             ++s;
696         } else {
697             ++s;
698             continue;
699         }
700         if (ivalue > thresh || (ivalue == thresh && digit > thresh_digit)) {
701             ivalue = integer_traits<value_type>::const_max;
702             status = NumArg::status_range;
703         } else
704             ivalue = 10 * ivalue + digit;
705         --integer_digits;
706     }
707     return s;
708 }
709 
710 const char *
parse_decimal_fraction(const char * begin,const char * end,bool is_signed,int exponent_delta,value_type & ivalue,int fraction_digits,uint32_t & fvalue,int & status)711 parse_decimal_fraction(const char *begin, const char *end,
712                        bool is_signed, int exponent_delta,
713                        value_type &ivalue,
714                        int fraction_digits, uint32_t &fvalue,
715                        int &status)
716 {
717     int integer_digits = exponent_delta;
718     end = preparse_fraction(begin, end, is_signed, integer_digits);
719     if (end == begin) {
720         status = NumArg::status_inval;
721         return begin;
722     }
723 
724     status = NumArg::status_ok;
725     const char *s = begin;
726 
727     ivalue = 0;
728     if (integer_digits > 0) {
729         s = parse_integer_portion(s, end, integer_digits, ivalue, status);
730         integer_digits = 0;
731     }
732 
733     fvalue = 0;
734     uint32_t maxfvalue = 1;
735     while (fraction_digits > 0) {
736         int digit;
737         if (integer_digits < 0) {
738             digit = 0;
739             ++integer_digits;
740         } else if (s == end || *s == 'E' || *s == 'e')
741             digit = 0;
742         else if (*s >= '0' && *s <= '9') {
743             digit = *s - '0';
744             ++s;
745         } else {
746             ++s;
747             continue;
748         }
749         fvalue = fvalue * 10 + digit;
750         maxfvalue = maxfvalue * 10;
751         --fraction_digits;
752     }
753     // perhaps round up
754     while (s != end && *s != 'E' && *s != 'e' && (*s < '0' || *s > '9'))
755         ++s;
756     if (s != end && *s >= '5' && *s <= '9' && ++fvalue == maxfvalue) {
757         fvalue = 0;
758         if (++ivalue == 0)
759             status = NumArg::status_range;
760     }
761 
762     return end;
763 }
764 
765 template<typename V, typename L = uint32_t>
766 struct fraction_accum {
767     enum { nlimb = (sizeof(V) / sizeof(L)) + 1 };
fraction_accum__anoncfbfd9190111::fraction_accum768     fraction_accum()
769         : zero(true) {
770         static_assert(sizeof(V) % sizeof(L) == 0, "V must be a size multiple of L");
771         for (int i = 0; i < nlimb; ++i)
772             limbs[i] = 0;
773     }
add_decimal_digit__anoncfbfd9190111::fraction_accum774     void add_decimal_digit(int d) {
775         if (d || !zero) {
776             zero = false;
777             limbs[nlimb - 1] += d << 1;
778             Bigint<L>::divide(limbs, limbs, nlimb, 10);
779         }
780     }
extract__anoncfbfd9190111::fraction_accum781     bool extract(V &value) {
782         if (zero)
783             value = 0;
784         else {
785             for (L *l = limbs; true; ++l)
786                 if (++*l != 0)
787                     break;
788             extract_integer(limbs, value);
789             value >>= 1;
790             if (limbs[nlimb - 1] & 1)
791                 value |= V(1) << (sizeof(V) * 8 - 1);
792         }
793         return limbs[nlimb - 1] > 1;
794     }
is_zero__anoncfbfd9190111::fraction_accum795     bool is_zero() const {
796         return zero;
797     }
798     L limbs[nlimb];
799     bool zero;
800 };
801 
802 #if HAVE_INT64_TYPES
803 template<>
804 struct fraction_accum<uint32_t, uint32_t> {
fraction_accum__anoncfbfd9190111::fraction_accum805     fraction_accum()
806         : accum(0) {
807     }
add_decimal_digit__anoncfbfd9190111::fraction_accum808     void add_decimal_digit(int d) {
809         accum = int_divide(accum + (uint64_t(d) << 33), 10);
810     }
extract__anoncfbfd9190111::fraction_accum811     bool extract(uint32_t &value) {
812         ++accum;
813         value = (accum >> 1);
814         return accum >= (uint64_t(1) << 33);
815     }
is_zero__anoncfbfd9190111::fraction_accum816     bool is_zero() const {
817         return accum == 0;
818     }
819     uint64_t accum;
820 };
821 #endif
822 
823 const char *
parse_fraction(const char * begin,const char * end,bool is_signed,int exponent_delta,value_type & ivalue,uint32_t & fvalue,int & status)824 parse_fraction(const char *begin, const char *end,
825                bool is_signed, int exponent_delta,
826                value_type &ivalue, uint32_t &fvalue, int &status)
827 {
828     int integer_digits = exponent_delta;
829     end = preparse_fraction(begin, end, is_signed, integer_digits);
830     if (end == begin) {
831         status = NumArg::status_inval;
832         return begin;
833     }
834 
835     status = NumArg::status_ok;
836     const char *s = begin;
837 
838     ivalue = 0;
839     if (integer_digits > 0) {
840         s = parse_integer_portion(s, end, integer_digits, ivalue, status);
841         integer_digits = 0;
842     }
843 
844     const char *x = s;
845     while (x != end && *x != 'E' && *x != 'e')
846         ++x;
847     fraction_accum<uint32_t> fwork;
848     while (x != s) {
849         --x;
850         if (*x >= '0' && *x <= '9') {
851             fwork.add_decimal_digit(*x - '0');
852             ++integer_digits;
853         }
854     }
855     while (integer_digits <= 0 && !fwork.is_zero()) {
856         fwork.add_decimal_digit(0);
857         ++integer_digits;
858     }
859     if (fwork.extract(fvalue) && ++ivalue == 0)
860         status = NumArg::status_range;
861 
862     return end;
863 }
864 }
865 
866 
867 bool
underparse(const String & str,bool is_signed,uint32_t & result)868 FixedPointArg::underparse(const String &str, bool is_signed, uint32_t &result)
869 {
870     value_type ivalue;
871     uint32_t fvalue;
872     const char *end = parse_fraction(str.begin(), str.end(),
873                                      is_signed, exponent_delta,
874                                      ivalue, fvalue, status);
875     if (end != str.end())
876         status = status_inval;
877     if (status && status != status_range)
878         return false;
879 
880     if (fraction_bits == 32) {
881         // Separating this case helps avoid undefined behavior like <<32
882         if (ivalue == 0)
883             result = fvalue;
884         else
885             status = status_range;
886     } else {
887         value_type mivalue = ivalue;
888         uint32_t mfvalue = fvalue + (1U << (31 - fraction_bits));
889         if (mfvalue < fvalue)
890             ++mivalue;
891         if (mivalue >= ivalue && mivalue < (1U << (32 - fraction_bits)))
892             result = (uint32_t(mivalue) << fraction_bits)
893                 | (mfvalue >> (32 - fraction_bits));
894         else
895             status = status_range;
896     }
897     if (status == status_range)
898         result = 0xFFFFFFFFU;
899     return true;
900 }
901 
902 bool
parse(const String & str,uint32_t & result,const ArgContext & args)903 FixedPointArg::parse(const String &str, uint32_t &result, const ArgContext &args)
904 {
905     uint32_t x;
906     if (!underparse(str, false, x))
907         return false;
908     else if (status == status_range) {
909         args.error("out of range, bound %s", cp_unparse_real2(x, fraction_bits).c_str());
910         return false;
911     } else {
912         result = x;
913         return true;
914     }
915 }
916 
917 bool
parse_saturating(const String & str,int32_t & result,const ArgContext &)918 FixedPointArg::parse_saturating(const String &str, int32_t &result, const ArgContext &)
919 {
920     uint32_t x;
921     if (!underparse(str, true, x))
922         return false;
923     bool negative = str[0] == '-';
924     if (status == status_ok
925         && x > uint32_t(integer_traits<int32_t>::const_max) + negative) {
926         status = status_range;
927         x = uint32_t(integer_traits<int32_t>::const_max) + negative;
928     }
929     result = negative ? -x : x;
930     return true;
931 }
932 
933 bool
parse(const String & str,int32_t & result,const ArgContext & args)934 FixedPointArg::parse(const String &str, int32_t &result, const ArgContext &args)
935 {
936     int32_t x;
937     if (!parse_saturating(str, x, args))
938         return false;
939     else if (status == status_range) {
940         args.error("out of range, bound %s", cp_unparse_real2(int32_t(x), fraction_bits).c_str());
941         return false;
942     } else {
943         result = x;
944         return true;
945     }
946 }
947 
948 
949 static uint32_t exp10val[] = { 1, 10, 100, 1000, 10000, 100000, 1000000,
950                                10000000, 100000000, 1000000000 };
951 
952 bool
underparse(const String & str,bool is_signed,uint32_t & result)953 DecimalFixedPointArg::underparse(const String &str, bool is_signed, uint32_t &result)
954 {
955     assert(fraction_digits < int(sizeof(exp10val) / sizeof(exp10val[0])));
956 
957     value_type ivalue;
958     uint32_t fvalue;
959     const char *end = parse_decimal_fraction(str.begin(), str.end(),
960                                              is_signed, exponent_delta,
961                                              ivalue, fraction_digits, fvalue, status);
962     if (end != str.end())
963         status = status_inval;
964     if (status && status != status_range)
965         return false;
966 
967     uint32_t mivalue(ivalue);
968     if (mivalue == ivalue) {
969         uint32_t imul[2];
970         int_multiply(mivalue, exp10val[fraction_digits], imul[0], imul[1]);
971         if (imul[1] == 0 && imul[0] + fvalue >= imul[0])
972             mivalue = imul[0] + fvalue;
973         else
974             status = status_range;
975     } else
976         status = status_range;
977 
978     if (status == status_range)
979         mivalue = integer_traits<uint32_t>::const_max;
980     result = mivalue;
981     return true;
982 }
983 
984 bool
parse(const String & str,uint32_t & result,const ArgContext & args)985 DecimalFixedPointArg::parse(const String &str, uint32_t &result,
986                             const ArgContext &args)
987 {
988     uint32_t x;
989     if (!underparse(str, false, x))
990         return false;
991     else if (status == status_range) {
992         args.error("out of range");
993         return false;
994     } else {
995         result = x;
996         return true;
997     }
998 }
999 
1000 bool
parse_saturating(const String & str,int32_t & result,const ArgContext &)1001 DecimalFixedPointArg::parse_saturating(const String &str, int32_t &result,
1002                                        const ArgContext &)
1003 {
1004     uint32_t x;
1005     if (!underparse(str, true, x))
1006         return false;
1007     bool negative = str[0] == '-';
1008     uint32_t limit(negative ? integer_traits<int32_t>::const_min
1009                    : integer_traits<int32_t>::const_max);
1010     if (x > limit) {
1011         status = status_range;
1012         result = limit;
1013     } else
1014         result = x;
1015     return true;
1016 }
1017 
1018 bool
parse(const String & str,int32_t & result,const ArgContext & args)1019 DecimalFixedPointArg::parse(const String &str, int32_t &result,
1020                             const ArgContext &args)
1021 {
1022     int32_t x;
1023     if (!parse_saturating(str, x, args))
1024         return false;
1025     else if (status == status_range) {
1026         args.error("out of range");
1027         return false;
1028     } else {
1029         result = x;
1030         return true;
1031     }
1032 }
1033 
1034 bool
parse_saturating(const String & str,uint32_t & iresult,uint32_t & fresult,const ArgContext &)1035 DecimalFixedPointArg::parse_saturating(const String &str, uint32_t &iresult,
1036                                        uint32_t &fresult, const ArgContext &)
1037 {
1038     value_type ivalue;
1039     uint32_t fvalue;
1040     const char *end = parse_decimal_fraction(str.begin(), str.end(),
1041                                              false, exponent_delta,
1042                                              ivalue, fraction_digits, fvalue, status);
1043     if (end != str.end())
1044         status = status_inval;
1045     if (status && status != status_range)
1046         return false;
1047     if (uint32_t(ivalue) != ivalue)
1048         status = status_range;
1049     if (status == status_range) {
1050         iresult = integer_traits<uint32_t>::const_max;
1051         fresult = exp10val[fraction_digits] - 1;
1052     } else {
1053         iresult = ivalue;
1054         fresult = fvalue;
1055     }
1056     return true;
1057 }
1058 
1059 bool
parse(const String & str,uint32_t & iresult,uint32_t & fresult,const ArgContext & args)1060 DecimalFixedPointArg::parse(const String &str, uint32_t &iresult,
1061                             uint32_t &fresult, const ArgContext &args)
1062 {
1063     uint32_t ivalue, fvalue;
1064     if (!parse_saturating(str, ivalue, fvalue, args))
1065         return false;
1066     else if (status == status_range) {
1067         args.error("out of range");
1068         return false;
1069     } else {
1070         iresult = ivalue;
1071         fresult = fvalue;
1072         return true;
1073     }
1074 }
1075 
1076 
1077 #if HAVE_FLOAT_TYPES
1078 bool
parse(const String & str,double & result,const ArgContext & args)1079 DoubleArg::parse(const String &str, double &result, const ArgContext &args)
1080 {
1081     if (str.length() == 0 || isspace((unsigned char) str[0])) {
1082     format_error:
1083         // check for space because strtod() accepts leading whitespace
1084         status = status_inval;
1085         return false;
1086     }
1087 
1088     errno = 0;
1089     char *endptr;
1090     double value = strtod(str.c_str(), &endptr);
1091     if (endptr != str.end())            // bad format; garbage after number
1092         goto format_error;
1093 
1094     if (errno == ERANGE) {
1095         status = status_range;
1096         const char *fmt;
1097         if (value == 0)
1098             fmt = "underflow, rounded to %g";
1099         else
1100             fmt = "out of range, bound %g";
1101         args.error(fmt, value);
1102         return false;
1103     }
1104 
1105     status = status_ok;
1106     result = value;
1107     return true;
1108 }
1109 #endif
1110 
1111 
1112 bool
parse(const String & str,bool & result,const ArgContext &)1113 BoolArg::parse(const String &str, bool &result, const ArgContext &)
1114 {
1115     const char *s = str.data();
1116     int len = str.length();
1117 
1118     if (len == 1 && (s[0] == '0' || s[0] == 'n' || s[0] == 'f'))
1119         result = false;
1120     else if (len == 1 && (s[0] == '1' || s[0] == 'y' || s[0] == 't'))
1121         result = true;
1122     else if (len == 5 && memcmp(s, "false", 5) == 0)
1123         result = false;
1124     else if (len == 4 && memcmp(s, "true", 4) == 0)
1125         result = true;
1126     else if (len == 2 && memcmp(s, "no", 2) == 0)
1127         result = false;
1128     else if (len == 3 && memcmp(s, "yes", 3) == 0)
1129         result = true;
1130     else
1131         return false;
1132 
1133     return true;
1134 }
1135 
1136 
1137 void
check_units()1138 UnitArg::check_units()
1139 {
1140     const unsigned char *u = units_;
1141     Vector<String> suffixes;
1142     while (*u) {
1143         assert(*u >= 1 && *u <= 7 && *u != 4);
1144         const unsigned char *next = u + 2 + (*u & 3);
1145         assert(*next);
1146         const unsigned char *post = next + 1;
1147         while (*post > 7)
1148             ++post;
1149         String suffix(next, post);
1150         for (String *it = suffixes.begin(); it != suffixes.end(); ++it)
1151             assert(suffix.length() < it->length()
1152                    || it->substring(-suffix.length()) != suffix);
1153         suffixes.push_back(suffix);
1154         u = post;
1155     }
1156 }
1157 
1158 const char *
parse(const char * begin,const char * end,int & power,int & factor) const1159 UnitArg::parse(const char *begin, const char *end, int &power, int &factor) const
1160 {
1161     const unsigned char *units = units_;
1162 
1163     while (*units) {
1164         const unsigned char *ubegin = units + 2 + (*units & 3);
1165         const unsigned char *uend = ubegin + 1;
1166         while (*uend > 7)
1167             ++uend;
1168 
1169         if (uend - ubegin <= end - begin
1170             && memcmp(ubegin, end - (uend - ubegin), uend - ubegin) == 0) {
1171             factor = units[2];
1172             if ((*units & 3) >= 2)
1173                 factor = 256 * factor + units[3];
1174             if ((*units & 3) >= 3)
1175                 factor = 256 * factor + units[4];
1176 
1177             power = units[1];
1178             if (*units >= 4)
1179                 power = -power;
1180 
1181             end = end - (uend - ubegin);
1182             if (prefix_chars_ && end > begin)
1183                 for (const unsigned char *prefix_chars = prefix_chars_;
1184                      *prefix_chars; prefix_chars += 2)
1185                     if ((char) *prefix_chars == end[-1]) {
1186                         power += prefix_chars[1] - 64;
1187                         --end;
1188                         break;
1189                     }
1190 
1191             while (end > begin && isspace((unsigned char) end[-1]))
1192                 --end;
1193             return end;
1194         }
1195 
1196         units = uend;
1197     }
1198 
1199     power = 0;
1200     factor = 1;
1201     return end;
1202 }
1203 
1204 
1205 static const char byte_bandwidth_units[] = "\
1206 \5\3\175baud\
1207 \5\3\175bps\
1208 \5\3\175b/s\
1209 \1\0\1Bps\
1210 \1\0\1B/s\
1211 ";
1212 static const char byte_bandwidth_prefixes[] = "\
1213 k\103K\103M\106G\111";
1214 
1215 static uint32_t
multiply_factor(uint32_t ix,uint32_t fx,uint32_t factor,int & status)1216 multiply_factor(uint32_t ix, uint32_t fx, uint32_t factor, int &status)
1217 {
1218     if (factor == 1) {
1219         if (int32_t(fx) < 0 && ++ix == 0)
1220             status = NumArg::status_range;
1221         return ix;
1222     } else {
1223         uint32_t flow, ftoint, ilow, ihigh;
1224         int_multiply(fx, factor, flow, ftoint);
1225         if (int32_t(flow) < 0)
1226             ++ftoint;
1227         int_multiply(ix, factor, ilow, ihigh);
1228         if (ihigh != 0 || ilow + ftoint < ftoint)
1229             status = NumArg::status_range;
1230         return ilow + ftoint;
1231     }
1232 }
1233 
1234 bool
parse(const String & str,uint32_t & result,const ArgContext & args)1235 BandwidthArg::parse(const String &str, uint32_t &result, const ArgContext &args)
1236 {
1237     int power, factor;
1238     const char *unit_end = UnitArg(byte_bandwidth_units, byte_bandwidth_prefixes).parse(str.begin(), str.end(), power, factor);
1239 
1240     value_type ix;
1241     uint32_t fx;
1242     const char *xend = parse_fraction(str.begin(), unit_end,
1243                                       false, power, ix, fx, status);
1244     if (status == status_inval || xend != unit_end) {
1245         status = status_inval;
1246         return false;
1247     }
1248     if (uint32_t(ix) != ix)
1249         status = status_range;
1250     ix = multiply_factor(ix, fx, factor, status);
1251     if (status == status_range) {
1252         args.error("out of range");
1253         result = 0xFFFFFFFFU;
1254         return false;
1255     } else {
1256         if (unit_end == str.end() && ix)
1257             status = status_unitless;
1258         result = ix;
1259         return true;
1260     }
1261 }
1262 
1263 String
unparse(uint32_t x)1264 BandwidthArg::unparse(uint32_t x)
1265 {
1266     if (x >= 0x20000000U)
1267         return cp_unparse_real10(x, 6) + "MBps";
1268     else if (x >= 125000000)
1269         return cp_unparse_real10(x * 8, 9) + "Gbps";
1270     else if (x >= 125000)
1271         return cp_unparse_real10(x * 8, 6) + "Mbps";
1272     else
1273         return cp_unparse_real10(x * 8, 3) + "kbps";
1274 }
1275 
1276 
1277 static const char seconds_units[] = "\
1278 \1\0\1s\
1279 \1\0\1sec\
1280 \1\1\6m\
1281 \1\1\6min\
1282 \1\2\044h\
1283 \1\2\044hr\
1284 \2\2\003\140d\
1285 \2\2\003\140day";
1286 static const char seconds_prefixes[] = "m\075u\072n\067";
1287 
1288 bool
parse_saturating(const String & str,uint32_t & result,const ArgContext &)1289 SecondsArg::parse_saturating(const String &str, uint32_t &result, const ArgContext &)
1290 {
1291     int power, factor;
1292     const char *unit_end = UnitArg(seconds_units, seconds_prefixes).parse(str.begin(), str.end(), power, factor);
1293 
1294     value_type ix;
1295     uint32_t fx;
1296     const char *xend = parse_fraction(str.begin(), unit_end,
1297                                       false, power + fraction_digits, ix, fx, status);
1298     if (status == status_inval || xend != unit_end) {
1299         status = status_inval;
1300         return false;
1301     }
1302     if (uint32_t(ix) != ix)
1303         status = status_range;
1304     ix = multiply_factor(ix, fx, factor, status);
1305     if (status == status_range)
1306         ix = integer_traits<uint32_t>::const_max;
1307     result = ix;
1308     return true;
1309 }
1310 
1311 bool
parse(const String & str,uint32_t & result,const ArgContext & args)1312 SecondsArg::parse(const String &str, uint32_t &result, const ArgContext &args)
1313 {
1314     uint32_t x;
1315     if (!parse_saturating(str, x, args))
1316         return false;
1317     else if (status == status_range) {
1318         args.error("out of range");
1319         return false;
1320     } else {
1321         result = x;
1322         return true;
1323     }
1324 }
1325 
1326 #if HAVE_FLOAT_TYPES
1327 bool
parse(const String & str,double & result,const ArgContext &)1328 SecondsArg::parse(const String &str, double &result, const ArgContext &)
1329 {
1330     int power, factor;
1331     const char *unit_end = UnitArg(seconds_units, seconds_prefixes).parse(str.begin(), str.end(), power, factor);
1332     if (!DoubleArg().parse(str.substring(str.begin(), unit_end), result))
1333         return false;
1334     if (factor != 1)
1335         result *= factor;
1336     power += fraction_digits;
1337     if (power != 0)
1338         result *= pow(10, power);
1339     return true;
1340 }
1341 #endif
1342 
1343 
1344 #if CLICK_USERLEVEL || CLICK_TOOL
1345 bool
parse(const String & str,String & result,const ArgContext &)1346 FilenameArg::parse(const String &str, String &result, const ArgContext &)
1347 {
1348     String fn;
1349     if (!cp_string(str, &fn) || !fn)
1350         return false;
1351 
1352     // expand home directory substitutions
1353     if (fn[0] == '~') {
1354         if (fn.length() == 1 || fn[1] == '/') {
1355             const char *home = getenv("HOME");
1356             if (home)
1357                 fn = String(home) + fn.substring(1);
1358         } else {
1359             int off = 1;
1360             while (off < fn.length() && fn[off] != '/')
1361                 off++;
1362             String username = fn.substring(1, off - 1);
1363             struct passwd *pwd = getpwnam(username.c_str());
1364             if (pwd && pwd->pw_dir)
1365                 fn = String(pwd->pw_dir) + fn.substring(off);
1366         }
1367     }
1368 
1369     // replace double slashes with single slashes
1370     int len = fn.length();
1371     for (int i = 0; i < len - 1; i++)
1372         if (fn[i] == '/' && fn[i+1] == '/') {
1373             fn = fn.substring(0, i) + fn.substring(i + 1);
1374             i--;
1375             len--;
1376         }
1377 
1378     // return
1379     result = fn;
1380     return true;
1381 }
1382 #endif
1383 
1384 
1385 #if !CLICK_TOOL
1386 bool
parse(const String & str,int & result,const ArgContext & args)1387 AnnoArg::parse(const String &str, int &result, const ArgContext &args)
1388 {
1389     int32_t annoval;
1390     if (!NameInfo::query_int(NameInfo::T_ANNOTATION, args.context(),
1391                              str, &annoval))
1392         return false;
1393     if (size > 0) {
1394         if (ANNOTATIONINFO_SIZE(annoval) && ANNOTATIONINFO_SIZE(annoval) != size)
1395             return false;
1396 # if !HAVE_INDIFFERENT_ALIGNMENT
1397         if ((size == 2 || size == 4 || size == 8)
1398             && (ANNOTATIONINFO_OFFSET(annoval) % size) != 0)
1399             return false;
1400 # endif
1401         if (ANNOTATIONINFO_OFFSET(annoval) + size > Packet::anno_size)
1402             return false;
1403         annoval = ANNOTATIONINFO_OFFSET(annoval);
1404     } else if (ANNOTATIONINFO_OFFSET(annoval) >= Packet::anno_size)
1405         return false;
1406     result = annoval;
1407     return true;
1408 }
1409 
1410 bool
parse(const String & str,Element * & result,const ArgContext & args)1411 ElementArg::parse(const String &str, Element *&result, const ArgContext &args)
1412 {
1413     const Element *context = args.context();
1414     assert(context);
1415 
1416     result = context->router()->find(str, context);
1417     if (!result)
1418         args.error("does not name an element");
1419     return result;
1420 }
1421 
1422 bool
parse(const String & str,Element * & result,const ArgContext & args)1423 ElementCastArg::parse(const String &str, Element *&result, const ArgContext &args)
1424 {
1425     if (ElementArg::parse(str, result, args)
1426         && !(result = reinterpret_cast<Element *>(result->cast(type))))
1427         args.error("element type mismatch, expected %s", type);
1428     return result;
1429 }
1430 #endif
1431 
1432 CLICK_ENDDECLS
1433