// See the file "COPYING" in the main distribution directory for copyright. #include "zeek/Obj.h" #include #include "zeek/Desc.h" #include "zeek/File.h" #include "zeek/Func.h" #include "zeek/plugin/Manager.h" namespace zeek { namespace detail { Location start_location("", 0, 0); Location end_location("", 0, 0); void Location::Describe(ODesc* d) const { if ( FileName() ) { d->Add(FileName()); if ( FirstLine() == 0 ) return; d->AddSP(","); } if ( LastLine() != FirstLine() ) { if ( LastLine() < FirstLine() ) reporter->InternalError("Location::Describe: %s inconsistent: last_line %d < first_line %d", FileName(), LastLine(), FirstLine()); d->Add("lines "); d->Add(FirstLine()); d->Add("-"); d->Add(LastLine()); } else { d->Add("line "); d->Add(FirstLine()); } } bool Location::operator==(const Location& l) const { if ( FileName() == l.FileName() || (FileName() && l.FileName() && util::streq(FileName(), l.FileName())) ) return FirstLine() == l.FirstLine() && LastLine() == l.LastLine(); else return false; } } // namespace detail int Obj::suppress_errors = 0; Obj::~Obj() { if ( notify_plugins ) PLUGIN_HOOK_VOID(HOOK_OBJ_DTOR, HookObjDtor(this)); delete location; } void Obj::Warn(const char* msg, const Obj* obj2, bool pinpoint_only, const detail::Location* expr_location) const { ODesc d; DoMsg(&d, msg, obj2, pinpoint_only, expr_location); reporter->Warning("%s", d.Description()); reporter->PopLocation(); } void Obj::Error(const char* msg, const Obj* obj2, bool pinpoint_only, const detail::Location* expr_location) const { if ( suppress_errors ) return; ODesc d; DoMsg(&d, msg, obj2, pinpoint_only, expr_location); reporter->Error("%s", d.Description()); reporter->PopLocation(); } void Obj::BadTag(const char* msg, const char* t1, const char* t2) const { char out[512]; if ( t2 ) snprintf(out, sizeof(out), "%s (%s/%s)", msg, t1, t2); else if ( t1 ) snprintf(out, sizeof(out), "%s (%s)", msg, t1); else snprintf(out, sizeof(out), "%s", msg); ODesc d; DoMsg(&d, out); reporter->FatalErrorWithCore("%s", d.Description()); reporter->PopLocation(); } void Obj::Internal(const char* msg) const { ODesc d; DoMsg(&d, msg); auto rcs = render_call_stack(); if ( rcs.empty() ) reporter->InternalError("%s", d.Description()); else reporter->InternalError("%s, call stack: %s", d.Description(), rcs.data()); reporter->PopLocation(); } void Obj::InternalWarning(const char* msg) const { ODesc d; DoMsg(&d, msg); reporter->InternalWarning("%s", d.Description()); reporter->PopLocation(); } void Obj::AddLocation(ODesc* d) const { if ( ! location ) { d->Add(""); return; } location->Describe(d); } bool Obj::SetLocationInfo(const detail::Location* start, const detail::Location* end) { if ( ! start || ! end ) return false; if ( end->FileName() && ! util::streq(start->FileName(), end->FileName()) ) return false; if ( location && (start == &detail::no_location || end == &detail::no_location) ) // We already have a better location, so don't use this one. return true; auto new_location = new detail::Location(start->FileName(), start->FirstLine(), end->LastLine()); // Don't delete this until we've constructed the new location, in case // "start" or "end" are our own location. delete location; location = new_location; return true; } void Obj::UpdateLocationEndInfo(const detail::Location& end) { if ( ! location ) SetLocationInfo(&end, &end); location->SetLastLine(end.LastLine()); } void Obj::DoMsg(ODesc* d, const char s1[], const Obj* obj2, bool pinpoint_only, const detail::Location* expr_location) const { d->SetShort(); d->Add(s1); PinPoint(d, obj2, pinpoint_only); const detail::Location* loc2 = nullptr; if ( obj2 && obj2->GetLocationInfo() != &detail::no_location && *obj2->GetLocationInfo() != *GetLocationInfo() ) loc2 = obj2->GetLocationInfo(); else if ( expr_location ) loc2 = expr_location; reporter->PushLocation(GetLocationInfo(), loc2); } void Obj::PinPoint(ODesc* d, const Obj* obj2, bool pinpoint_only) const { d->Add(" ("); Describe(d); if ( obj2 && ! pinpoint_only ) { d->Add(" and "); obj2->Describe(d); } d->Add(")"); } void Obj::Print() const { static File fstderr(stderr); ODesc d(DESC_READABLE, &fstderr); Describe(&d); d.Add("\n"); } void bad_ref(int type) { reporter->InternalError("bad reference count [%d]", type); abort(); } void obj_delete_func(void* v) { Unref((Obj*)v); } } // namespace zeek