AstNode *attr = attributes.at(id);
        if (attr->type != AST_CONSTANT)
-               log_error("Attribute `%s' with non-constant value at %s:%d!\n",
-                               id.c_str(), attr->filename.c_str(), attr->linenum);
+               log_file_error(attr->filename, attr->linenum, "Attribute `%s' with non-constant value!\n",
+                              id.c_str());
 
        return attr->integer != 0;
 }
 
                for (auto &attr : ast->attributes) {
                        if (attr.second->type != AST_CONSTANT)
-                               log_error("Attribute `%s' with non-constant value at %s:%d!\n",
-                                               attr.first.c_str(), ast->filename.c_str(), ast->linenum);
+                               log_file_error(ast->filename, ast->linenum, "Attribute `%s' with non-constant value!\n",
+                                              attr.first.c_str());
                        current_module->attributes[attr.first] = attr.second->asAttrConst();
                }
                for (size_t i = 0; i < ast->children.size(); i++) {
                        if (design->has((*it)->str)) {
                                RTLIL::Module *existing_mod = design->module((*it)->str);
                                if (!nooverwrite && !overwrite && !existing_mod->get_bool_attribute("\\blackbox")) {
-                                       log_error("Re-definition of module `%s' at %s:%d!\n",
-                                                       (*it)->str.c_str(), (*it)->filename.c_str(), (*it)->linenum);
+                                       log_file_error((*it)->filename, (*it)->linenum, "Re-definition of module `%s'!\n",
+                                                      (*it)->str.c_str());
                                } else if (nooverwrite) {
                                        log("Ignoring re-definition of module `%s' at %s:%d.\n",
                                                        (*it)->str.c_str(), (*it)->filename.c_str(), (*it)->linenum);
 }
 
 YOSYS_NAMESPACE_END
-
 
        if (gen_attributes)
                for (auto &attr : that->attributes) {
                        if (attr.second->type != AST_CONSTANT)
-                               log_error("Attribute `%s' with non-constant value at %s:%d!\n",
-                                               attr.first.c_str(), that->filename.c_str(), that->linenum);
+                               log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n",
+                                              attr.first.c_str());
                        cell->attributes[attr.first] = attr.second->asAttrConst();
                }
 
        if (that != NULL)
                for (auto &attr : that->attributes) {
                        if (attr.second->type != AST_CONSTANT)
-                               log_error("Attribute `%s' with non-constant value at %s:%d!\n",
-                                               attr.first.c_str(), that->filename.c_str(), that->linenum);
+                               log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n",
+                                              attr.first.c_str());
                        cell->attributes[attr.first] = attr.second->asAttrConst();
                }
 
 
        for (auto &attr : that->attributes) {
                if (attr.second->type != AST_CONSTANT)
-                       log_error("Attribute `%s' with non-constant value at %s:%d!\n",
-                                       attr.first.c_str(), that->filename.c_str(), that->linenum);
+                       log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n",
+                                      attr.first.c_str());
                cell->attributes[attr.first] = attr.second->asAttrConst();
        }
 
 
        for (auto &attr : that->attributes) {
                if (attr.second->type != AST_CONSTANT)
-                       log_error("Attribute `%s' with non-constant value at %s:%d!\n",
-                                       attr.first.c_str(), that->filename.c_str(), that->linenum);
+                       log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n",
+                                      attr.first.c_str());
                cell->attributes[attr.first] = attr.second->asAttrConst();
        }
 
                proc->name = stringf("$proc$%s:%d$%d", always->filename.c_str(), always->linenum, autoidx++);
                for (auto &attr : always->attributes) {
                        if (attr.second->type != AST_CONSTANT)
-                               log_error("Attribute `%s' with non-constant value at %s:%d!\n",
-                                               attr.first.c_str(), always->filename.c_str(), always->linenum);
+                               log_file_error(always->filename, always->linenum, "Attribute `%s' with non-constant value!\n",
+                                               attr.first.c_str());
                        proc->attributes[attr.first] = attr.second->asAttrConst();
                }
                current_module->processes[proc->name] = proc;
 
                                for (auto &attr : ast->attributes) {
                                        if (attr.second->type != AST_CONSTANT)
-                                               log_error("Attribute `%s' with non-constant value at %s:%d!\n",
-                                                               attr.first.c_str(), ast->filename.c_str(), ast->linenum);
+                                               log_file_error(ast->filename, ast->linenum, "Attribute `%s' with non-constant value!\n",
+                                                              attr.first.c_str());
                                        sw->attributes[attr.first] = attr.second->asAttrConst();
                                }
 
                                while (left_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
                                while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
                                if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT)
