Replaced CONFESS with throw std::exception in libslic3r, so now

libslic3r should be compilable without Perl.
This commit is contained in:
bubnikv 2018-09-18 10:09:58 +02:00
parent 27bba45331
commit 3ddaccb641
30 changed files with 261 additions and 246 deletions

View File

@ -10,12 +10,6 @@ const std::string USAGE_STR = {
"Usage: slabasebed stlfilename.stl"
};
void confess_at(const char * /*file*/,
int /*line*/,
const char * /*func*/,
const char * /*pat*/,
...) {}
int main(const int argc, const char *argv[]) {
using namespace Slic3r;
using std::cout; using std::endl;

View File

@ -14,8 +14,6 @@
using namespace Slic3r;
void confess_at(const char *file, int line, const char *func, const char *pat, ...){}
int
main(int argc, char **argv)
{

View File

@ -518,6 +518,8 @@ add_library(XS ${XS_SHARED_LIBRARY_TYPE}
${LIBDIR}/libslic3r/utils.cpp
${LIBDIR}/slic3r/GUI/wxPerlIface.cpp
${LIBDIR}/perlglue.cpp
${LIBDIR}/callback.cpp
${LIBDIR}/callback.hpp
${LIBDIR}/ppport.h
${LIBDIR}/xsinit.h
${CMAKE_CURRENT_LIST_DIR}/xsp/my.map

155
xs/src/callback.cpp Normal file
View File

@ -0,0 +1,155 @@
#include "callback.hpp"
#include <xsinit.h>
void PerlCallback::register_callback(void *sv)
{
if (! SvROK((SV*)sv) || SvTYPE(SvRV((SV*)sv)) != SVt_PVCV)
croak("Not a Callback %_ for PerlFunction", (SV*)sv);
if (m_callback)
SvSetSV((SV*)m_callback, (SV*)sv);
else
m_callback = newSVsv((SV*)sv);
}
void PerlCallback::deregister_callback()
{
if (m_callback) {
sv_2mortal((SV*)m_callback);
m_callback = nullptr;
}
}
void PerlCallback::call() const
{
if (! m_callback)
return;
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
PUTBACK;
perl_call_sv(SvRV((SV*)m_callback), G_DISCARD);
FREETMPS;
LEAVE;
}
void PerlCallback::call(int i) const
{
if (! m_callback)
return;
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSViv(i)));
PUTBACK;
perl_call_sv(SvRV((SV*)m_callback), G_DISCARD);
FREETMPS;
LEAVE;
}
void PerlCallback::call(int i, int j) const
{
if (! m_callback)
return;
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSViv(i)));
XPUSHs(sv_2mortal(newSViv(j)));
PUTBACK;
perl_call_sv(SvRV((SV*)m_callback), G_DISCARD);
FREETMPS;
LEAVE;
}
void PerlCallback::call(const std::vector<int>& ints) const
{
if (! m_callback)
return;
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
for (int i : ints)
{
XPUSHs(sv_2mortal(newSViv(i)));
}
PUTBACK;
perl_call_sv(SvRV((SV*)m_callback), G_DISCARD);
FREETMPS;
LEAVE;
}
void PerlCallback::call(double a) const
{
if (!m_callback)
return;
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSVnv(a)));
PUTBACK;
perl_call_sv(SvRV((SV*)m_callback), G_DISCARD);
FREETMPS;
LEAVE;
}
void PerlCallback::call(double a, double b) const
{
if (!m_callback)
return;
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSVnv(a)));
XPUSHs(sv_2mortal(newSVnv(b)));
PUTBACK;
perl_call_sv(SvRV((SV*)m_callback), G_DISCARD);
FREETMPS;
LEAVE;
}
void PerlCallback::call(double a, double b, double c) const
{
if (!m_callback)
return;
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSVnv(a)));
XPUSHs(sv_2mortal(newSVnv(b)));
XPUSHs(sv_2mortal(newSVnv(c)));
PUTBACK;
perl_call_sv(SvRV((SV*)m_callback), G_DISCARD);
FREETMPS;
LEAVE;
}
void PerlCallback::call(double a, double b, double c, double d) const
{
if (!m_callback)
return;
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSVnv(a)));
XPUSHs(sv_2mortal(newSVnv(b)));
XPUSHs(sv_2mortal(newSVnv(c)));
XPUSHs(sv_2mortal(newSVnv(d)));
PUTBACK;
perl_call_sv(SvRV((SV*)m_callback), G_DISCARD);
FREETMPS;
LEAVE;
}
void PerlCallback::call(bool b) const
{
call(b ? 1 : 0);
}

