ebb12636ac2cc65ce91c353fa18cec2871b5e0b5
[blender.git] / source / gameengine / Expressions / Value.cpp
1 // Value.cpp: implementation of the CValue class.
2 // developed at Eindhoven University of Technology, 1997
3 // by the OOPS team
4 //////////////////////////////////////////////////////////////////////
5 /*
6  * Copyright (c) 1996-2000 Erwin Coumans <coockie@acm.org>
7  *
8  * Permission to use, copy, modify, distribute and sell this software
9  * and its documentation for any purpose is hereby granted without fee,
10  * provided that the above copyright notice appear in all copies and
11  * that both that copyright notice and this permission notice appear
12  * in supporting documentation.  Erwin Coumans makes no
13  * representations about the suitability of this software for any
14  * purpose.  It is provided "as is" without express or implied warranty.
15  *
16  */
17 #include "Value.h"
18 #include "FloatValue.h"
19 #include "IntValue.h"
20 #include "VectorValue.h"
21 #include "VoidValue.h"
22 #include "StringValue.h"
23 #include "ErrorValue.h"
24 #include "ListValue.h"
25
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
29
30 //////////////////////////////////////////////////////////////////////
31 // Construction/Destruction
32 //////////////////////////////////////////////////////////////////////
33
34 double CValue::m_sZeroVec[3] = {0.0,0.0,0.0};
35 bool CValue::m_ignore_deprecation_warnings(false);
36
37 #ifndef NO_EXP_PYTHON_EMBEDDING
38
39 PyObject* cvalue_add(PyObject*v, PyObject*w)
40 {
41         return  ((CValue*)v)->Calc(VALUE_ADD_OPERATOR,(CValue*)w);
42 }
43 PyObject* cvalue_sub(PyObject*v, PyObject*w)
44 {
45         return  ((CValue*)v)->Calc(VALUE_SUB_OPERATOR,(CValue*)w);
46 }
47 PyObject* cvalue_mul(PyObject*v, PyObject*w)
48 {
49         return  ((CValue*)v)->Calc(VALUE_MUL_OPERATOR,(CValue*)w);
50 }
51 PyObject* cvalue_div(PyObject*v, PyObject*w)
52 {
53         return  ((CValue*)v)->Calc(VALUE_DIV_OPERATOR,(CValue*)w);
54 }
55 PyObject* cvalue_mod(PyObject*v, PyObject*w)
56 {
57         return  ((CValue*)v)->Calc(VALUE_MOD_OPERATOR,(CValue*)w);
58 }
59 PyObject* cvalue_neg(PyObject*v)
60 {
61         return  ((CValue*)v)->Calc(VALUE_NEG_OPERATOR,(CValue*)v);
62 }
63 PyObject* cvalue_pos(PyObject*v)
64 {
65         return  ((CValue*)v)->Calc(VALUE_POS_OPERATOR,(CValue*)v);
66 }
67
68
69 int MyPyCompare (PyObject* v,PyObject* w)
70 {
71         CValue* eqval =  ((CValue*)v)->Calc(VALUE_EQL_OPERATOR,(CValue*)w);
72         STR_String txt = eqval->GetText();
73         eqval->Release();
74         if (txt=="TRUE")
75                 return 0;
76         CValue* lessval =  ((CValue*)v)->Calc(VALUE_LES_OPERATOR,(CValue*)w);
77         txt = lessval->GetText();
78         lessval->Release();
79         if (txt=="TRUE")
80                 return -1;
81
82         return 1;
83 }
84
85
86 int cvalue_coerce(PyObject** pv,PyObject** pw)
87 {
88         if (PyInt_Check(*pw)) {
89                 double db  = (double)PyInt_AsLong(*pw);
90                 *pw = new CIntValue((int) db);
91                 Py_INCREF(*pv);
92                 return 0;
93         }
94         else if (PyLong_Check(*pw)) {
95                 double db = PyLong_AsDouble(*pw);
96                 *pw = new CFloatValue(db);
97                 Py_INCREF(*pv);
98                 return 0;
99         }
100         else if (PyFloat_Check(*pw)) {
101                 double db = PyFloat_AsDouble(*pw);
102                 *pw = new CFloatValue(db);
103                 Py_INCREF(*pv);
104                 return 0;
105         } else if (PyString_Check(*pw)) {
106                 const STR_String str = PyString_AsString(*pw);
107                 *pw = new CStringValue(str,"");
108                 Py_INCREF(*pv);
109                 return 0;
110         }
111         return 1; /* Can't do it */
112
113 }
114 static PyNumberMethods cvalue_as_number = {
115         (binaryfunc)cvalue_add, /*nb_add*/
116         (binaryfunc)cvalue_sub, /*nb_subtract*/
117         (binaryfunc)cvalue_mul, /*nb_multiply*/
118         (binaryfunc)cvalue_div, /*nb_divide*/
119         (binaryfunc)cvalue_mod, /*nb_remainder*/
120         0,//(binaryfunc)cvalue_divmod,  /*nb_divmod*/
121         0,//0,//0,//0,//(ternaryfunc)cvalue_pow, /*nb_power*/
122         (unaryfunc)cvalue_neg, /*nb_negative*/
123         0,//(unaryfunc)cvalue_pos, /*nb_positive*/
124         0,//(unaryfunc)cvalue_abs, /*nb_absolute*/
125         0,//(inquiry)cvalue_nonzero, /*nb_nonzero*/
126         0,              /*nb_invert*/
127         0,              /*nb_lshift*/
128         0,              /*nb_rshift*/
129         0,              /*nb_and*/
130         0,              /*nb_xor*/
131         0,              /*nb_or*/
132         (coercion)cvalue_coerce, /*nb_coerce*/
133         0,//(unaryfunc)cvalue_int, /*nb_int*/
134         0,//(unaryfunc)cvalue_long, /*nb_long*/
135         0,//(unaryfunc)cvalue_float, /*nb_float*/
136         0,              /*nb_oct*/
137         0,              /*nb_hex*/
138 };
139
140
141 PyTypeObject CValue::Type = {
142         PyObject_HEAD_INIT(&PyType_Type)
143         0,
144         "CValue",
145         sizeof(CValue),
146         0,
147         PyDestructor,
148         0,
149         __getattr,
150         __setattr,
151         &MyPyCompare,
152         __repr,
153         &cvalue_as_number,
154         0,
155         0,
156         0,
157         0
158 };
159
160 PyParentObject CValue::Parents[] = {
161         &CValue::Type,
162                 NULL
163 };
164
165 PyMethodDef CValue::Methods[] = {
166 //      { "printHello", (PyCFunction) CValue::sPyPrintHello, METH_VARARGS},
167         { "getName", (PyCFunction) CValue::sPyGetName, METH_NOARGS},
168         {NULL,NULL} //Sentinel
169 };
170
171 PyObject* CValue::PyGetName(PyObject* self)
172 {
173         return PyString_FromString(this->GetName());
174 }
175
176 /*#define CVALUE_DEBUG*/
177 #ifdef CVALUE_DEBUG
178 int gRefCount;
179 struct SmartCValueRef 
180 {
181         CValue *m_ref;
182         int m_count;
183         SmartCValueRef(CValue *ref)
184         {
185                 m_ref = ref;
186                 m_count = gRefCount++;
187         }
188 };
189
190 #include <vector>
191
192 std::vector<SmartCValueRef> gRefList;
193 #endif
194
195 #ifdef _DEBUG
196 //int gRefCountValue;
197 #endif
198
199 CValue::CValue(PyTypeObject *T)
200                 : PyObjectPlus(T),
201 #else
202 CValue::CValue()
203
204 #endif //NO_EXP_PYTHON_EMBEDDING
205         
206 m_pNamedPropertyArray(NULL),
207 m_refcount(1)
208 /*
209 pre: false
210 effect: constucts a CValue
211 */
212 {
213         //debug(gRefCountValue++)       // debugging
214 #ifdef _DEBUG
215         //gRefCountValue++;
216 #ifdef CVALUE_DEBUG
217         gRefList.push_back(SmartCValueRef(this));
218 #endif
219 #endif
220 }
221
222
223
224 CValue::~CValue()
225 /*
226 pre:
227 effect: deletes the object
228 */
229 {
230         ClearProperties();
231
232         assertd (m_refcount==0);
233 #ifdef CVALUE_DEBUG
234         std::vector<SmartCValueRef>::iterator it;
235         for (it=gRefList.begin(); it!=gRefList.end(); it++)
236         {
237                 if (it->m_ref == this)
238                 {
239                         *it = gRefList.back();
240                         gRefList.pop_back();
241                         break;
242                 }
243         }
244 #endif
245 }
246
247
248
249
250 #define VALUE_SUB(val1, val2) (val1)->Calc(VALUE_SUB_OPERATOR, val2)
251 #define VALUE_MUL(val1, val2) (val1)->Calc(VALUE_MUL_OPERATOR, val2)
252 #define VALUE_DIV(val1, val2) (val1)->Calc(VALUE_DIV_OPERATOR, val2)
253 #define VALUE_NEG(val1)       (val1)->Calc(VALUE_NEG_OPERATOR, val1)
254 #define VALUE_POS(val1)       (val1)->Calc(VALUE_POS_OPERATOR, val1)
255
256
257 STR_String CValue::op2str (VALUE_OPERATOR op)
258 {
259         //pre:
260         //ret: the stringrepresentation of operator op
261         
262         STR_String opmsg;
263         switch (op) {
264         case VALUE_MOD_OPERATOR:
265                 opmsg = " % ";
266                 break;
267         case VALUE_ADD_OPERATOR:
268                 opmsg = " + ";
269                 break;
270         case VALUE_SUB_OPERATOR:
271                 opmsg = " - ";
272                 break;
273         case VALUE_MUL_OPERATOR:
274                 opmsg = " * ";
275                 break;
276         case VALUE_DIV_OPERATOR:
277                 opmsg = " / ";
278                 break;
279         case VALUE_NEG_OPERATOR:
280                 opmsg = " -";
281                 break;
282         case VALUE_POS_OPERATOR:
283                 opmsg = " +";
284                 break;
285         case VALUE_AND_OPERATOR:
286                 opmsg = " & ";
287                 break;
288         case VALUE_OR_OPERATOR:
289                 opmsg = " | ";
290                 break;
291         case VALUE_EQL_OPERATOR:
292                 opmsg = " = ";
293                 break;
294         case VALUE_NEQ_OPERATOR:
295                 opmsg = " != ";
296                 break;
297         case VALUE_NOT_OPERATOR:
298                 opmsg = " !";
299                 break;
300         default:
301                 opmsg="Error in Errorhandling routine.";
302                 //              AfxMessageBox("Invalid operator");
303                 break;
304         }
305         return opmsg;
306 }
307
308
309
310
311
312 //---------------------------------------------------------------------------------------------------------------------
313 //      Property Management
314 //---------------------------------------------------------------------------------------------------------------------
315
316
317
318 //
319 // Set property <ioProperty>, overwrites and releases a previous property with the same name if needed
320 //
321 void CValue::SetProperty(const STR_String & name,CValue* ioProperty)
322 {
323         // Check if somebody is setting an empty property
324         if (ioProperty==NULL)
325         {
326                 trace("Warning:trying to set empty property!");
327                 return;
328         }
329
330         // Make sure we have a property array
331         if (m_pNamedPropertyArray == NULL)
332                 m_pNamedPropertyArray = new std::map<STR_String,CValue *>;
333
334         // Try to replace property (if so -> exit as soon as we replaced it)
335         CValue* oldval = (*m_pNamedPropertyArray)[name];
336         if (oldval)
337         {
338                 oldval->Release();
339         }
340         
341         // Add property at end of array
342         (*m_pNamedPropertyArray)[name] = ioProperty->AddRef();//->Add(ioProperty);
343 }
344
345
346
347 //
348 // Get pointer to a property with name <inName>, returns NULL if there is no property named <inName>
349 //
350 CValue* CValue::GetProperty(const STR_String & inName)
351 {
352         // Check properties, as soon as we found it -> Return a pointer to the property
353         CValue* result = NULL;
354         if (m_pNamedPropertyArray)
355         {
356                 std::map<STR_String,CValue*>::iterator it = (*m_pNamedPropertyArray).find(inName);
357                 if (!( it==m_pNamedPropertyArray->end()))
358                 {
359                         result = (*it).second;
360                 }
361
362         }
363                 //for (int i=0; i<m_pValuePropertyArray->size(); i++)
364                 //      if ((*m_pValuePropertyArray)[i]->GetName() == inName)
365                 //              return (*m_pValuePropertyArray)[i];
366         
367         // Did not find property with name <inName>, return NULL property pointer
368         return result;
369 }
370
371
372
373 //
374 // Get text description of property with name <inName>, returns an empty string if there is no property named <inName>
375 //
376 STR_String CValue::GetPropertyText(const STR_String & inName,const STR_String& deftext)
377 {
378         CValue *property = GetProperty(inName);
379         if (property)
380                 return property->GetText();
381         else
382                 return deftext;//String::sEmpty;
383 }
384
385 float CValue::GetPropertyNumber(const STR_String& inName,float defnumber)
386 {
387         CValue *property = GetProperty(inName);
388         if (property)
389                 return property->GetNumber();
390         else
391                 return defnumber;
392 }
393
394
395
396 //
397 // Remove the property named <inName>, returns true if the property was succesfully removed, false if property was not found or could not be removed
398 //
399 bool CValue::RemoveProperty(const STR_String & inName)
400 {
401         // Check if there are properties at all which can be removed
402         if (m_pNamedPropertyArray) {    
403                 CValue* val = GetProperty(inName);
404                 if (NULL != val) 
405                 {
406                         val->Release();
407                         m_pNamedPropertyArray->erase(inName);
408                         return true;
409                 }
410         } 
411         
412         char err[128];
413         if (m_pNamedPropertyArray)
414                 sprintf(err, "attribute \"%s\" dosnt exist", inName.ReadPtr());
415         else
416                 sprintf(err, "attribute \"%s\" dosnt exist (no property array)", inName.ReadPtr());
417         
418         PyErr_SetString(PyExc_AttributeError, err);
419         return false;
420 }
421
422 //
423 // Get Property Names
424 //
425 vector<STR_String> CValue::GetPropertyNames()
426 {
427         vector<STR_String> result;
428         if(!m_pNamedPropertyArray) return result;
429         for ( std::map<STR_String,CValue*>::iterator it = m_pNamedPropertyArray->begin();
430         !(it == m_pNamedPropertyArray->end());it++)
431         {
432                 result.push_back((*it).first);
433         }
434         return result;
435 }
436
437 //
438 // Clear all properties
439 //
440 void CValue::ClearProperties()
441 {               
442         // Check if we have any properties
443         if (m_pNamedPropertyArray == NULL)
444                 return;
445
446         // Remove all properties
447         for ( std::map<STR_String,CValue*>::iterator it = m_pNamedPropertyArray->begin();
448         !(it == m_pNamedPropertyArray->end());it++)
449         {
450                 CValue* tmpval = (*it).second;
451                 //STR_String name = (*it).first;
452                 tmpval->Release();
453         }
454
455         // Delete property array
456         delete m_pNamedPropertyArray;
457         m_pNamedPropertyArray=NULL;
458 }
459
460
461
462 //
463 // Set all properties' modified flag to <inModified>
464 //
465 void CValue::SetPropertiesModified(bool inModified)
466 {
467         int numprops = GetPropertyCount();
468         for (int i=0; i<numprops; i++)
469                 GetProperty(i)->SetModified(inModified);
470 }
471
472
473
474 //
475 // Check if any of the properties in this value have been modified
476 //
477 bool CValue::IsAnyPropertyModified()
478 {
479         int numprops = GetPropertyCount();
480         for (int i=0;i<numprops;i++)
481                 if (GetProperty(i)->IsModified())
482                         return true;
483
484         return false;
485 }
486
487
488
489 //
490 // Get property number <inIndex>
491 //
492
493 CValue* CValue::GetProperty(int inIndex)
494 {
495
496         int count=0;
497         CValue* result = NULL;
498
499         if (m_pNamedPropertyArray)
500         {
501                 for ( std::map<STR_String,CValue*>::iterator it = m_pNamedPropertyArray->begin();
502                 !(it == m_pNamedPropertyArray->end());it++)
503                 {
504                         if (count++==inIndex)
505                         {
506                                 result = (*it).second;
507                                 break;
508                         }
509                 }
510
511         }
512         return result;
513 }
514
515
516
517 //
518 // Get the amount of properties assiocated with this value
519 //
520 int CValue::GetPropertyCount()
521 {
522         if (m_pNamedPropertyArray)
523                 return m_pNamedPropertyArray->size();
524         else
525                 return 0;
526 }
527
528
529
530
531
532 void CValue::CloneProperties(CValue *replica)
533 {
534         
535         if (m_pNamedPropertyArray)
536         {
537                 replica->m_pNamedPropertyArray=NULL;
538                 for ( std::map<STR_String,CValue*>::iterator it = m_pNamedPropertyArray->begin();
539                 !(it == m_pNamedPropertyArray->end());it++)
540                 {
541                         CValue *val = (*it).second->GetReplica();
542                         replica->SetProperty((*it).first,val);
543                         val->Release();
544                 }
545         }
546
547         
548 }
549
550 double*         CValue::GetVector3(bool bGetTransformedVec)
551 {
552         assertd(false); // don;t get vector from me
553         return m_sZeroVec;//::sZero;
554 }
555
556
557 /*---------------------------------------------------------------------------------------------------------------------
558         Reference Counting
559 ---------------------------------------------------------------------------------------------------------------------*/
560 //
561 // Add a reference to this value
562 //
563 CValue *CValue::AddRef()
564 {
565         // Increase global reference count, used to see at the end of the program
566         // if all CValue-derived classes have been dereferenced to 0
567         //debug(gRefCountValue++);
568 #ifdef _DEBUG
569         //gRefCountValue++;
570 #endif
571         m_refcount++; 
572         return this;
573 }
574
575
576
577 //
578 // Release a reference to this value (when reference count reaches 0, the value is removed from the heap)
579 //
580 int     CValue::Release()
581 {
582         // Decrease global reference count, used to see at the end of the program
583         // if all CValue-derived classes have been dereferenced to 0
584         //debug(gRefCountValue--);
585 #ifdef _DEBUG
586         //gRefCountValue--;
587 #endif
588         // Decrease local reference count, if it reaches 0 the object should be freed
589         if (--m_refcount > 0)
590         {
591                 // Reference count normal, return new reference count
592                 return m_refcount;
593         }
594         else
595         {
596                 // Reference count reached 0, delete ourselves and return 0
597 //              MT_assert(m_refcount==0, "Reference count reached sub-zero, object released too much");
598                 delete this;
599                 return 0;
600         }
601
602 }
603
604
605
606 //
607 // Disable reference counting for this value
608 //
609 void CValue::DisableRefCount()
610 {
611         assertd(m_refcount == 1);
612         m_refcount--;
613
614         //debug(gRefCountValue--);
615 #ifdef _DEBUG
616         //gRefCountValue--;
617 #endif
618         m_ValFlags.RefCountDisabled=true;
619 }
620
621
622
623 void CValue::AddDataToReplica(CValue *replica)
624 {
625         replica->m_refcount = 1;
626
627         //register with Python
628         _Py_NewReference(replica);
629
630 #ifdef _DEBUG
631         //gRefCountValue++;
632 #endif
633         replica->m_ValFlags.RefCountDisabled = false;
634
635         replica->ReplicaSetName(GetName());
636
637         //copy all props
638         CloneProperties(replica);
639 }
640
641
642
643 CValue* CValue::FindIdentifier(const STR_String& identifiername)
644 {
645
646         CValue* result = NULL;
647
648         int pos = 0;
649         // if a dot exists, explode the name into pieces to get the subcontext
650         if ((pos=identifiername.Find('.'))>=0)
651         {
652                 const STR_String rightstring = identifiername.Right(identifiername.Length() -1 - pos);
653                 const STR_String leftstring = identifiername.Left(pos);
654                 CValue* tempresult = GetProperty(leftstring);
655                 if (tempresult)
656                 {
657                         result=tempresult->FindIdentifier(rightstring);
658                 } 
659         } else
660         {
661                 result = GetProperty(identifiername);
662                 if (result)
663                         return result->AddRef();
664         }
665         if (!result)
666         {
667                 // warning here !!!
668                 result = new CErrorValue(identifiername+" not found");
669         }
670         return result;
671 }
672
673
674 #ifndef NO_EXP_PYTHON_EMBEDDING
675
676
677 static PyMethodDef      CValueMethods[] = 
678 {
679         //{ "new", CValue::PyMake , METH_VARARGS},
680         { NULL,NULL}    // Sentinel
681 };
682
683 PyAttributeDef CValue::Attributes[] = {
684         { NULL }        //Sentinel
685 };
686
687
688 PyObject*       CValue::_getattr(const char *attr)
689 {
690         CValue* resultattr = FindIdentifier(STR_String(attr));
691         STR_String text;
692         if (resultattr)
693         {
694                 if (resultattr->IsError())
695                 {
696                         resultattr->Release();
697                 } else
698                 {
699                         // to avoid some compare problems, return a real pythonthing
700                         PyObject* pyconvert = resultattr->ConvertValueToPython();
701                         if (pyconvert)
702                         {
703                                 resultattr->Release();
704                                 return pyconvert;
705                         } else
706                         {
707                                 // also check if it's already in pythoninterpreter!
708                                 return resultattr;
709                         }
710                         
711                 }
712         }
713         _getattr_up(PyObjectPlus);
714 }
715
716 CValue* CValue::ConvertPythonToValue(PyObject* pyobj)
717 {
718
719         CValue* vallie = NULL;
720
721         if (PyList_Check(pyobj))
722         {
723                 CListValue* listval = new CListValue();
724                 bool error = false;
725
726                 int i;
727                 int numitems = PyList_Size(pyobj);
728                 for (i=0;i<numitems;i++)
729                 {
730                         PyObject* listitem = PyList_GetItem(pyobj,i); /* borrowed ref */
731                         CValue* listitemval = ConvertPythonToValue(listitem);
732                         if (listitemval)
733                         {
734                                 listval->Add(listitemval);
735                         } else
736                         {
737                                 error = true;
738                         }
739                 }
740                 if (!error)
741                 {
742                         // jippie! could be converted
743                         vallie = listval;
744                 } else
745                 {
746                         // list could not be converted... bad luck
747                         listval->Release();
748                 }
749
750         } else
751         if (PyFloat_Check(pyobj))
752         {
753                 vallie = new CFloatValue( (float)PyFloat_AsDouble(pyobj) );
754         } else
755         if (PyInt_Check(pyobj))
756         {
757                 vallie = new CIntValue( (int)PyInt_AS_LONG(pyobj) );
758         } else
759         if (PyString_Check(pyobj))
760         {
761                 vallie = new CStringValue(PyString_AsString(pyobj),"");
762         } else
763         if (pyobj->ob_type==&CValue::Type || pyobj->ob_type==&CListValue::Type)
764         {
765                 vallie = ((CValue*) pyobj)->AddRef();
766         } else
767         {
768                 /* return an error value from the caller */
769                 PyErr_SetString(PyExc_TypeError, "This python value could not be assigned to a game engine property");
770         }
771         return vallie;
772
773 }
774
775 int     CValue::_delattr(const char *attr)
776 {
777         if (!RemoveProperty(STR_String(attr))) /* sets error */
778                 return 1;
779         return 0;
780 }
781
782 int     CValue::_setattr(const char *attr,PyObject* pyobj)
783 {
784         CValue* vallie = ConvertPythonToValue(pyobj);
785         if (vallie)
786         {
787                 STR_String attr_str = attr;
788                 CValue* oldprop = GetProperty(attr_str);
789                 
790                 if (oldprop)
791                 {
792                         oldprop->SetValue(vallie);
793                 } else
794                 {
795                         SetProperty(attr_str, vallie);
796                 }
797                 vallie->Release();
798         } else
799         {
800                 return 1; /* ConvertPythonToValue sets the error message */
801         }
802         
803         //PyObjectPlus::_setattr(attr,value);
804         return 0;
805 };
806
807 PyObject*       CValue::ConvertKeysToPython( void )
808 {
809         PyObject *pylist = PyList_New( 0 );
810         PyObject *pystr;
811         
812         if (m_pNamedPropertyArray)
813         {
814                 for ( std::map<STR_String,CValue*>::iterator it = m_pNamedPropertyArray->begin();
815                 !(it == m_pNamedPropertyArray->end());it++)
816                 {
817                         pystr = PyString_FromString( (*it).first );
818                         PyList_Append(pylist, pystr);
819                         Py_DECREF( pystr );
820                 }
821         }
822         return pylist;
823 }
824
825 /*
826 PyObject*       CValue::PyMake(PyObject* ignored,PyObject* args)
827 {
828
829         //if (!PyArg_ParseTuple(args,"s",&name)) return NULL;
830         Py_RETURN_NONE;//new CValue();
831 }
832 */
833
834 extern "C" {
835         void initCValue(void)
836         {
837                 Py_InitModule("CValue",CValueMethods);
838         }
839 }
840
841
842
843 #endif //NO_EXP_PYTHON_EMBEDDING
844
845 ///////////////////////////////////////////////////////////////////////////////////////////////
846 ///////////////////////////////////////////////////////////////////////////////////////////////
847 /* These implementations were moved out of the header */
848
849 void CValue::SetOwnerExpression(class CExpression* expr)
850 {
851         /* intentionally empty */
852 }
853
854 void CValue::SetColorOperator(VALUE_OPERATOR op)
855 {
856         /* intentionally empty */
857 }
858 void CValue::SetValue(CValue* newval)
859
860         // no one should get here
861         assertd(newval->GetNumber() == 10121969);       
862 }
863 ///////////////////////////////////////////////////////////////////////////////////////////////
864 ///////////////////////////////////////////////////////////////////////////////////////////////
865 /* deprecation warning management */
866 void CValue::SetDeprecationWarnings(bool ignoreDeprecationWarnings)
867 {
868         m_ignore_deprecation_warnings = ignoreDeprecationWarnings;
869 }
870
871 void CValue::ShowDeprecationWarning(const char* old_way,const char* new_way)
872 {
873         if (!m_ignore_deprecation_warnings) {
874                 printf("Method %s is deprecated, please use %s instead.\n", old_way, new_way);
875                 
876                 // import sys; print '\t%s:%d' % (sys._getframe(0).f_code.co_filename, sys._getframe(0).f_lineno)
877                 
878                 PyObject *getframe, *frame;
879                 PyObject *f_lineno, *f_code, *co_filename;
880                 
881                 getframe = PySys_GetObject("_getframe"); // borrowed
882                 if (getframe) {
883                         frame = PyObject_CallObject(getframe, NULL);
884                         if (frame) {
885                                 f_lineno= PyObject_GetAttrString(frame, "f_lineno");
886                                 f_code= PyObject_GetAttrString(frame, "f_code");
887                                 if (f_lineno && f_code) {
888                                         co_filename= PyObject_GetAttrString(f_code, "co_filename");
889                                         if (co_filename) {
890                                                 
891                                                 printf("\t%s:%d\n", PyString_AsString(co_filename), (int)PyInt_AsLong(f_lineno));
892                                                 
893                                                 Py_DECREF(f_lineno);
894                                                 Py_DECREF(f_code);
895                                                 Py_DECREF(co_filename);
896                                                 Py_DECREF(frame);
897                                                 return;
898                                         }
899                                 }
900                                 
901                                 Py_XDECREF(f_lineno);
902                                 Py_XDECREF(f_code);
903                                 Py_DECREF(frame);
904                         }
905                         
906                 }
907                 PyErr_Clear();
908                 printf("\tERROR - Could not access sys._getframe(0).f_lineno or sys._getframe().f_code.co_filename\n");
909         }
910 }
911