-                                       log_error("Unsupported expression on dynamic range select on signal `%s' at %s:%d!\n",
-                                                       str.c_str(), filename.c_str(), linenum);
+                                       log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n",
+                                                      str.c_str());
                                this_width = left_at_zero_ast->integer - right_at_zero_ast->integer + 1;
                                delete left_at_zero_ast;
                                delete right_at_zero_ast;
                        if (GetSize(children) == 1) {
                                while (children[0]->simplify(true, false, false, 1, -1, false, true) == true) { }
                                if (children[0]->type != AST_CONSTANT)
-                                       log_error("System function %s called with non-const argument at %s:%d!\n",
-                                                       RTLIL::unescape_id(str).c_str(), filename.c_str(), linenum);
+                                       log_file_error(filename, linenum, "System function %s called with non-const argument!\n",
+                                                      RTLIL::unescape_id(str).c_str());
                                width_hint = max(width_hint, int(children[0]->asInt(true)));
                        }
                        break;
        default:
                for (auto f : log_files)
                        current_ast->dumpAst(f, "verilog-ast> ");
-               log_error("Don't know how to detect sign and width for %s node at %s:%d!\n",
-                               type2str(type).c_str(), filename.c_str(), linenum);
+               log_file_error(filename, linenum, "Don't know how to detect sign and width for %s node!\n",
+                              type2str(type).c_str());
        }
 
        if (*found_real)
        // create an RTLIL::Wire for an AST_WIRE node
        case AST_WIRE: {
                        if (current_module->wires_.count(str) != 0)
-                               log_error("Re-definition of signal `%s' at %s:%d!\n",
-                                               str.c_str(), filename.c_str(), linenum);
+                               log_file_error(filename, linenum, "Re-definition of signal `%s'!\n",
+                                              str.c_str());
                        if (!range_valid)
-                               log_error("Signal `%s' with non-constant width at %s:%d!\n",
-                                               str.c_str(), filename.c_str(), linenum);
+                               log_file_error(filename, linenum, "Signal `%s' with non-constant width!\n",
+                                              str.c_str());
 
                        log_assert(range_left >= range_right || (range_left == -1 && range_right == 0));
 
 
                        for (auto &attr : attributes) {
                                if (attr.second->type != AST_CONSTANT)
-                                       log_error("Attribute `%s' with non-constant value at %s:%d!\n",
-                                                       attr.first.c_str(), filename.c_str(), linenum);
+                                       log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n",
+                                                      attr.first.c_str());
                                wire->attributes[attr.first] = attr.second->asAttrConst();
                        }
                }
        // create an RTLIL::Memory for an AST_MEMORY node
        case AST_MEMORY: {
                        if (current_module->memories.count(str) != 0)
-                               log_error("Re-definition of memory `%s' at %s:%d!\n",
-                                               str.c_str(), filename.c_str(), linenum);
+                               log_file_error(filename, linenum, "Re-definition of memory `%s'!\n",
+                                              str.c_str());
 
                        log_assert(children.size() >= 2);
                        log_assert(children[0]->type == AST_RANGE);
                        log_assert(children[1]->type == AST_RANGE);
 
                        if (!children[0]->range_valid || !children[1]->range_valid)
-                               log_error("Memory `%s' with non-constant width or size at %s:%d!\n",
-                                               str.c_str(), filename.c_str(), linenum);
+                               log_file_error(filename, linenum, "Memory `%s' with non-constant width or size!\n",
+                                              str.c_str());
 
                        RTLIL::Memory *memory = new RTLIL::Memory;
                        memory->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
 
                        for (auto &attr : attributes) {
                                if (attr.second->type != AST_CONSTANT)
-                                       log_error("Attribute `%s' with non-constant value at %s:%d!\n",
-                                                       attr.first.c_str(), filename.c_str(), linenum);
+                                       log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n",
+                                                      attr.first.c_str());
                                memory->attributes[attr.first] = attr.second->asAttrConst();
                        }
                }
        case AST_REALVALUE:
                {
                        RTLIL::SigSpec sig = realAsConst(width_hint);
-                       log_warning("converting real value %e to binary %s at %s:%d.\n",
-                                       realvalue, log_signal(sig), filename.c_str(), linenum);
+                       log_file_warning(filename, linenum, "converting real value %e to binary %s.\n",
+                                        realvalue, log_signal(sig));
                        return sig;
                }
 
                        }
                        else if (id2ast->type == AST_PARAMETER || id2ast->type == AST_LOCALPARAM) {
                                if (id2ast->children[0]->type != AST_CONSTANT)
-                                       log_error("Parameter %s does not evaluate to constant value at %s:%d!\n",
-                                                       str.c_str(), filename.c_str(), linenum);
+                                       log_file_error(filename, linenum, "Parameter %s does not evaluate to constant value!\n",
+                                                      str.c_str());
                                chunk = RTLIL::Const(id2ast->children[0]->bits);
                                goto use_const_chunk;
                        }
                        else if (!id2ast || (id2ast->type != AST_WIRE && id2ast->type != AST_AUTOWIRE &&
                                        id2ast->type != AST_MEMORY) || current_module->wires_.count(str) == 0)