32
xs/src/callback.hpp Normal file
View File

@ -0,0 +1,32 @@
#ifndef slic3r_PerlCallback_hpp_
#define slic3r_PerlCallback_hpp_
#include <locale>
#include "libslic3r.h"
namespace Slic3r {
class PerlCallback {
public:
PerlCallback(void *sv) : m_callback(nullptr) { this->register_callback(sv); }
PerlCallback() : m_callback(nullptr) {}
~PerlCallback() { this->deregister_callback(); }
void register_callback(void *sv);
void deregister_callback();
void call() const;
void call(int i) const;
void call(int i, int j) const;
void call(const std::vector<int>& ints) const;
void call(double a) const;
void call(double a, double b) const;
void call(double a, double b, double c) const;
void call(double a, double b, double c, double d) const;
void call(bool b) const;
private:
void *m_callback;
};
} // namespace Slic3r
#endif /* slic3r_PerlCallback_hpp_ */

View File

@ -21,7 +21,7 @@ public:
BoundingBoxBase(const std::vector<PointClass>& points) : min(PointClass::Zero()), max(PointClass::Zero())
{
if (points.empty())
CONFESS("Empty point set supplied to BoundingBoxBase constructor");
throw std::invalid_argument("Empty point set supplied to BoundingBoxBase constructor");
typename std::vector<PointClass>::const_iterator it = points.begin();
this->min = *it;
@ -65,7 +65,7 @@ public:
BoundingBox3Base(const std::vector<PointClass>& points)
{
if (points.empty())
CONFESS("Empty point set supplied to BoundingBox3Base constructor");
throw std::invalid_argument("Empty point set supplied to BoundingBox3Base constructor");
typename std::vector<PointClass>::const_iterator it = points.begin();
this->min = *it;
this->max = *it;

View File

@ -437,7 +437,8 @@ ExPolygon::triangulate_pp(Polygons* polygons) const
// perform triangulation
std::list<TPPLPoly> output;
int res = TPPLPartition().Triangulate_MONO(&input, &output);
if (res != 1) CONFESS("Triangulation failed");
if (res != 1)
throw std::runtime_error("Triangulation failed");
// convert output polygons
for (std::list<TPPLPoly>::iterator poly = output.begin(); poly != output.end(); ++poly) {

View File

@ -88,7 +88,7 @@ public:
// Following methods shall never be called on an ExtrusionEntityCollection.
Polyline as_polyline() const {
CONFESS("Calling as_polyline() on a ExtrusionEntityCollection");
throw std::runtime_error("Calling as_polyline() on a ExtrusionEntityCollection");
return Polyline();
};
@ -98,7 +98,7 @@ public:
}
double length() const override {
CONFESS("Calling length() on a ExtrusionEntityCollection");
throw std::runtime_error("Calling length() on a ExtrusionEntityCollection");
return 0.;
}
};

View File

@ -34,7 +34,7 @@ Fill* Fill::new_from_type(const InfillPattern type)
case ipArchimedeanChords: return new FillArchimedeanChords();
case ipHilbertCurve: return new FillHilbertCurve();
case ipOctagramSpiral: return new FillOctagramSpiral();
default: CONFESS("unknown type"); return nullptr;
default: throw std::invalid_argument("unknown type");;
}
}

View File

