diff options
Diffstat (limited to 'src/item.cc')
-rw-r--r-- | src/item.cc | 162 |
1 files changed, 90 insertions, 72 deletions
diff --git a/src/item.cc b/src/item.cc index 6a948ae4..f59c9e29 100644 --- a/src/item.cc +++ b/src/item.cc @@ -58,22 +58,22 @@ bool item_t::has_tag(const string& tag) const } bool item_t::has_tag(const mask_t& tag_mask, - const optional<mask_t>& value_mask) const + const optional<mask_t>& value_mask) const { if (metadata) { foreach (const string_map::value_type& data, *metadata) { if (tag_mask.match(data.first)) { - if (! value_mask) - return true; - else if (data.second.first) - return value_mask->match(*data.second.first); + if (! value_mask) + return true; + else if (data.second.first) + return value_mask->match(data.second.first->to_string()); } } } return false; } -optional<string> item_t::get_tag(const string& tag) const +optional<value_t> item_t::get_tag(const string& tag) const { DEBUG("item.meta", "Getting item tag: " << tag); if (metadata) { @@ -87,24 +87,26 @@ optional<string> item_t::get_tag(const string& tag) const return none; } -optional<string> item_t::get_tag(const mask_t& tag_mask, - const optional<mask_t>& value_mask) const +optional<value_t> item_t::get_tag(const mask_t& tag_mask, + const optional<mask_t>& value_mask) const { if (metadata) { foreach (const string_map::value_type& data, *metadata) { if (tag_mask.match(data.first) && - (! value_mask || - (data.second.first && value_mask->match(*data.second.first)))) - return data.second.first; + (! value_mask || + (data.second.first && + value_mask->match(data.second.first->to_string())))) { + return data.second.first; + } } } return none; } item_t::string_map::iterator -item_t::set_tag(const string& tag, - const optional<string>& value, - const bool overwrite_existing) +item_t::set_tag(const string& tag, + const optional<value_t>& value, + const bool overwrite_existing) { assert(! tag.empty()); @@ -112,10 +114,12 @@ item_t::set_tag(const string& tag, metadata = string_map(); DEBUG("item.meta", "Setting tag '" << tag << "' to value '" - << (value ? *value : string("<none>")) << "'"); + << (value ? *value : string_value("<none>")) << "'"); - optional<string> data = value; - if (data && data->empty()) + optional<value_t> data = value; + if (data && + (data->is_null() || + (data->is_string() && data->as_string().empty()))) data = none; string_map::iterator i = metadata->find(tag); @@ -131,23 +135,25 @@ item_t::set_tag(const string& tag, } } -void item_t::parse_tags(const char * p, bool overwrite_existing, - optional<date_t::year_type> current_year) +void item_t::parse_tags(const char * p, + scope_t& scope, + bool overwrite_existing, + optional<date_t::year_type> current_year) { if (const char * b = std::strchr(p, '[')) { if (*(b + 1) != '\0' && - (std::isdigit(*(b + 1)) || *(b + 1) == '=')) { + (std::isdigit(*(b + 1)) || *(b + 1) == '=')) { if (const char * e = std::strchr(p, ']')) { - char buf[256]; - std::strncpy(buf, b + 1, e - b - 1); - buf[e - b - 1] = '\0'; - - if (char * p = std::strchr(buf, '=')) { - *p++ = '\0'; - _date_eff = parse_date(p, current_year); - } - if (buf[0]) - _date = parse_date(buf, current_year); + char buf[256]; + std::strncpy(buf, b + 1, e - b - 1); + buf[e - b - 1] = '\0'; + + if (char * p = std::strchr(buf, '=')) { + *p++ = '\0'; + _date_eff = parse_date(p, current_year); + } + if (buf[0]) + _date = parse_date(buf, current_year); } } } @@ -160,32 +166,47 @@ void item_t::parse_tags(const char * p, bool overwrite_existing, std::strcpy(buf.get(), p); string tag; + bool by_value = false; for (char * q = std::strtok(buf.get(), " \t"); q; q = std::strtok(NULL, " \t")) { const string::size_type len = std::strlen(q); + if (len < 2) continue; if (! tag.empty()) { - string_map::iterator i = set_tag(tag, string(p + (q - buf.get())), - overwrite_existing); + string_map::iterator i; + string field(p + (q - buf.get())); + if (by_value) { + bind_scope_t bound_scope(scope, *this); + i = set_tag(tag, expr_t(field).calc(bound_scope), overwrite_existing); + } else { + i = set_tag(tag, string_value(field), overwrite_existing); + } (*i).second.second = true; break; } else if (q[0] == ':' && q[len - 1] == ':') { // a series of tags for (char * r = std::strtok(q + 1, ":"); - r; - r = std::strtok(NULL, ":")) { - string_map::iterator i = set_tag(r, none, overwrite_existing); - (*i).second.second = true; + r; + r = std::strtok(NULL, ":")) { + string_map::iterator i = set_tag(r, none, overwrite_existing); + (*i).second.second = true; } } else if (q[len - 1] == ':') { // a metadata setting - tag = string(q, len - 1); + int index = 1; + if (q[len - 2] == ':') { + by_value = true; + index = 2; + } + tag = string(q, len - index); } } } -void item_t::append_note(const char * p, bool overwrite_existing, - optional<date_t::year_type> current_year) +void item_t::append_note(const char * p, + scope_t& scope, + bool overwrite_existing, + optional<date_t::year_type> current_year) { if (note) { *note += '\n'; @@ -194,7 +215,7 @@ void item_t::append_note(const char * p, bool overwrite_existing, note = p; } - parse_tags(p, overwrite_existing, current_year); + parse_tags(p, scope, overwrite_existing, current_year); } namespace { @@ -235,21 +256,21 @@ namespace { if (args.size() == 1) { if (args[0].is_string()) - return item.has_tag(args[0].as_string()); + return item.has_tag(args[0].as_string()); else if (args[0].is_mask()) - return item.has_tag(args[0].as_mask()); + return item.has_tag(args[0].as_mask()); else - throw_(std::runtime_error, - _("Expected string or mask for argument 1, but received %1") - << args[0].label()); + throw_(std::runtime_error, + _("Expected string or mask for argument 1, but received %1") + << args[0].label()); } else if (args.size() == 2) { if (args[0].is_mask() && args[1].is_mask()) - return item.has_tag(args[0].to_mask(), args[1].to_mask()); + return item.has_tag(args[0].to_mask(), args[1].to_mask()); else - throw_(std::runtime_error, - _("Expected masks for arguments 1 and 2, but received %1 and %2") - << args[0].label() << args[1].label()); + throw_(std::runtime_error, + _("Expected masks for arguments 1 and 2, but received %1 and %2") + << args[0].label() << args[1].label()); } else if (args.size() == 0) { throw_(std::runtime_error, _("Too few arguments to function")); @@ -263,25 +284,25 @@ namespace { value_t get_tag(call_scope_t& args) { item_t& item(find_scope<item_t>(args)); - optional<string> str; + optional<value_t> val; if (args.size() == 1) { if (args[0].is_string()) - str = item.get_tag(args[0].as_string()); + val = item.get_tag(args[0].as_string()); else if (args[0].is_mask()) - str = item.get_tag(args[0].as_mask()); + val = item.get_tag(args[0].as_mask()); else - throw_(std::runtime_error, - _("Expected string or mask for argument 1, but received %1") - << args[0].label()); + throw_(std::runtime_error, + _("Expected string or mask for argument 1, but received %1") + << args[0].label()); } else if (args.size() == 2) { if (args[0].is_mask() && args[1].is_mask()) - str = item.get_tag(args[0].to_mask(), args[1].to_mask()); + val = item.get_tag(args[0].to_mask(), args[1].to_mask()); else - throw_(std::runtime_error, - _("Expected masks for arguments 1 and 2, but received %1 and %2") - << args[0].label() << args[1].label()); + throw_(std::runtime_error, + _("Expected masks for arguments 1 and 2, but received %1 and %2") + << args[0].label() << args[1].label()); } else if (args.size() == 0) { throw_(std::runtime_error, _("Too few arguments to function")); @@ -290,10 +311,7 @@ namespace { throw_(std::runtime_error, _("Too many arguments to function")); } - if (str) - return string_value(*str); - else - return NULL_VALUE; + return val ? *val : NULL_VALUE; } value_t get_pathname(item_t& item) { @@ -355,13 +373,13 @@ value_t get_comment(item_t& item) bool need_separator = false; for (const char * p = item.note->c_str(); *p; p++) { if (*p == '\n') { - need_separator = true; + need_separator = true; } else { - if (need_separator) { - buf << "\n ;"; - need_separator = false; - } - buf << *p; + if (need_separator) { + buf << "\n ;"; + need_separator = false; + } + buf << *p; } } return string_value(buf.str()); @@ -369,7 +387,7 @@ value_t get_comment(item_t& item) } expr_t::ptr_op_t item_t::lookup(const symbol_t::kind_t kind, - const string& name) + const string& name) { if (kind != symbol_t::FUNCTION) return NULL; @@ -502,7 +520,7 @@ bool item_t::valid() const void print_item(std::ostream& out, const item_t& item, const string& prefix) { out << source_context(item.pos->pathname, item.pos->beg_pos, - item.pos->end_pos, prefix); + item.pos->end_pos, prefix); } string item_context(const item_t& item, const string& desc) @@ -528,7 +546,7 @@ string item_context(const item_t& item, const string& desc) if (item.pos->beg_line != item.pos->end_line) out << _(", lines ") << item.pos->beg_line << "-" - << item.pos->end_line << ":\n"; + << item.pos->end_line << ":\n"; else out << _(", line ") << item.pos->beg_line << ":\n"; |