-                               log_error("Identifier `%s' doesn't map to any signal at %s:%d!\n",
-                                               str.c_str(), filename.c_str(), linenum);
+                               log_file_error(filename, linenum, "Identifier `%s' doesn't map to any signal!\n",
+                                               str.c_str());
 
                        if (id2ast->type == AST_MEMORY)
-                               log_error("Identifier `%s' does map to an unexpanded memory at %s:%d!\n",
-                                               str.c_str(), filename.c_str(), linenum);
+                               log_file_error(filename, linenum, "Identifier `%s' does map to an unexpanded memory!\n",
+                                              str.c_str());
 
                        wire = current_module->wires_[str];
                        chunk.wire = wire;
                                        while (left_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
                                        while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
                                        if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT)
-                                               log_error("Unsupported expression on dynamic range select on signal `%s' at %s:%d!\n",
-                                                               str.c_str(), filename.c_str(), linenum);
+                                               log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n",
+                                                              str.c_str());
                                        int width = left_at_zero_ast->integer - right_at_zero_ast->integer + 1;
                                        AstNode *fake_ast = new AstNode(AST_NONE, clone(), children[0]->children.size() >= 2 ?
                                                        children[0]->children[1]->clone() : children[0]->children[0]->clone());
                                                chunk.offset = (id2ast->range_left - id2ast->range_right + 1) - (chunk.offset + chunk.width);
                                        if (chunk.offset >= source_width || chunk.offset + chunk.width < 0) {
                                                if (chunk.width == 1)
-                                                       log_warning("Range select out of bounds on signal `%s' at %s:%d: Setting result bit to undef.\n",
-                                                                       str.c_str(), filename.c_str(), linenum);
+                                                       log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting result bit to undef.\n",
+                                                                        str.c_str());
                                                else
-                                                       log_warning("Range select out of bounds on signal `%s' at %s:%d: Setting all %d result bits to undef.\n",
-                                                                       str.c_str(), filename.c_str(), linenum, chunk.width);
+                                                       log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting all %d result bits to undef.\n",
+                                                                       str.c_str(), chunk.width);
                                                chunk = RTLIL::SigChunk(RTLIL::State::Sx, chunk.width);
                                        } else {
                                                if (chunk.width + chunk.offset > source_width) {
                                                        chunk.offset += add_undef_bits_lsb;
                                                }
                                                if (add_undef_bits_lsb)
-                                                       log_warning("Range select out of bounds on signal `%s' at %s:%d: Setting %d LSB bits to undef.\n",
-                                                                       str.c_str(), filename.c_str(), linenum, add_undef_bits_lsb);
+                                                       log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting %d LSB bits to undef.\n",
+                                                                        str.c_str(), add_undef_bits_lsb);
                                                if (add_undef_bits_msb)