@ -28,7 +28,7 @@ Flow Flow::new_from_config_width(FlowRole role, const ConfigOptionFloatOrPercent
{
// we need layer height unless it's a bridge
if (height <= 0 && bridge_flow_ratio == 0)
CONFESS("Invalid flow height supplied to new_from_config_width()");
throw std::invalid_argument("Invalid flow height supplied to new_from_config_width()");
float w;
if (bridge_flow_ratio > 0) {
@ -53,7 +53,7 @@ Flow Flow::new_from_spacing(float spacing, float nozzle_diameter, float height,
{
// we need layer height unless it's a bridge
if (height <= 0 && !bridge)
CONFESS("Invalid flow height supplied to new_from_spacing()");
throw std::invalid_argument("Invalid flow height supplied to new_from_spacing()");
// Calculate width from spacing.
// For normal extrusons, extrusion width is wider than the spacing due to the rounding and squishing of the extrusions.
// For bridge extrusions, the extrusions are placed with a tiny BRIDGE_EXTRA_SPACING gaps between the threads.

View File

@ -800,7 +800,7 @@ bool store_amf(const char *path, Model *model, Print* print, bool export_print_c
for (ModelVolume *volume : object->volumes) {
vertices_offsets.push_back(num_vertices);
if (! volume->mesh.repaired)
CONFESS("store_amf() requires repair()");
throw std::runtime_error("store_amf() requires repair()");
auto &stl = volume->mesh.stl;
if (stl.v_shared == nullptr)
stl_generate_shared_vertices(&stl);

View File

@ -2204,7 +2204,7 @@ std::string GCode::extrude_entity(const ExtrusionEntity &entity, std::string des
else if (const ExtrusionLoop* loop = dynamic_cast<const ExtrusionLoop*>(&entity))
return this->extrude_loop(*loop, description, speed, lower_layer_edge_grid);
else {
CONFESS("Invalid argument supplied to extrude()");
throw std::invalid_argument("Invalid argument supplied to extrude()");
return "";
}
}
@ -2389,7 +2389,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
} else if (path.role() == erGapFill) {
speed = m_config.get_abs_value("gap_fill_speed");
} else {
CONFESS("Invalid speed");
throw std::invalid_argument("Invalid speed");
}
}
if (this->on_first_layer())
@ -2715,7 +2715,7 @@ void GCode::ObjectByExtruder::Island::Region::append(const std::string& type, co
}
else
if (type != "infills") {
CONFESS("Unknown parameter!");
throw std::invalid_argument("Unknown parameter!");
return;
}

View File

@ -93,7 +93,7 @@ static BoundingBoxf extrusionentity_extents(const ExtrusionEntity *extrusion_ent
auto *extrusion_entity_collection = dynamic_cast<const ExtrusionEntityCollection*>(extrusion_entity);
if (extrusion_entity_collection != nullptr)
return extrusionentity_extents(*extrusion_entity_collection);
CONFESS("Unexpected extrusion_entity type in extrusionentity_extents()");
throw std::runtime_error("Unexpected extrusion_entity type in extrusionentity_extents()");
return BoundingBoxf();
}

View File

@ -432,7 +432,7 @@ Pointfs arrange(size_t num_parts, const Vec2d &part_size, coordf_t gap, const Bo
size_t cellw = size_t(floor((bed_bbox.size()(0) + gap) / cell_size(0)));
size_t cellh = size_t(floor((bed_bbox.size()(1) + gap) / cell_size(1)));
if (num_parts > cellw * cellh)
CONFESS(PRINTF_ZU " parts won't fit in your print area!\n", num_parts);
throw std::invalid_argument(PRINTF_ZU " parts won't fit in your print area!\n", num_parts);
// Get a bounding box of cellw x cellh cells, centered at the center of the bed.
Vec2d cells_size(cellw * cell_size(0) - gap, cellh * cell_size(1) - gap);

View File

@ -340,7 +340,7 @@ void Model::duplicate(size_t copies_num, coordf_t dist, const BoundingBoxf* bb)
Pointfs model_sizes(copies_num-1, to_2d(this->bounding_box().size()));
Pointfs positions;
if (! _arrange(model_sizes, dist, bb, positions))
CONFESS("Cannot duplicate part as the resulting objects would not fit on the print bed.\n");
throw std::invalid_argument("Cannot duplicate part as the resulting objects would not fit on the print bed.\n");
// note that this will leave the object count unaltered
@ -671,7 +671,8 @@ BoundingBoxf3 ModelObject::raw_bounding_box() const
BoundingBoxf3 bb;
for (const ModelVolume *v : this->volumes)
if (v->is_model_part()) {
if (this->instances.empty()) CONFESS("Can't call raw_bounding_box() with no instances");
if (this->instances.empty())
throw std::invalid_argument("Can't call raw_bounding_box() with no instances");
bb.merge(this->instances.front()->transform_mesh_bounding_box(&v->mesh, true));
}
return bb;

View File

@ -47,7 +47,7 @@ Polygon::split_at_vertex(const Point &point) const
for (const Point &pt : this->points)
if (pt == point)
return this->split_at_index(&pt - &this->points.front());
CONFESS("Point not found");
throw std::invalid_argument("Point not found");
return Polyline();
}

View File

@ -18,7 +18,8 @@ Polyline::operator Polylines() const
Polyline::operator Line() const
{
if (this->points.size() > 2) CONFESS("Can't convert polyline with more than two points to a line");
if (this->points.size() > 2)
throw std::invalid_argument("Can't convert polyline with more than two points to a line");
return Line(this->points.front(), this->points.back());
}

View File

@ -77,7 +77,8 @@ Polylines PolylineCollection::_chained_path_from(
Point PolylineCollection::leftmost_point(const Polylines &polylines)
{
if (polylines.empty()) CONFESS("leftmost_point() called on empty PolylineCollection");
if (polylines.empty())
throw std::invalid_argument("leftmost_point() called on empty PolylineCollection");
Polylines::const_iterator it = polylines.begin();
Point p = it->leftmost_point();
for (++ it; it != polylines.end(); ++it) {

View File

@ -819,7 +819,8 @@ BoundingBox Print::total_bounding_box() const
double Print::skirt_first_layer_height() const
{
if (m_objects.empty()) CONFESS("skirt_first_layer_height() can't be called without PrintObjects");
if (m_objects.empty())
throw std::invalid_argument("skirt_first_layer_height() can't be called without PrintObjects");
return m_objects.front()->config().get_abs_value("first_layer_height");
}

View File

@ -25,7 +25,7 @@ Flow PrintRegion::flow(FlowRole role, double layer_height, bool bridge, bool fir
} else if (role == frTopSolidInfill) {
config_width = m_config.top_infill_extrusion_width;
} else {
CONFESS("Unknown role");
throw std::invalid_argument("Unknown role");
}
}
if (config_width.value == 0) {
@ -42,7 +42,7 @@ Flow PrintRegion::flow(FlowRole role, double layer_height, bool bridge, bool fir
} else if (role == frSolidInfill || role == frTopSolidInfill) {
extruder = m_config.solid_infill_extruder;
} else {
CONFESS("Unknown role $role");
throw std::invalid_argument("Unknown role");
}
double nozzle_diameter = m_print->config().nozzle_diameter.get_at(extruder-1);

View File

@ -308,7 +308,8 @@ void TriangleMesh::rotate(double angle, Point* center)
bool TriangleMesh::has_multiple_patches() const
{
// we need neighbors
if (!this->repaired) CONFESS("split() requires repair()");
if (!this->repaired)
throw std::runtime_error("split() requires repair()");
if (this->stl.stats.number_of_facets == 0)
return false;
@ -338,7 +339,8 @@ bool TriangleMesh::has_multiple_patches() const
size_t TriangleMesh::number_of_patches() const
{
// we need neighbors
if (!this->repaired) CONFESS("split() requires repair()");
if (!this->repaired)
throw std::runtime_error("split() requires repair()");
if (this->stl.stats.number_of_facets == 0)
return false;
@ -382,7 +384,7 @@ TriangleMeshPtrs TriangleMesh::split() const
// we need neighbors
if (!this->repaired)
CONFESS("split() requires repair()");
throw std::runtime_error("split() requires repair()");
// loop while we have remaining facets
for (;;) {

View File

@ -95,26 +95,6 @@ inline T next_highest_power_of_2(T v)
extern std::string xml_escape(std::string text);
class PerlCallback {
public:
PerlCallback(void *sv) : m_callback(nullptr) { this->register_callback(sv); }
PerlCallback() : m_callback(nullptr) {}
~PerlCallback() { this->deregister_callback(); }
void register_callback(void *sv);
void deregister_callback();
void call() const;
void call(int i) const;
void call(int i, int j) const;
void call(const std::vector<int>& ints) const;
void call(double a) const;
void call(double a, double b) const;
void call(double a, double b, double c) const;
void call(double a, double b, double c, double d) const;
void call(bool b) const;
private:
void *m_callback;
};
} // namespace Slic3r
#endif // slic3r_Utils_hpp_

View File

@ -48,14 +48,6 @@ typedef double coordf_t;
//inline coord_t scale_(coordf_t v) { return coord_t(floor(v / SCALING_FACTOR + 0.5f)); }
#define scale_(val) ((val) / SCALING_FACTOR)
#define SCALED_EPSILON scale_(EPSILON)
/* Implementation of CONFESS("foo"): */
#ifdef _MSC_VER
#define CONFESS(...) confess_at(__FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
#else
#define CONFESS(...) confess_at(__FILE__, __LINE__, __func__, __VA_ARGS__)
#endif
void confess_at(const char *file, int line, const char *func, const char *pat, ...);
/* End implementation of CONFESS("foo"): */
// Which C++ version is supported?
// For example, could optimized functions with move semantics be used?

View File

@ -233,187 +233,6 @@ int copy_file(const std::string &from, const std::string &to)
} // namespace Slic3r
#include <xsinit.h>
void
confess_at(const char *file, int line, const char *func,
const char *pat, ...)
{
#ifdef SLIC3RXS
va_list args;
SV *error_sv = newSVpvf("Error in function %s at %s:%d: ", func,
file, line);
va_start(args, pat);
sv_vcatpvf(error_sv, pat, &args);
va_end(args);
sv_catpvn(error_sv, "\n\t", 2);
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs( sv_2mortal(error_sv) );
PUTBACK;
call_pv("Carp::confess", G_DISCARD);
FREETMPS;
LEAVE;
#endif
}
void PerlCallback::register_callback(void *sv)
{
if (! SvROK((SV*)sv) || SvTYPE(SvRV((SV*)sv)) != SVt_PVCV)
croak("Not a Callback %_ for PerlFunction", (SV*)sv);
if (m_callback)
SvSetSV((SV*)m_callback, (SV*)sv);
else
m_callback = newSVsv((SV*)sv);
}
void PerlCallback::deregister_callback()
{
if (m_callback) {
sv_2mortal((SV*)m_callback);
m_callback = nullptr;
}
}
void PerlCallback::call() const
{
if (! m_callback)
return;
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
PUTBACK;
perl_call_sv(SvRV((SV*)m_callback), G_DISCARD);
FREETMPS;
LEAVE;
}
void PerlCallback::call(int i) const
{
if (! m_callback)
return;
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSViv(i)));
PUTBACK;
perl_call_sv(SvRV((SV*)m_callback), G_DISCARD);
FREETMPS;
LEAVE;
}
void PerlCallback::call(int i, int j) const
{
if (! m_callback)
return;
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSViv(i)));
XPUSHs(sv_2mortal(newSViv(j)));
PUTBACK;
perl_call_sv(SvRV((SV*)m_callback), G_DISCARD);
FREETMPS;
LEAVE;
}
void PerlCallback::call(const std::vector<int>& ints) const
{
if (! m_callback)
return;
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
for (int i : ints)
{
XPUSHs(sv_2mortal(newSViv(i)));
}
PUTBACK;
perl_call_sv(SvRV((SV*)m_callback), G_DISCARD);
FREETMPS;
LEAVE;
}
void PerlCallback::call(double a) const
{
if (!m_callback)
return;
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSVnv(a)));
PUTBACK;
perl_call_sv(SvRV((SV*)m_callback), G_DISCARD);
FREETMPS;
LEAVE;
}
void PerlCallback::call(double a, double b) const
{
if (!m_callback)
return;
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSVnv(a)));
XPUSHs(sv_2mortal(newSVnv(b)));
PUTBACK;
perl_call_sv(SvRV((SV*)m_callback), G_DISCARD);
FREETMPS;
LEAVE;
}
void PerlCallback::call(double a, double b, double c) const
{
if (!m_callback)
return;
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSVnv(a)));
XPUSHs(sv_2mortal(newSVnv(b)));
XPUSHs(sv_2mortal(newSVnv(c)));
PUTBACK;
perl_call_sv(SvRV((SV*)m_callback), G_DISCARD);
FREETMPS;
LEAVE;
}
void PerlCallback::call(double a, double b, double c, double d) const
{
if (!m_callback)
return;
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSVnv(a)));
XPUSHs(sv_2mortal(newSVnv(b)));
XPUSHs(sv_2mortal(newSVnv(c)));
XPUSHs(sv_2mortal(newSVnv(d)));
PUTBACK;
perl_call_sv(SvRV((SV*)m_callback), G_DISCARD);
FREETMPS;
LEAVE;
}
void PerlCallback::call(bool b) const
{
call(b ? 1 : 0);
}
#ifdef WIN32
#ifndef NOMINMAX
# define NOMINMAX

