Yoba Perl
perl_stack.cpp
1 #include "yobaperl/perl_stack.hpp"
2 #include "yobaperl/perl.hpp"
3 
4 namespace yoba { namespace priv {
5 
6 
7 
8 PerlStack::PerlStack(Perl & perl)
9  : _perl(perl),
10  _interpreter(perl.getInterpreter()),
11  sp(PL_stack_sp)
12 {
13  ENTER;
14  SAVETMPS;
15  PUSHMARK(SP);
16 }
17 
18 PerlStack::~PerlStack()
19 {
20  PUTBACK;
21  FREETMPS;
22  LEAVE;
23 }
24 
25 
26 
27 void PerlStack::extend(ssize_t size)
28 {
29  EXTEND(SP, size);
30 }
31 
32 void PerlStack::pushSV(SV * sv, bool extend)
33 {
34  if(extend)
35  XPUSHs(sv);
36  else
37  PUSHs(sv);
38 }
39 
40 SV * PerlStack::popSV()
41 {
42  return POPs;
43 }
44 
45 void PerlStack::pushScalar(Scalar arg)
46 {
47  pushSV(arg.detachMortalSV(), /*extend*/true);
48 }
49 
50 void PerlStack::pushArray(Array args)
51 {
52  extend(args.getSize());
53  for(int i = 0; i < args.getSize(); i++)
54  pushSV(args[i].detachMortalSV(), /*extend*/false);
55 }
56 
57 Scalar PerlStack::popScalar()
58 {
59  YOBAPERL_ASSERT(_returns_count == 1);
60  return Scalar(_perl, popSV(), /*ref++*/true);
61 }
62 
63 Array PerlStack::popArray()
64 {
65  YOBAPERL_ASSERT(_returns_count != -1);
66 
67  AV * result = av_make(_returns_count, SP - _returns_count + 1);
68  SP -= _returns_count;
69  return Array(_perl, result, /*ref++*/false);
70 }
71 
72 void PerlStack::call(Code code, I32 flags)
73 {
74  PUTBACK;
75  _returns_count = call_sv(code.detachSV(), flags);
76  SPAGAIN;
77 
78  if(_perl.hasError())
79  {
80  if(_returns_count > 0)
81  POPs;
82 
83  if(_perl.isExceptionsEnabled())
84  throw PerlException(_perl.getId(), _perl.getError());
85 
86  if(_perl.isWarningsEnabled())
87  warn("%s", _perl.getError().c_str());
88  }
89 }
90 
91 void PerlStack::callMethod(Code code, I32 flags)
92 {
93  PUTBACK;
94 // _returns_count = call_method(sub_name.c_str(), flags);
95 
96 
97  _returns_count = call_sv(code.detachSV(), flags | G_METHOD);
98  SPAGAIN;
99 
100  if(_perl.hasError())
101  {
102  if(_returns_count > 0)
103  POPs;
104 
105  if(_perl.isExceptionsEnabled())
106  throw PerlException(_perl.getId(), _perl.getError());
107 
108  if(_perl.isWarningsEnabled())
109  warn("%s", _perl.getError().c_str());
110  }
111 }
112 
113 void PerlStack::eval(const std::string & code, I32 flags)
114 {
115  // Prevent segfault
116 #ifdef YOBAPERL_MULTIPLICITY
117  _perl.setContext();
118 #endif
119 
120  // YobaPerl::call() may throw exceptions inside eval
121  try
122  {
123  _returns_count = eval_sv(_perl.newScalar(code).detachMortalSV(), flags);
124  SPAGAIN;
125  }
126  catch(const PerlException & e)
127  {
128  // Add code string and rethrow
129  throw PerlException(e.getPerlId(), e.getInfo(), code);
130  }
131 
132  if(_perl.hasError())
133  {
134  if(_returns_count > 0)
135  POPs;
136 
137  if(_perl.isExceptionsEnabled())
138  throw PerlException(_perl.getId(), _perl.getError(), code);
139 
140  if(_perl.isWarningsEnabled())
141  warn("%s\nCode:\n%s", _perl.getError().c_str(), code.c_str());
142  }
143 }
144 
145 
146 
147 }} // namespace yoba::priv
Definition: array.cpp:5