-                                                       log_warning("Range select out of bounds on signal `%s' at %s:%d: Setting %d MSB bits to undef.\n",
-                                                                       str.c_str(), filename.c_str(), linenum, add_undef_bits_msb);
+                                                       log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting %d MSB bits to undef.\n",
+                                                                        str.c_str(), add_undef_bits_msb);
                                        }
                                }
                        }
 
                        for (auto &attr : attributes) {
                                if (attr.second->type != AST_CONSTANT)
-                                       log_error("Attribute `%s' with non-constant value at %s:%d!\n",
-                                                       attr.first.c_str(), filename.c_str(), linenum);
+                                       log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n",
+                                                      attr.first.c_str());
                                cell->attributes[attr.first] = attr.second->asAttrConst();
                        }
 
                                                new_left.append(left[i]);
                                                new_right.append(right[i]);
                                        }
-                               log_warning("Ignoring assignment to constant bits at %s:%d:\n"
-                                               "    old assignment: %s = %s\n    new assignment: %s = %s.\n",
-                                               filename.c_str(), linenum, log_signal(left), log_signal(right),
-                                               log_signal(new_left), log_signal(new_right));
+                               log_file_warning(filename, linenum, "Ignoring assignment to constant bits:\n"
+                                                "    old assignment: %s = %s\n    new assignment: %s = %s.\n",
+                                                log_signal(left), log_signal(right),
+                                                log_signal(new_left), log_signal(new_right));
                                left = new_left;
                                right = new_right;
                        }
                        int port_counter = 0, para_counter = 0;
 
                        if (current_module->count_id(str) != 0)
-                               log_error("Re-definition of cell `%s' at %s:%d!\n",
-                                               str.c_str(), filename.c_str(), linenum);
+                               log_file_error(filename, linenum, "Re-definition of cell `%s'!\n", str.c_str());
 
                        RTLIL::Cell *cell = current_module->addCell(str, "");
                        cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
                                if (child->type == AST_PARASET) {
                                        IdString paraname = child->str.empty() ? stringf("$%d", ++para_counter) : child->str;
                                        if (child->children[0]->type == AST_REALVALUE) {
-                                               log_warning("Replacing floating point parameter %s.%s = %f with string at %s:%d.\n",
-                                                       log_id(cell), log_id(paraname), child->children[0]->realvalue,
-                                                       filename.c_str(), linenum);
+                                               log_file_warning(filename, linenum, "Replacing floating point parameter %s.%s = %f with string.\n",
+                                                                log_id(cell), log_id(paraname), child->children[0]->realvalue);
                                                auto strnode = AstNode::mkconst_str(stringf("%f", child->children[0]->realvalue));
                                                strnode->cloneInto(child->children[0]);
                                                delete strnode;
                                        }
                                        if (child->children[0]->type != AST_CONSTANT)
-                                               log_error("Parameter %s.%s with non-constant value at %s:%d!\n",
-                                                               log_id(cell), log_id(paraname), filename.c_str(), linenum);
+                                               log_file_error(filename, linenum, "Parameter %s.%s with non-constant value!\n",
+                                                              log_id(cell), log_id(paraname));
                                        cell->parameters[paraname] = child->children[0]->asParaConst();
                                        continue;
                                }
                        }
                        for (auto &attr : attributes) {
                                if (attr.second->type != AST_CONSTANT)
-                                       log_error("Attribute `%s' with non-constant value at %s:%d!\n",
-                                                       attr.first.c_str(), filename.c_str(), linenum);
+                                       log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n",
+                                                      attr.first.c_str());
                                cell->attributes[attr.first] = attr.second->asAttrConst();
                        }
                }
                                int width = width_hint;
 
                                if (GetSize(children) > 1)