View File

@ -1687,7 +1687,7 @@ void _3DScene::extrusionentity_to_verts(const ExtrusionEntity *extrusion_entity,
if (extrusion_entity_collection != nullptr)
extrusionentity_to_verts(*extrusion_entity_collection, print_z, copy, volume);
else {
CONFESS("Unexpected extrusion_entity type in to_verts()");
throw std::runtime_error("Unexpected extrusion_entity type in to_verts()");
}
}
}

View File

@ -7,6 +7,7 @@
// Print now includes tbb, and tbb includes Windows. This breaks compilation of wxWidgets if included before wx.
#include "../../libslic3r/Print.hpp"
#include "../../libslic3r/Utils.hpp"
#include "../../libslic3r/GCode/PostProcessor.hpp"
//#undef NDEBUG

View File

@ -2,7 +2,7 @@
#define slic3r_GLToolbar_hpp_
#include "../../slic3r/GUI/GLTexture.hpp"
#include "../../libslic3r/Utils.hpp"
#include "../../callback.hpp"
#include <string>
#include <vector>

View File

@ -4,7 +4,7 @@
#include <string>
#include <vector>
#include "PrintConfig.hpp"
#include "../../libslic3r/Utils.hpp"
#include "../../callback.hpp"
#include "GUI_ObjectParts.hpp"
#include <wx/intl.h>

