| 81 | } |
| 82 | |
| 83 | LogFilter * |
| 84 | LogFilter::parse(const char *name, Action action, const char *condition) |
| 85 | { |
| 86 | SimpleTokenizer tok(condition); |
| 87 | std::unique_ptr<LogField> logfield; |
| 88 | |
| 89 | ink_release_assert(action != N_ACTIONS); |
| 90 | |
| 91 | if (tok.getNumTokensRemaining() < 3) { |
| 92 | Error("Invalid condition syntax '%s'; cannot create filter '%s'", condition, name); |
| 93 | return nullptr; |
| 94 | } |
| 95 | |
| 96 | char *field_str = tok.getNext(); |
| 97 | char *oper_str = tok.getNext(); |
| 98 | char *val_str = tok.getRest(); |
| 99 | |
| 100 | // validate field symbol |
| 101 | if (strlen(field_str) > 2 && field_str[0] == '%' && field_str[1] == '<') { |
| 102 | Dbg(dbg_ctl_log, "Field symbol has <> form: %s", field_str); |
| 103 | char *end = field_str; |
| 104 | while (*end && *end != '>') { |
| 105 | end++; |
| 106 | } |
| 107 | *end = '\0'; |
| 108 | field_str += 2; |
| 109 | Dbg(dbg_ctl_log, "... now field symbol is %s", field_str); |
| 110 | } |
| 111 | |
| 112 | if (LogField *f = Log::global_field_list.find_by_symbol(field_str)) { |
| 113 | logfield.reset(new LogField(*f)); |
| 114 | } |
| 115 | |
| 116 | if (!logfield) { |
| 117 | // check for container fields |
| 118 | if (*field_str == '{') { |
| 119 | Dbg(dbg_ctl_log, "%s appears to be a container field", field_str); |
| 120 | |
| 121 | char *fname; |
| 122 | char *cname; |
| 123 | char *fname_end; |
| 124 | |
| 125 | fname_end = strchr(field_str, '}'); |
| 126 | if (nullptr == fname_end) { |
| 127 | Error("Invalid container field specification: no trailing '}' in '%s' cannot create filter '%s'", field_str, name); |
| 128 | return nullptr; |
| 129 | } |
| 130 | |
| 131 | fname = field_str + 1; |
| 132 | *fname_end = 0; // changes '}' to '\0' |
| 133 | |
| 134 | // start of container symbol |
| 135 | cname = fname_end + 1; |
| 136 | |
| 137 | Dbg(dbg_ctl_log, "found container field: Name = %s, symbol = %s", fname, cname); |
| 138 | |
| 139 | LogField::Container container = LogField::valid_container_name(cname); |
| 140 | if (container == LogField::NO_CONTAINER) { |