-                                       log_error("System function %s got %d arguments, expected 1 or 0 at %s:%d.\n",
-                                                       RTLIL::unescape_id(str).c_str(), GetSize(children), filename.c_str(), linenum);
+                                       log_file_error(filename, linenum, "System function %s got %d arguments, expected 1 or 0.\n",
+                                                      RTLIL::unescape_id(str).c_str(), GetSize(children));
 
                                if (GetSize(children) == 1) {
                                        if (children[0]->type != AST_CONSTANT)
-                                               log_error("System function %s called with non-const argument at %s:%d!\n",
-                                                               RTLIL::unescape_id(str).c_str(), filename.c_str(), linenum);
+                                               log_file_error(filename, linenum, "System function %s called with non-const argument!\n",
+                                                              RTLIL::unescape_id(str).c_str());
                                        width = children[0]->asInt(true);
                                }
 
                                if (width <= 0)
-                                       log_error("Failed to detect width of %s at %s:%d!\n",
-                                                       RTLIL::unescape_id(str).c_str(), filename.c_str(), linenum);
+                                       log_file_error(filename, linenum, "Failed to detect width of %s!\n",
+                                                      RTLIL::unescape_id(str).c_str());
 
                                Cell *cell = current_module->addCell(myid, str.substr(1));
                                cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
                for (auto f : log_files)
                        current_ast->dumpAst(f, "verilog-ast> ");
                type_name = type2str(type);