View File

@ -4,7 +4,7 @@
#include <memory>
#include <functional>
#include "../../libslic3r/Utils.hpp"
#include "../../callback.hpp"
class wxTimer;
class wxGauge;

View File

@ -209,6 +209,41 @@ SV* to_SV(TriangleMesh* THIS);
// Return a pointer to the associated wxWidgets object instance given by classname.
extern void* wxPli_sv_2_object( pTHX_ SV* scalar, const char* classname );
inline void confess_at(const char *file, int line, const char *func, const char *pat, ...)
{
#ifdef SLIC3RXS
va_list args;
SV *error_sv = newSVpvf("Error in function %s at %s:%d: ", func,
file, line);
va_start(args, pat);
sv_vcatpvf(error_sv, pat, &args);
va_end(args);
sv_catpvn(error_sv, "\n\t", 2);
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs( sv_2mortal(error_sv) );
PUTBACK;
call_pv("Carp::confess", G_DISCARD);
FREETMPS;
LEAVE;
#endif
}
#ifndef CONFESS
/* Implementation of CONFESS("foo"): */
#ifdef _MSC_VER
#define CONFESS(...) confess_at(__FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
#else
#define CONFESS(...) confess_at(__FILE__, __LINE__, __func__, __VA_ARGS__)
#endif
/* End implementation of CONFESS("foo"): */
#endif /* CONFESS */
using namespace Slic3r;
#endif