PageRenderTime 56ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/error.cc

https://github.com/bhesmans/click
C++ | 1235 lines | 1020 code | 146 blank | 69 comment | 363 complexity | d12d5ce0c442459459d4d95c3c68c66b MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause
  1. // -*- related-file-name: "../include/click/error.hh" -*-
  2. /*
  3. * error.{cc,hh} -- flexible classes for error reporting
  4. * Eddie Kohler
  5. *
  6. * Copyright (c) 1999-2000 Massachusetts Institute of Technology
  7. * Copyright (c) 2001-2008 Eddie Kohler
  8. * Copyright (c) 2008 Meraki, Inc.
  9. *
  10. * Permission is hereby granted, free of charge, to any person obtaining a
  11. * copy of this software and associated documentation files (the "Software"),
  12. * to deal in the Software without restriction, subject to the conditions
  13. * listed in the Click LICENSE file. These conditions include: you must
  14. * preserve this copyright notice, and you cannot mention the copyright
  15. * holders in advertising related to the Software without their permission.
  16. * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
  17. * notice is a summary of the Click LICENSE file; the license in that file is
  18. * legally binding.
  19. */
  20. #include <click/config.h>
  21. #include <click/error.hh>
  22. #include <click/straccum.hh>
  23. #ifndef CLICK_TOOL
  24. # include <click/element.hh>
  25. #endif
  26. #include <click/ipaddress.hh>
  27. #include <click/etheraddress.hh>
  28. #include <click/timestamp.hh>
  29. #include <click/confparse.hh>
  30. #include <click/algorithm.hh>
  31. #if CLICK_USERLEVEL || CLICK_TOOL
  32. # include <unistd.h>
  33. #endif
  34. CLICK_DECLS
  35. /** @file error.hh
  36. * @brief Flexible error handling classes.
  37. */
  38. struct ErrorHandler::Conversion {
  39. String name;
  40. ConversionFunction hook;
  41. Conversion *next;
  42. };
  43. static ErrorHandler::Conversion *error_items;
  44. const char ErrorHandler::e_abort[] = "<-999>";
  45. const char ErrorHandler::e_fatal[] = "<-1>";
  46. const char ErrorHandler::e_emergency[] = "<0>";
  47. const char ErrorHandler::e_alert[] = "<1>";
  48. const char ErrorHandler::e_critical[] = "<2>";
  49. const char ErrorHandler::e_error[] = "<3>";
  50. const char ErrorHandler::e_warning[] = "<4>";
  51. const char ErrorHandler::e_warning_annotated[] = "<4>warning: ";
  52. const char ErrorHandler::e_notice[] = "<5>";
  53. const char ErrorHandler::e_info[] = "<6>";
  54. const char ErrorHandler::e_debug[] = "<7>";
  55. const int ErrorHandler::ok_result = 0;
  56. const int ErrorHandler::error_result = -EINVAL;
  57. ErrorHandler *ErrorHandler::the_default_handler = 0;
  58. ErrorHandler *ErrorHandler::the_silent_handler = 0;
  59. // ANNOTATION MANAGEMENT
  60. static const char *
  61. parse_level(const char *begin, const char *end, int *result)
  62. {
  63. int x = 0;
  64. const char *s = begin;
  65. bool negative = false;
  66. if (s != end && *s == '-') {
  67. negative = true;
  68. ++s;
  69. } else if (s != end && *s == '+')
  70. ++s;
  71. const char *digits = s;
  72. for (; s != end && *s >= '0' && *s <= '9'; ++s)
  73. x = x * 10 + *s - '0';
  74. if (s != end && *s == '.')
  75. for (++s; s != end && *s >= '0' && *s <= '9'; ++s)
  76. /* nada */;
  77. if (s == digits || (s == digits + 1 && s[-1] == '.'))
  78. return begin;
  79. if (result)
  80. *result = (negative ? -x : x);
  81. return s;
  82. }
  83. String
  84. ErrorHandler::make_anno(const char *name, const String &value)
  85. {
  86. StringAccum sa;
  87. sa.reserve(value.length() + 10);
  88. // level annotation requires special handling
  89. if (name[0] == '<' && name[1] == '>' && name[2] == 0) {
  90. if (parse_level(value.begin(), value.end(), 0) == value.end()) {
  91. sa << '<' << value << '>';
  92. return sa.take_string();
  93. } else
  94. return String();
  95. }
  96. sa << '{' << name << ':';
  97. const char *last = value.begin(), *end = value.end();
  98. for (const char *s = value.begin(); s != end; ++s)
  99. if (*s == '\\' || *s == '}') {
  100. sa.append(last, s);
  101. sa << '\\' << *s;
  102. last = s + 1;
  103. } else if (*s == '\n') {
  104. sa.append(last, s);
  105. sa << '\\' << 'n';
  106. last = s + 1;
  107. }
  108. sa.append(last, end);
  109. sa << '}';
  110. return sa.take_string();
  111. }
  112. const char *
  113. ErrorHandler::skip_anno(const String &str, const char *begin, const char *end,
  114. String *name_result, String *value_result, bool raw)
  115. {
  116. String name, value;
  117. const char *s = begin;
  118. if (s + 3 <= end && *s == '<') {
  119. const char *x = parse_level(s + 1, end, 0);
  120. if (x != s + 1 && x != end && *x == '>') {
  121. name = String::make_stable("<>", 2);
  122. if (likely(str))
  123. value = str.substring(begin + 1, x);
  124. begin = x + 1;
  125. }
  126. } else if (s + 2 <= end && *s == '{' && s[1] == '}')
  127. begin = s + 2;
  128. else if (s + 3 <= end && *s == '{' && str) {
  129. for (++s; s != end && isalnum((unsigned char) *s); ++s)
  130. /* nada */;
  131. if (s == end || s == begin + 1 || (*s != '}' && *s != ':'))
  132. /* not an annotation */;
  133. else if (*s == '}' && likely(str)) {
  134. name = str.substring(begin + 1, s);
  135. begin = s + 1;
  136. } else if (*s == '}') {
  137. name = String::make_stable("{}", 2);
  138. begin = s + 1;
  139. } else if (likely(str)) {
  140. const char *x, *last = s + 1;
  141. StringAccum sa;
  142. for (x = s + 1; x != end && *x != '\n' && *x != '}'; ++x)
  143. if (*x == '\\' && x + 1 != end && x[1] != '\n') {
  144. if (!raw) {
  145. sa.append(last, x);
  146. sa << (x[1] == 'n' ? '\n' : x[1]);
  147. last = x + 2;
  148. }
  149. ++x;
  150. }
  151. if (x != end && *x == '}') {
  152. name = str.substring(begin + 1, s);
  153. if (sa) {
  154. sa.append(last, x);
  155. value = sa.take_string();
  156. } else
  157. value = str.substring(s + 1, x);
  158. begin = x + 1;
  159. }
  160. } else {
  161. const char *x;
  162. for (x = s + 1; x != end && *x != '\n' && *x != '}'; ++x)
  163. if (*x == '\\' && x + 1 != end && x[1] != '\n')
  164. ++x;
  165. if (x != end && *x == '}') {
  166. name = String::make_stable("{}", 2);
  167. begin = x + 1;
  168. }
  169. }
  170. }
  171. if (name_result)
  172. *name_result = name;
  173. if (value_result)
  174. *value_result = value;
  175. return begin;
  176. }
  177. const char *
  178. ErrorHandler::parse_anno(const String &str, const char *begin, const char *end,
  179. ...)
  180. {
  181. const char *names[8];
  182. void *values[8];
  183. int nanno = 0;
  184. va_list val;
  185. va_start(val, end);
  186. while (const char *n = va_arg(val, const char *)) {
  187. assert(nanno < 8);
  188. names[nanno] = n;
  189. if (n[0] == '#')
  190. values[nanno] = va_arg(val, int *);
  191. else
  192. values[nanno] = va_arg(val, String *);
  193. ++nanno;
  194. }
  195. String name, value;
  196. while (1) {
  197. begin = skip_anno(str, begin, end, &name, &value, false);
  198. if (!name)
  199. break;
  200. for (int i = 0; i < nanno; ++i)
  201. if (names[i][0] == '#') {
  202. if (name == (names[i] + 1))
  203. parse_level(value.begin(), value.end(), (int *) values[i]);
  204. } else {
  205. if (name == names[i])
  206. *(String *) values[i] = value;
  207. }
  208. }
  209. return begin;
  210. }
  211. String
  212. ErrorHandler::combine_anno(const String &text, const String &anno)
  213. {
  214. if (!anno)
  215. return text;
  216. String names[8], values[8];
  217. int nanno = 0;
  218. const char *abegin = anno.begin();
  219. while (abegin != anno.end()) {
  220. assert(nanno < 8);
  221. abegin = skip_anno(anno, abegin, anno.end(), &names[nanno], &values[nanno], true);
  222. if (names[nanno])
  223. ++nanno;
  224. else
  225. break;
  226. }
  227. const char *last = text.begin(), *s = last;
  228. String name;
  229. StringAccum sa;
  230. while (s != text.end()) {
  231. const char *line = s;
  232. uint32_t mask = (1U << nanno) - 1;
  233. while (1) {
  234. s = skip_anno(text, s, text.end(), &name, 0, false);
  235. if (!name)
  236. break;
  237. for (int i = 0; i < nanno; ++i)
  238. if (name == names[i])
  239. mask &= ~(1U << i);
  240. }
  241. if (mask) {
  242. sa.append(last, line);
  243. for (int i = 0; i < nanno; ++i)
  244. if (mask & (1U << i)) {
  245. if (names[i].equals("<>", 2))
  246. sa << '<' << values[i] << '>';
  247. else
  248. sa << '{' << names[i] << ':' << values[i] << '}';
  249. }
  250. last = line;
  251. }
  252. if (abegin != anno.end()) {
  253. sa.append(last, s);
  254. sa.append(abegin, anno.end());
  255. last = s;
  256. }
  257. while (s != text.end() && *s != '\n')
  258. ++s;
  259. if (s != text.end())
  260. ++s;
  261. }
  262. if (sa) {
  263. sa.append(last, text.end());
  264. return sa.take_string();
  265. } else
  266. return text;
  267. }
  268. String
  269. ErrorHandler::clean_landmark(const String &landmark, bool with_colon)
  270. {
  271. const char *end = landmark.end();
  272. while (end != landmark.begin() && isspace((unsigned char) end[-1]))
  273. --end;
  274. if (end != landmark.begin() && end[-1] == ':')
  275. --end;
  276. if (end == landmark.begin())
  277. return String();
  278. else if (with_colon)
  279. return landmark.substring(landmark.begin(), end) + ": ";
  280. else
  281. return landmark.substring(landmark.begin(), end);
  282. }
  283. // FORMATTING
  284. #define NUMBUF_SIZE 128
  285. #define ErrH ErrorHandler
  286. static char *
  287. do_number(unsigned long num, char *after_last, int base, int flags)
  288. {
  289. const char *digits =
  290. ((flags & ErrH::cf_uppercase) ? "0123456789ABCDEF" : "0123456789abcdef");
  291. char *pos = after_last;
  292. while (num) {
  293. *--pos = digits[num % base];
  294. num /= base;
  295. }
  296. if (pos == after_last)
  297. *--pos = '0';
  298. return pos;
  299. }
  300. static char *
  301. do_number_flags(char *pos, char *after_last, int base, int flags,
  302. int precision, int field_width)
  303. {
  304. // remove cf_alternate_form for zero results in base 16
  305. if ((flags & ErrH::cf_alternate_form) && base == 16 && *pos == '0')
  306. flags &= ~ErrH::cf_alternate_form;
  307. // account for zero padding
  308. if (precision >= 0)
  309. while (after_last - pos < precision)
  310. *--pos = '0';
  311. else if (flags & ErrH::cf_zero_pad) {
  312. if ((flags & ErrH::cf_alternate_form) && base == 16)
  313. field_width -= 2;
  314. if ((flags & ErrH::cf_negative)
  315. || (flags & (ErrH::cf_plus_positive | ErrH::cf_space_positive)))
  316. field_width--;
  317. while (after_last - pos < field_width)
  318. *--pos = '0';
  319. }
  320. // alternate forms
  321. if ((flags & ErrH::cf_alternate_form) && base == 8 && pos[1] != '0')
  322. *--pos = '0';
  323. else if ((flags & ErrH::cf_alternate_form) && base == 16) {
  324. *--pos = ((flags & ErrH::cf_uppercase) ? 'X' : 'x');
  325. *--pos = '0';
  326. }
  327. // sign
  328. if (flags & ErrH::cf_negative)
  329. *--pos = '-';
  330. else if (flags & ErrH::cf_plus_positive)
  331. *--pos = '+';
  332. else if (flags & ErrH::cf_space_positive)
  333. *--pos = ' ';
  334. return pos;
  335. }
  336. String
  337. ErrorHandler::vxformat(int default_flags, const char *s, va_list val)
  338. {
  339. StringAccum msg;
  340. char numbuf[NUMBUF_SIZE]; // for numerics
  341. numbuf[NUMBUF_SIZE-1] = 0;
  342. String strstore; // to ensure temporaries aren't destroyed
  343. // declare and initialize these here to make gcc shut up about possible
  344. // use before initialization
  345. int flags = 0;
  346. int field_width = -1;
  347. int precision = -1;
  348. int width_flag = 0;
  349. int base = 10;
  350. while (1) {
  351. const char *pct = strchr(s, '%');
  352. if (!pct) {
  353. if (*s)
  354. msg << s;
  355. break;
  356. }
  357. if (pct != s) {
  358. msg.append(s, pct - s);
  359. s = pct;
  360. }
  361. // parse flags
  362. flags = default_flags;
  363. flags:
  364. switch (*++s) {
  365. case '#': flags |= cf_alternate_form; goto flags;
  366. case '0': flags |= cf_zero_pad; goto flags;
  367. case '-': flags |= cf_left_just; goto flags;
  368. case ' ': flags |= cf_space_positive; goto flags;
  369. case '+': flags |= cf_plus_positive; goto flags;
  370. case '\'': flags |= cf_singlequote; goto flags;
  371. case '_': flags &= ~cf_utf8; goto flags;
  372. }
  373. // parse field width
  374. field_width = -1;
  375. if (*s == '*') {
  376. field_width = va_arg(val, int);
  377. if (field_width < 0) {
  378. field_width = -field_width;
  379. flags |= cf_left_just;
  380. }
  381. s++;
  382. } else if (*s >= '0' && *s <= '9')
  383. for (field_width = 0; *s >= '0' && *s <= '9'; s++)
  384. field_width = 10*field_width + *s - '0';
  385. // parse precision
  386. precision = -1;
  387. if (*s == '.') {
  388. s++;
  389. precision = 0;
  390. if (*s == '*') {
  391. precision = va_arg(val, int);
  392. s++;
  393. } else if (*s >= '0' && *s <= '9')
  394. for (; *s >= '0' && *s <= '9'; s++)
  395. precision = 10*precision + *s - '0';
  396. }
  397. // parse width flags
  398. width_flag = 0;
  399. width_flags:
  400. switch (*s) {
  401. case 'h': case 'l':
  402. if (width_flag == *s)
  403. width_flag = *s + 'A' - 'a';
  404. else if (width_flag)
  405. break;
  406. else
  407. width_flag = *s;
  408. s++;
  409. goto width_flags;
  410. case 'z':
  411. if (width_flag)
  412. break;
  413. width_flag = *s++;
  414. break;
  415. case '^':
  416. if (!isdigit((unsigned char) s[1]) || width_flag)
  417. break;
  418. for (s++; isdigit((unsigned char) *s); s++)
  419. width_flag = width_flag * 10 + *s - '0';
  420. width_flag = -width_flag;
  421. break;
  422. }
  423. // conversion character
  424. // after switch, data lies between `s1' and `s2'
  425. const char *s1 = 0, *s2 = 0;
  426. base = 10;
  427. switch (*s++) {
  428. case 's': {
  429. s1 = va_arg(val, const char *);
  430. if (!s1)
  431. s1 = "(null)";
  432. // fetch length
  433. int len;
  434. if (precision < 0)
  435. len = strlen(s1);
  436. else {
  437. #if HAVE_STRNLEN
  438. len = strnlen(s1, precision);
  439. #else
  440. for (len = 0; len < precision && s1[len] != 0; ++len)
  441. /* do nothing */;
  442. #endif
  443. }
  444. // transform string if alternate form
  445. if (flags & cf_alternate_form) {
  446. strstore = String(s1, len).printable();
  447. if (precision < 0 || strstore.length() < precision)
  448. len = strstore.length();
  449. }
  450. // quote characters that look like annotations, readjusting length
  451. if (flags & (cf_singlequote | cf_alternate_form)) {
  452. if (!(flags & cf_alternate_form))
  453. strstore = String(s1, len);
  454. // check first line, considering trailing part of 'msg'
  455. const char *mbegin = msg.end();
  456. while (mbegin != msg.begin() && mbegin[-1] != '\n')
  457. --mbegin;
  458. if (skip_anno(strstore.begin(), strstore.end()) != strstore.begin()
  459. && skip_anno(mbegin, msg.end()) == msg.end()) {
  460. strstore = String::make_stable("{}", 2) + strstore;
  461. len += 2;
  462. }
  463. // check subsequent lines
  464. const char *s = find(strstore.begin(), strstore.end(), '\n');
  465. while (s != strstore.end() && s + 1 != strstore.end()) {
  466. size_t nextpos = (s + 1) - strstore.begin();
  467. if (skip_anno(s + 1, strstore.end()) != s + 1) {
  468. strstore = strstore.substring(strstore.begin(), s + 1)
  469. + String::make_stable("{}", 2)
  470. + strstore.substring(s + 1, strstore.end());
  471. len += 2;
  472. }
  473. s = find(strstore.begin() + nextpos, strstore.end(), '\n');
  474. }
  475. }
  476. // obtain begin and end pointers
  477. if (flags & (cf_singlequote | cf_alternate_form))
  478. s1 = strstore.begin();
  479. s2 = s1 + len;
  480. break;
  481. }
  482. case 'c': {
  483. int c = va_arg(val, int);
  484. // check for extension of 'signed char' to 'int'
  485. if (c < 0)
  486. c += 256;
  487. // assume ASCII
  488. if (c == '\n')
  489. strcpy(numbuf, "\\n");
  490. else if (c == '\t')
  491. strcpy(numbuf, "\\t");
  492. else if (c == '\r')
  493. strcpy(numbuf, "\\r");
  494. else if (c == '\0')
  495. strcpy(numbuf, "\\0");
  496. else if (c < 0 || c >= 256)
  497. strcpy(numbuf, "(bad char)");
  498. else if (c < 32 || c >= 0177)
  499. sprintf(numbuf, "\\%03o", c);
  500. else
  501. sprintf(numbuf, "%c", c);
  502. s1 = numbuf;
  503. s2 = strchr(numbuf, 0);
  504. break;
  505. }
  506. case '%': {
  507. numbuf[0] = '%';
  508. s1 = numbuf;
  509. s2 = s1 + 1;
  510. break;
  511. }
  512. case '<':
  513. s1 = (flags & cf_utf8 ? "\342\200\230" : "\'");
  514. s2 = s1 + strlen(s1);
  515. break;
  516. case '>':
  517. case ',':
  518. s1 = (flags & cf_utf8 ? "\342\200\231" : "\'");
  519. s2 = s1 + strlen(s1);
  520. break;
  521. case 'd':
  522. case 'i':
  523. flags |= cf_signed;
  524. case 'u':
  525. number: {
  526. // protect numbuf from overflow
  527. if (field_width > NUMBUF_SIZE)
  528. field_width = NUMBUF_SIZE;
  529. if (precision > NUMBUF_SIZE - 4)
  530. precision = NUMBUF_SIZE - 4;
  531. s2 = numbuf + NUMBUF_SIZE;
  532. unsigned long num;
  533. switch (width_flag) {
  534. case 'H':
  535. case -8:
  536. num = (unsigned char) va_arg(val, int);
  537. if ((flags & cf_signed) && (signed char) num < 0)
  538. num = -(signed char) num, flags |= cf_negative;
  539. break;
  540. case 'h':
  541. case -16:
  542. num = (unsigned short) va_arg(val, int);
  543. if ((flags & cf_signed) && (short) num < 0)
  544. num = -(short) num, flags |= cf_negative;
  545. break;
  546. case 0:
  547. case -32:
  548. #if SIZEOF_LONG == 4
  549. case 'l':
  550. #endif
  551. #if SIZEOF_SIZE_T == 4
  552. case 'z':
  553. #endif
  554. num = va_arg(val, unsigned);
  555. if ((flags & cf_signed) && (int) num < 0)
  556. num = -(int) num, flags |= cf_negative;
  557. break;
  558. #if HAVE_INT64_TYPES
  559. # if SIZEOF_LONG == 8
  560. case 'l':
  561. # endif
  562. # if SIZEOF_LONG_LONG == 8
  563. case 'L':
  564. # endif
  565. # if SIZEOF_SIZE_T == 8
  566. case 'z':
  567. # endif
  568. case -64: {
  569. uint64_t qnum = va_arg(val, uint64_t);
  570. if ((flags & cf_signed) && (int64_t)qnum < 0)
  571. qnum = -(int64_t) qnum, flags |= cf_negative;
  572. StringAccum sa;
  573. sa.append_numeric(static_cast<String::uintmax_t>(qnum), base, (flags & cf_uppercase));
  574. s1 = s2 - sa.length();
  575. memcpy(const_cast<char*>(s1), sa.data(), s2 - s1);
  576. goto got_number;
  577. }
  578. #endif
  579. default:
  580. goto error;
  581. }
  582. s1 = do_number(num, (char *)s2, base, flags);
  583. #if HAVE_INT64_TYPES
  584. got_number:
  585. #endif
  586. s1 = do_number_flags((char *)s1, (char *)s2, base, flags,
  587. precision, field_width);
  588. break;
  589. }
  590. case 'o':
  591. base = 8;
  592. goto number;
  593. case 'X':
  594. flags |= cf_uppercase;
  595. case 'x':
  596. base = 16;
  597. goto number;
  598. case 'p': {
  599. if (*s == '{') {
  600. s1 = s2 = s + 1;
  601. while (*s2 && *s2 != '}' && !isspace((unsigned char) *s2))
  602. ++s2;
  603. if (*s2 == '}')
  604. goto braces;
  605. }
  606. void *v = va_arg(val, void *);
  607. s2 = numbuf + NUMBUF_SIZE;
  608. s1 = do_number((unsigned long)v, (char *)s2, 16, flags);
  609. s1 = do_number_flags((char *)s1, (char *)s2, 16, flags | cf_alternate_form,
  610. precision, field_width);
  611. break;
  612. }
  613. #if HAVE_FLOAT_TYPES
  614. case 'e': case 'f': case 'g':
  615. case 'E': case 'F': case 'G': {
  616. char format[80], *f = format, new_numbuf[NUMBUF_SIZE];
  617. *f++ = '%';
  618. if (flags & cf_alternate_form)
  619. *f++ = '#';
  620. if (precision >= 0)
  621. f += sprintf(f, ".%d", precision);
  622. *f++ = s[-1];
  623. *f++ = 0;
  624. int len = sprintf(new_numbuf, format, va_arg(val, double));
  625. s2 = numbuf + NUMBUF_SIZE;
  626. s1 = s2 - len;
  627. memcpy((char *)s1, new_numbuf, len); // note: no terminating \0
  628. s1 = do_number_flags((char *)s1, (char *)s2, 10, flags & ~cf_alternate_form, -1, field_width);
  629. break;
  630. }
  631. #endif
  632. case '{':
  633. s1 = s2 = s;
  634. while (*s2 && *s2 != '}' && !isspace((unsigned char) *s2))
  635. ++s2;
  636. if (*s2 != '}')
  637. goto error;
  638. goto braces;
  639. braces:
  640. s = s2 + 1;
  641. for (Conversion *item = error_items; item; item = item->next)
  642. if (item->name.equals(s1, s2 - s1)) {
  643. strstore = item->hook(flags, VA_LIST_REF(val));
  644. s1 = strstore.begin();
  645. s2 = strstore.end();
  646. goto got_result;
  647. }
  648. goto error;
  649. error:
  650. default:
  651. assert(0 /* Bad % in error */);
  652. break;
  653. }
  654. // add result of conversion
  655. got_result:
  656. int slen = s2 - s1;
  657. if (slen > field_width)
  658. field_width = slen;
  659. char *dest = msg.extend(field_width);
  660. if (flags & cf_left_just) {
  661. memcpy(dest, s1, slen);
  662. memset(dest + slen, ' ', field_width - slen);
  663. } else {
  664. memcpy(dest + field_width - slen, s1, slen);
  665. memset(dest, (flags & cf_zero_pad ? '0' : ' '), field_width - slen);
  666. }
  667. }
  668. return msg.take_string();
  669. }
  670. String
  671. ErrorHandler::xformat(int default_flags, const char *fmt, ...)
  672. {
  673. va_list val;
  674. va_start(val, fmt);
  675. String s = vxformat(default_flags, fmt, val);
  676. va_end(val);
  677. return s;
  678. }
  679. String
  680. ErrorHandler::xformat(const char *fmt, ...)
  681. {
  682. va_list val;
  683. va_start(val, fmt);
  684. String s = vxformat(0, fmt, val);
  685. va_end(val);
  686. return s;
  687. }
  688. String
  689. ErrorHandler::format(const char *fmt, ...)
  690. {
  691. va_list val;
  692. va_start(val, fmt);
  693. String s = vformat(fmt, val);
  694. va_end(val);
  695. return s;
  696. }
  697. // ERROR MESSAGE SHORTHAND
  698. void
  699. ErrorHandler::debug(const char *fmt, ...)
  700. {
  701. va_list val;
  702. va_start(val, fmt);
  703. xmessage(String::make_stable(e_debug, 3), fmt, val);
  704. va_end(val);
  705. }
  706. void
  707. ErrorHandler::message(const char *fmt, ...)
  708. {
  709. va_list val;
  710. va_start(val, fmt);
  711. xmessage(String::make_stable(e_info, 3), fmt, val);
  712. va_end(val);
  713. }
  714. int
  715. ErrorHandler::warning(const char *fmt, ...)
  716. {
  717. va_list val;
  718. va_start(val, fmt);
  719. int r = xmessage(String::make_stable(e_warning_annotated, 12), fmt, val);
  720. va_end(val);
  721. return r;
  722. }
  723. int
  724. ErrorHandler::error(const char *fmt, ...)
  725. {
  726. va_list val;
  727. va_start(val, fmt);
  728. int r = xmessage(String::make_stable(e_error, 3), fmt, val);
  729. va_end(val);
  730. return r;
  731. }
  732. int
  733. ErrorHandler::fatal(const char *fmt, ...)
  734. {
  735. va_list val;
  736. va_start(val, fmt);
  737. int r = xmessage(String::make_stable(e_fatal, 4), fmt, val);
  738. va_end(val);
  739. return r;
  740. }
  741. void
  742. ErrorHandler::ldebug(const String &landmark, const char *fmt, ...)
  743. {
  744. va_list val;
  745. va_start(val, fmt);
  746. String l = make_landmark_anno(landmark);
  747. xmessage(String::make_stable(e_debug, 3) + l, fmt, val);
  748. va_end(val);
  749. }
  750. void
  751. ErrorHandler::lmessage(const String &landmark, const char *fmt, ...)
  752. {
  753. va_list val;
  754. va_start(val, fmt);
  755. String l = make_landmark_anno(landmark);
  756. xmessage(String::make_stable(e_info, 3) + l, fmt, val);
  757. va_end(val);
  758. }
  759. int
  760. ErrorHandler::lwarning(const String &landmark, const char *fmt, ...)
  761. {
  762. va_list val;
  763. va_start(val, fmt);
  764. String l = make_landmark_anno(landmark);
  765. int r = xmessage(l + String::make_stable(e_warning_annotated, 12), fmt, val);
  766. va_end(val);
  767. return r;
  768. }
  769. int
  770. ErrorHandler::lerror(const String &landmark, const char *fmt, ...)
  771. {
  772. va_list val;
  773. va_start(val, fmt);
  774. String l = make_landmark_anno(landmark);
  775. int r = xmessage(String::make_stable(e_error, 3) + l, fmt, val);
  776. va_end(val);
  777. return r;
  778. }
  779. int
  780. ErrorHandler::lfatal(const String &landmark, const char *fmt, ...)
  781. {
  782. va_list val;
  783. va_start(val, fmt);
  784. String l = make_landmark_anno(landmark);
  785. int r = xmessage(String::make_stable(e_fatal, 4) + l, fmt, val);
  786. va_end(val);
  787. return r;
  788. }
  789. int
  790. ErrorHandler::xmessage(const String &str)
  791. {
  792. String xstr = decorate(str);
  793. int min_level = 1000, xlevel = 1000;
  794. const char *s = xstr.begin(), *end = xstr.end();
  795. void *user_data = 0;
  796. while (s != end) {
  797. const char *l = parse_anno(xstr, s, end, "#<>", &xlevel,
  798. (const char *) 0);
  799. const char *nl = find(l, end, '\n');
  800. String line = xstr.substring(s, nl);
  801. s = nl + (nl != end);
  802. user_data = emit(line, user_data, s != end);
  803. min_level = (xlevel < min_level ? xlevel : min_level);
  804. }
  805. account(min_level);
  806. return (min_level <= el_warning ? error_result : ok_result);
  807. }
  808. String
  809. ErrorHandler::vformat(const char *fmt, va_list val)
  810. {
  811. return vxformat(0, fmt, val);
  812. }
  813. String
  814. ErrorHandler::decorate(const String &str)
  815. {
  816. return str;
  817. }
  818. void *
  819. ErrorHandler::emit(const String &, void *user_data, bool)
  820. {
  821. return user_data;
  822. }
  823. #if defined(CLICK_USERLEVEL) || defined(CLICK_TOOL)
  824. //
  825. // FILE ERROR HANDLER
  826. //
  827. FileErrorHandler::FileErrorHandler(FILE *f, const String &context)
  828. : _f(f), _context(context), _default_flags(0)
  829. {
  830. if (isatty(fileno(_f))) {
  831. char *s = getenv("LANG");
  832. if (s && (strstr(s, "UTF-8") != 0 || strstr(s, "UTF8") != 0
  833. || strstr(s, "utf8") != 0))
  834. _default_flags |= cf_utf8;
  835. }
  836. }
  837. String
  838. FileErrorHandler::vformat(const char *fmt, va_list val)
  839. {
  840. return vxformat(_default_flags, fmt, val);
  841. }
  842. void *
  843. FileErrorHandler::emit(const String &str, void *, bool)
  844. {
  845. String landmark;
  846. const char *s = parse_anno(str, str.begin(), str.end(),
  847. "l", &landmark, (const char *) 0);
  848. StringAccum sa;
  849. sa << _context << clean_landmark(landmark, true)
  850. << str.substring(s, str.end()) << '\n';
  851. ignore_result(fwrite(sa.begin(), 1, sa.length(), _f));
  852. return 0;
  853. }
  854. void
  855. FileErrorHandler::account(int level)
  856. {
  857. ErrorHandler::account(level);
  858. if (level <= el_abort)
  859. abort();
  860. else if (level <= el_fatal)
  861. exit(-level);
  862. }
  863. #endif
  864. //
  865. // STATIC ERROR HANDLERS
  866. //
  867. ErrorHandler::Conversion *
  868. ErrorHandler::add_conversion(const String &name, ConversionFunction function)
  869. {
  870. if (Conversion *c = new Conversion) {
  871. c->name = name;
  872. c->hook = function;
  873. c->next = error_items;
  874. error_items = c;
  875. return c;
  876. } else
  877. return 0;
  878. }
  879. int
  880. ErrorHandler::remove_conversion(ErrorHandler::Conversion *conv)
  881. {
  882. Conversion **pprev = &error_items;
  883. for (Conversion *c = error_items; c; pprev = &c->next, c = *pprev)
  884. if (c == conv) {
  885. *pprev = c->next;
  886. delete c;
  887. return 0;
  888. }
  889. return -1;
  890. }
  891. static String
  892. timeval_error_hook(int, VA_LIST_REF_T val)
  893. {
  894. const struct timeval *tvp = va_arg(VA_LIST_DEREF(val), const struct timeval *);
  895. if (tvp) {
  896. StringAccum sa;
  897. sa << *tvp;
  898. return sa.take_string();
  899. } else
  900. return String::make_stable("(null)", 6);
  901. }
  902. static String
  903. timestamp_error_hook(int, VA_LIST_REF_T val)
  904. {
  905. const Timestamp *tsp = va_arg(VA_LIST_DEREF(val), const Timestamp *);
  906. if (tsp) {
  907. StringAccum sa;
  908. sa << *tsp;
  909. return sa.take_string();
  910. } else
  911. return String::make_stable("(null)", 6);
  912. }
  913. static String
  914. ip_ptr_error_hook(int, VA_LIST_REF_T val)
  915. {
  916. const IPAddress *ipp = va_arg(VA_LIST_DEREF(val), const IPAddress *);
  917. if (ipp)
  918. return ipp->unparse();
  919. else
  920. return String::make_stable("(null)", 6);
  921. }
  922. static String
  923. ether_ptr_error_hook(int, VA_LIST_REF_T val)
  924. {
  925. const EtherAddress *ethp = va_arg(VA_LIST_DEREF(val), const EtherAddress *);
  926. if (ethp)
  927. return ethp->unparse();
  928. else
  929. return String::make_stable("(null)", 6);
  930. }
  931. #ifndef CLICK_TOOL
  932. static String
  933. element_error_hook(int, VA_LIST_REF_T val)
  934. {
  935. const Element *e = va_arg(VA_LIST_DEREF(val), const Element *);
  936. if (e)
  937. return e->declaration();
  938. else
  939. return String::make_stable("(null)", 6);
  940. }
  941. #endif
  942. ErrorHandler *
  943. ErrorHandler::static_initialize(ErrorHandler *default_handler)
  944. {
  945. if (!the_silent_handler) {
  946. the_default_handler = default_handler;
  947. the_silent_handler = new SilentErrorHandler;
  948. add_conversion("timeval", timeval_error_hook);
  949. add_conversion("timestamp", timestamp_error_hook);
  950. #ifndef CLICK_TOOL
  951. add_conversion("element", element_error_hook);
  952. #endif
  953. add_conversion("ip_ptr", ip_ptr_error_hook);
  954. add_conversion("ether_ptr", ether_ptr_error_hook);
  955. }
  956. return default_handler;
  957. }
  958. void
  959. ErrorHandler::static_cleanup()
  960. {
  961. delete the_default_handler;
  962. delete the_silent_handler;
  963. the_default_handler = the_silent_handler = 0;
  964. while (error_items) {
  965. Conversion *next = error_items->next;
  966. delete error_items;
  967. error_items = next;
  968. }
  969. }
  970. void
  971. ErrorHandler::set_default_handler(ErrorHandler *errh)
  972. {
  973. the_default_handler = errh;
  974. }
  975. //
  976. // ERROR VENEER
  977. //
  978. String
  979. ErrorVeneer::vformat(const char *fmt, va_list val)
  980. {
  981. if (_errh)
  982. return _errh->vformat(fmt, val);
  983. else
  984. return ErrorHandler::vformat(fmt, val);
  985. }
  986. String
  987. ErrorVeneer::decorate(const String &str)
  988. {
  989. if (_errh)
  990. return _errh->decorate(str);
  991. else
  992. return ErrorHandler::decorate(str);
  993. }
  994. void *
  995. ErrorVeneer::emit(const String &str, void *user_data, bool more)
  996. {
  997. if (_errh)
  998. return _errh->emit(str, user_data, more);
  999. else
  1000. return ErrorHandler::emit(str, user_data, more);
  1001. }
  1002. void
  1003. ErrorVeneer::account(int level)
  1004. {
  1005. ErrorHandler::account(level);
  1006. if (_errh)
  1007. _errh->account(level);
  1008. }
  1009. //
  1010. // CONTEXT ERROR HANDLER
  1011. //
  1012. ContextErrorHandler::ContextErrorHandler(ErrorHandler *errh, const char *fmt,
  1013. ...)
  1014. : ErrorVeneer(errh), _indent(String::make_stable(" ", 2)),
  1015. _context_printed(false)
  1016. {
  1017. va_list val;
  1018. va_start(val, fmt);
  1019. _context = ErrorVeneer::vformat(fmt, val);
  1020. va_end(val);
  1021. if (_context)
  1022. _context = combine_anno(_context, String::make_stable("{context:context}", 17));
  1023. }
  1024. String
  1025. ContextErrorHandler::decorate(const String &str)
  1026. {
  1027. String context_anno;
  1028. const char *str_endanno = parse_anno(str, str.begin(), str.end(),
  1029. "context", &context_anno,
  1030. (const char *) 0);
  1031. if (context_anno.equals("no", 2))
  1032. return ErrorVeneer::decorate(str);
  1033. String istr;
  1034. if (context_anno.equals("noindent", 8))
  1035. istr = combine_anno(str, _context_landmark);
  1036. else
  1037. istr = combine_anno(str, _context_landmark + _indent);
  1038. if (!_context_printed && !context_anno.equals("nocontext", 9)) {
  1039. String astr = combine_anno(combine_anno(_context, _context_landmark),
  1040. str.substring(str.begin(), str_endanno));
  1041. if (astr && astr.back() != '\n')
  1042. astr += '\n';
  1043. _context_printed = true;
  1044. return ErrorVeneer::decorate(astr + istr);
  1045. } else
  1046. return ErrorVeneer::decorate(istr);
  1047. }
  1048. //
  1049. // PREFIX ERROR HANDLER
  1050. //
  1051. PrefixErrorHandler::PrefixErrorHandler(ErrorHandler *errh,
  1052. const String &prefix)
  1053. : ErrorVeneer(errh), _prefix(prefix)
  1054. {
  1055. }
  1056. String
  1057. PrefixErrorHandler::decorate(const String &str)
  1058. {
  1059. return ErrorVeneer::decorate(combine_anno(str, _prefix));
  1060. }
  1061. //
  1062. // LANDMARK ERROR HANDLER
  1063. //
  1064. LandmarkErrorHandler::LandmarkErrorHandler(ErrorHandler *errh, const String &landmark)
  1065. : ErrorVeneer(errh), _landmark(make_landmark_anno(landmark))
  1066. {
  1067. }
  1068. String
  1069. LandmarkErrorHandler::decorate(const String &str)
  1070. {
  1071. return ErrorVeneer::decorate(combine_anno(str, _landmark));
  1072. }
  1073. //
  1074. // BAIL ERROR HANDLER
  1075. //
  1076. #if defined(CLICK_USERLEVEL) || defined(CLICK_TOOL)
  1077. BailErrorHandler::BailErrorHandler(ErrorHandler *errh, int l)
  1078. : ErrorVeneer(errh), _level(l)
  1079. {
  1080. }
  1081. void
  1082. BailErrorHandler::account(int level)
  1083. {
  1084. ErrorVeneer::account(level);
  1085. if (level <= _level)
  1086. exit(1);
  1087. }
  1088. #endif
  1089. CLICK_ENDDECLS