-               log_error("Don't know how to generate RTLIL code for %s node at %s:%d!\n",
-                               type_name.c_str(), filename.c_str(), linenum);
+               log_file_error(filename, linenum, "Don't know how to generate RTLIL code for %s node!\n",
+                              type_name.c_str());
        }
 
        return RTLIL::SigSpec();
 
        {
                int nargs = GetSize(children);
                if (nargs < 1)
-                       log_error("System task `%s' got %d arguments, expected >= 1 at %s:%d.\n",
-                                       str.c_str(), int(children.size()), filename.c_str(), linenum);
+                       log_file_error(filename, linenum, "System task `%s' got %d arguments, expected >= 1.\n",
+                                      str.c_str(), int(children.size()));
 
                // First argument is the format string
                AstNode *node_string = children[0];
                                        case 'x':
                                        case 'X':
                                                if (next_arg >= GetSize(children))
-                                                       log_error("Missing argument for %%%c format specifier in system task `%s' at %s:%d.\n",
-                                                                       cformat, str.c_str(), filename.c_str(), linenum);
+                                                       log_file_error(filename, linenum, "Missing argument for %%%c format specifier in system task `%s'.\n",
+                                                                      cformat, str.c_str());
 
                                                node_arg = children[next_arg++];
                                                while (node_arg->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
                paramname = "\\" + paramname.substr(pos+1);
 
                if (current_scope.at(modname)->type != AST_CELL)
-                       log_error("Defparam argument `%s . %s` does not match a cell at %s:%d!\n",
-                                       RTLIL::unescape_id(modname).c_str(), RTLIL::unescape_id(paramname).c_str(), filename.c_str(), linenum);
+                       log_file_error(filename, linenum, "Defparam argument `%s . %s` does not match a cell!\n",
+                                      RTLIL::unescape_id(modname).c_str(), RTLIL::unescape_id(paramname).c_str());
 
                AstNode *paraset = new AstNode(AST_PARASET, children[1]->clone(), GetSize(children) > 2 ? children[2]->clone() : NULL);
                paraset->str = paramname;
                        int width = std::abs(children[1]->range_left - children[1]->range_right) + 1;
                        if (children[0]->type == AST_REALVALUE) {
                                RTLIL::Const constvalue = children[0]->realAsConst(width);
-                               log_warning("converting real value %e to binary %s at %s:%d.\n",
-                                               children[0]->realvalue, log_signal(constvalue), filename.c_str(), linenum);
+                               log_file_warning(filename, linenum, "converting real value %e to binary %s.\n",
+                                                children[0]->realvalue, log_signal(constvalue));
                                delete children[0];
                                children[0] = mkconst_bits(constvalue.bits, sign_hint);
                                did_something = true;
        {
                for (size_t i = 0; i < children.size(); i++)
                        if (children[i]->type == AST_WIRE || children[i]->type == AST_MEMORY || children[i]->type == AST_PARAMETER || children[i]->type == AST_LOCALPARAM)
-                               log_error("Local declaration in unnamed block at %s:%d is an unsupported SystemVerilog feature!\n",
-                                               children[i]->filename.c_str(), children[i]->linenum);
+                               log_file_error(children[i]->filename, children[i]->linenum, "Local declaration in unnamed block is an unsupported SystemVerilog feature!\n");
        }
 
        // transform block with name
        if (type == AST_PRIMITIVE)
        {
                if (children.size() < 2)
-                       log_error("Insufficient number of arguments for primitive `%s' at %s:%d!\n",
-                                       str.c_str(), filename.c_str(), linenum);
+                       log_file_error(filename, linenum, "Insufficient number of arguments for primitive `%s'!\n",
+                                      str.c_str());
 
                std::vector<AstNode*> children_list;
                for (auto child : children) {
                if (str == "bufif0" || str == "bufif1" || str == "notif0" || str == "notif1")
                {
                        if (children_list.size() != 3)
-                               log_error("Invalid number of arguments for primitive `%s' at %s:%d!\n",
-                                               str.c_str(), filename.c_str(), linenum);
+                               log_file_error(filename, linenum, "Invalid number of arguments for primitive `%s'!\n",
+                                              str.c_str());
 
                        std::vector<RTLIL::State> z_const(1, RTLIL::State::Sz);
 
                        while (left_at_zero_ast->simplify(true, true, false, stage, -1, false, false)) { }
                        while (right_at_zero_ast->simplify(true, true, false, stage, -1, false, false)) { }
                        if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT)
-                               log_error("Unsupported expression on dynamic range select on signal `%s' at %s:%d!\n",
-                                               str.c_str(), filename.c_str(), linenum);
+                               log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n",
+                                              str.c_str());
                        result_width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1;
                }
                did_something = true;
                                int num_steps = 1;
 
                                if (GetSize(children) != 1 && GetSize(children) != 2)
-                                       log_error("System function %s got %d arguments, expected 1 or 2 at %s:%d.\n",
-                                                       RTLIL::unescape_id(str).c_str(), int(children.size()), filename.c_str(), linenum);
+                                       log_file_error(filename, linenum, "System function %s got %d arguments, expected 1 or 2.\n",
+                                                      RTLIL::unescape_id(str).c_str(), int(children.size()));
 
                                if (!current_always_clocked)
-                                       log_error("System function %s is only allowed in clocked blocks at %s:%d.\n",
-                                                       RTLIL::unescape_id(str).c_str(), filename.c_str(), linenum);
+                                       log_file_error(filename, linenum, "System function %s is only allowed in clocked blocks.\n",
+                                                      RTLIL::unescape_id(str).c_str());
 
                                if (GetSize(children) == 2)
                                {
                        if (str == "\\$stable" || str == "\\$rose" || str == "\\$fell")
                        {
                                if (GetSize(children) != 1)
-                                       log_error("System function %s got %d arguments, expected 1 at %s:%d.\n",
-                                                       RTLIL::unescape_id(str).c_str(), int(children.size()), filename.c_str(), linenum);
+                                       log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n",
+                                                      RTLIL::unescape_id(str).c_str(), int(children.size()));
 
                                if (!current_always_clocked)
-                                       log_error("System function %s is only allowed in clocked blocks at %s:%d.\n",
-                                                       RTLIL::unescape_id(str).c_str(), filename.c_str(), linenum);
+                                       log_file_error(filename, linenum, "System function %s is only allowed in clocked blocks.\n",
+                                                      RTLIL::unescape_id(str).c_str());
 
                                AstNode *present = children.at(0)->clone();
                                AstNode *past = clone();
                        if (str == "\\$clog2")
                        {
                                if (children.size() != 1)
-                                       log_error("System function %s got %d arguments, expected 1 at %s:%d.\n",
-                                                       RTLIL::unescape_id(str).c_str(), int(children.size()), filename.c_str(), linenum);
+                                       log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n",
+                                                      RTLIL::unescape_id(str).c_str(), int(children.size()));
 
                                AstNode *buf = children[0]->clone();
                                while (buf->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
                        if (str == "\\$size" || str == "\\$bits")
                        {
                                if (str == "\\$bits" && children.size() != 1)
-                                       log_error("System function %s got %d arguments, expected 1 at %s:%d.\n",
-                                                       RTLIL::unescape_id(str).c_str(), int(children.size()), filename.c_str(), linenum);
+                                       log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n",
+                                                      RTLIL::unescape_id(str).c_str(), int(children.size()));
 
                                if (str == "\\$size" && children.size() != 1 && children.size() != 2)
-                                       log_error("System function %s got %d arguments, expected 1 or 2 at %s:%d.\n",
-                                                       RTLIL::unescape_id(str).c_str(), int(children.size()), filename.c_str(), linenum);
+                                       log_file_error(filename, linenum, "System function %s got %d arguments, expected 1 or 2.\n",
+                                                      RTLIL::unescape_id(str).c_str(), int(children.size()));
 
                                int dim = 1;
                                if (str == "\\$size" && children.size() == 2) {
 
                                if (func_with_two_arguments) {
                                        if (children.size() != 2)
-                                               log_error("System function %s got %d arguments, expected 2 at %s:%d.\n",
-                                                               RTLIL::unescape_id(str).c_str(), int(children.size()), filename.c_str(), linenum);
+                                               log_file_error(filename, linenum, "System function %s got %d arguments, expected 2.\n",
+                                                              RTLIL::unescape_id(str).c_str(), int(children.size()));
                                } else {
                                        if (children.size() != 1)
-                                               log_error("System function %s got %d arguments, expected 1 at %s:%d.\n",
-                                                               RTLIL::unescape_id(str).c_str(), int(children.size()), filename.c_str(), linenum);
+                                               log_file_error(filename, linenum, "System function %s got %d arguments, expected 1.\n",
+                                                              RTLIL::unescape_id(str).c_str(), int(children.size()));
                                }
 
                                if (children.size() >= 1) {
                                        while (children[0]->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
                                        if (!children[0]->isConst())
-                                               log_error("Failed to evaluate system function `%s' with non-constant argument at %s:%d.\n",
-                                                               RTLIL::unescape_id(str).c_str(), filename.c_str(), linenum);
+                                               log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant argument.\n",
+                                                              RTLIL::unescape_id(str).c_str());
                                        int child_width_hint = width_hint;
                                        bool child_sign_hint = sign_hint;
                                        children[0]->detectSignWidth(child_width_hint, child_sign_hint);
                                if (children.size() >= 2) {
                                        while (children[1]->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
                                        if (!children[1]->isConst())
-                                               log_error("Failed to evaluate system function `%s' with non-constant argument at %s:%d.\n",
-                                                               RTLIL::unescape_id(str).c_str(), filename.c_str(), linenum);
+                                               log_file_error(filename, linenum, "Failed to evaluate system function `%s' with non-constant argument.\n",
+                                                              RTLIL::unescape_id(str).c_str());
                                        int child_width_hint = width_hint;
                                        bool child_sign_hint = sign_hint;
                                        children[1]->detectSignWidth(child_width_hint, child_sign_hint);
                        if (str == "\\$readmemh" || str == "\\$readmemb")
                        {
                                if (GetSize(children) < 2 || GetSize(children) > 4)
-                                       log_error("System function %s got %d arguments, expected 2-4 at %s:%d.\n",
-                                                       RTLIL::unescape_id(str).c_str(), int(children.size()), filename.c_str(), linenum);
+                                       log_file_error(filename, linenum, "System function %s got %d arguments, expected 2-4.\n",
+                                                      RTLIL::unescape_id(str).c_str(), int(children.size()));
 
                                AstNode *node_filename = children[0]->clone();
                                while (node_filename->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
                                continue;
 
                        if (stmt->children.at(1)->type != AST_CONSTANT)
-                               log_error("Non-constant expression in constant function at %s:%d (called from %s:%d). X\n",
-                                               stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum);
+                               log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function (called from %s:%d). X\n",
+                                              fcall->filename.c_str(), fcall->linenum);
 
                        if (stmt->children.at(0)->type != AST_IDENTIFIER)
-                               log_error("Unsupported composite left hand side in constant function at %s:%d (called from %s:%d).\n",
-                                               stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum);
+                               log_file_error(stmt->filename, stmt->linenum, "Unsupported composite left hand side in constant function (called from %s:%d).\n",
+                                              fcall->filename.c_str(), fcall->linenum);
 
                        if (!variables.count(stmt->children.at(0)->str))
-                               log_error("Assignment to non-local variable in constant function at %s:%d (called from %s:%d).\n",
-                                               stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum);
+                               log_file_error(stmt->filename, stmt->linenum, "Assignment to non-local variable in constant function (called from %s:%d).\n",
+                                              fcall->filename.c_str(), fcall->linenum);
 
                        if (stmt->children.at(0)->children.empty()) {
                                variables[stmt->children.at(0)->str].val = stmt->children.at(1)->bitsAsConst(variables[stmt->children.at(0)->str].val.bits.size());
                        while (cond->simplify(true, false, false, 1, -1, false, true)) { }
 
                        if (cond->type != AST_CONSTANT)
-                               log_error("Non-constant expression in constant function at %s:%d (called from %s:%d).\n",
-                                               stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum);
+                               log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function (called from %s:%d).\n",
+                                              fcall->filename.c_str(), fcall->linenum);
 
                        if (cond->asBool()) {
                                block->children.insert(block->children.begin(), stmt->children.at(1)->clone());
                        while (num->simplify(true, false, false, 1, -1, false, true)) { }
 
                        if (num->type != AST_CONSTANT)
-                               log_error("Non-constant expression in constant function at %s:%d (called from %s:%d).\n",
-                                               stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum);
+                               log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function (called from %s:%d).\n",
+                                              fcall->filename.c_str(), fcall->linenum);
 
                        block->children.erase(block->children.begin());
                        for (int i = 0; i < num->bitsAsConst().as_int(); i++)
                                        while (cond->simplify(true, false, false, 1, -1, false, true)) { }
 
                                        if (cond->type != AST_CONSTANT)
-                                               log_error("Non-constant expression in constant function at %s:%d (called from %s:%d).\n",
-                                                               stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum);
+                                               log_file_error(stmt->filename, stmt->linenum, "Non-constant expression in constant function (called from %s:%d).\n",
+                                                              fcall->filename.c_str(), fcall->linenum);
 
                                        found_match = cond->asBool();
                                        delete cond;
                        continue;
                }
 
-               log_error("Unsupported language construct in constant function at %s:%d (called from %s:%d).\n",
-                               stmt->filename.c_str(), stmt->linenum, fcall->filename.c_str(), fcall->linenum);
+               log_file_error(stmt->filename, stmt->linenum, "Unsupported language construct in constant function (called from %s:%d).\n",
+                              fcall->filename.c_str(), fcall->linenum);
                log_abort();
        }
 
 
        int carry = 0;
        for (size_t i = 0; i < digits.size(); i++) {
                if (digits[i] >= 10)
-                       log_error("Invalid use of [a-fxz?] in decimal constant at %s:%d.\n",
-                               current_filename.c_str(), get_line_num());
+                       log_file_error(current_filename, get_line_num(), "Invalid use of [a-fxz?] in decimal constant.\n");
                digits[i] += carry * 10;
                carry = digits[i] % 2;
                digits[i] /= 2;
                int bits_per_digit = my_ilog2(base-1);
                for (auto it = digits.rbegin(), e = digits.rend(); it != e; it++) {
                        if (*it > (base-1) && *it < 0xf0)
-                               log_error("Digit larger than %d used in in base-%d constant at %s:%d.\n",
-                                       base-1, base, current_filename.c_str(), get_line_num());
+                               log_file_error(current_filename, get_line_num(), "Digit larger than %d used in in base-%d constant.\n",
+                                              base-1, base);
                        for (int i = 0; i < bits_per_digit; i++) {
                                int bitmask = 1 << i;
                                if (*it == 0xf0)
 }
 
 YOSYS_NAMESPACE_END
-