Added getitem/setitem access for KX_GameObject
[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         if (ioProperty==NULL)
324         {       // Check if somebody is setting an empty property
325                 trace("Warning:trying to set empty property!");
326                 return;
327         }
328
329         if (m_pNamedPropertyArray)
330         {       // Try to replace property (if so -> exit as soon as we replaced it)
331                 CValue* oldval = (*m_pNamedPropertyArray)[name];
332                 if (oldval)
333                         oldval->Release();
334         }
335         else { // Make sure we have a property array
336                 m_pNamedPropertyArray = new std::map<STR_String,CValue *>;
337         }
338         
339         // Add property at end of array
340         (*m_pNamedPropertyArray)[name] = ioProperty->AddRef();//->Add(ioProperty);
341 }
342
343 void CValue::SetProperty(const char* name,CValue* ioProperty)
344 {
345         if (ioProperty==NULL)
346         {       // Check if somebody is setting an empty property
347                 trace("Warning:trying to set empty property!");
348                 return;
349         }
350
351         if (m_pNamedPropertyArray)
352         {       // Try to replace property (if so -> exit as soon as we replaced it)
353                 CValue* oldval = (*m_pNamedPropertyArray)[name];
354                 if (oldval)
355                         oldval->Release();
356         }
357         else { // Make sure we have a property array
358                 m_pNamedPropertyArray = new std::map<STR_String,CValue *>;
359         }
360         
361         // Add property at end of array
362         (*m_pNamedPropertyArray)[name] = ioProperty->AddRef();//->Add(ioProperty);
363 }
364
365 //
366 // Get pointer to a property with name <inName>, returns NULL if there is no property named <inName>
367 //
368 CValue* CValue::GetProperty(const STR_String & inName)
369 {
370         if (m_pNamedPropertyArray) {
371                 std::map<STR_String,CValue*>::iterator it = m_pNamedPropertyArray->find(inName);
372                 if (it != m_pNamedPropertyArray->end())
373                         return (*it).second;
374         }
375         return NULL;
376 }
377
378 CValue* CValue::GetProperty(const char *inName)
379 {
380         if (m_pNamedPropertyArray) {
381                 std::map<STR_String,CValue*>::iterator it = m_pNamedPropertyArray->find(inName);
382                 if (it != m_pNamedPropertyArray->end())
383                         return (*it).second;
384         }
385         return NULL;
386 }
387
388 //
389 // Get text description of property with name <inName>, returns an empty string if there is no property named <inName>
390 //
391 STR_String CValue::GetPropertyText(const STR_String & inName,const STR_String& deftext)
392 {
393         CValue *property = GetProperty(inName);
394         if (property)
395                 return property->GetText();
396         else
397                 return deftext;//String::sEmpty;
398 }
399
400 float CValue::GetPropertyNumber(const STR_String& inName,float defnumber)
401 {
402         CValue *property = GetProperty(inName);
403         if (property)
404                 return property->GetNumber();
405         else
406                 return defnumber;
407 }
408
409
410
411 //
412 // Remove the property named <inName>, returns true if the property was succesfully removed, false if property was not found or could not be removed
413 //
414 bool CValue::RemoveProperty(const char *inName)
415 {
416         // Check if there are properties at all which can be removed
417         if (m_pNamedPropertyArray)
418         {
419                 std::map<STR_String,CValue*>::iterator it = m_pNamedPropertyArray->find(inName);
420                 if (it != m_pNamedPropertyArray->end())
421                 {
422                         ((*it).second)->Release();
423                         m_pNamedPropertyArray->erase(it);
424                         return true;
425                 }
426         }
427         
428         return false;
429 }
430
431 //
432 // Get Property Names
433 //
434 vector<STR_String> CValue::GetPropertyNames()
435 {
436         vector<STR_String> result;
437         if(!m_pNamedPropertyArray) return result;
438         std::map<STR_String,CValue*>::iterator it;
439         for (it= m_pNamedPropertyArray->begin(); (it != m_pNamedPropertyArray->end()); it++)
440         {
441                 result.push_back((*it).first);
442         }
443         return result;
444 }
445
446 //
447 // Clear all properties
448 //
449 void CValue::ClearProperties()
450 {               
451         // Check if we have any properties
452         if (m_pNamedPropertyArray == NULL)
453                 return;
454
455         // Remove all properties
456         std::map<STR_String,CValue*>::iterator it;
457         for (it= m_pNamedPropertyArray->begin();(it != m_pNamedPropertyArray->end()); it++)
458         {
459                 CValue* tmpval = (*it).second;
460                 //STR_String name = (*it).first;
461                 tmpval->Release();
462         }
463
464         // Delete property array
465         delete m_pNamedPropertyArray;
466         m_pNamedPropertyArray=NULL;
467 }
468
469
470
471 //
472 // Set all properties' modified flag to <inModified>
473 //
474 void CValue::SetPropertiesModified(bool inModified)
475 {
476         if(!m_pNamedPropertyArray) return;
477         std::map<STR_String,CValue*>::iterator it;
478         
479         for (it= m_pNamedPropertyArray->begin();(it != m_pNamedPropertyArray->end()); it++)
480                 ((*it).second)->SetModified(inModified);
481 }
482
483
484
485 //
486 // Check if any of the properties in this value have been modified
487 //
488 bool CValue::IsAnyPropertyModified()
489 {
490         if(!m_pNamedPropertyArray) return false;
491         std::map<STR_String,CValue*>::iterator it;
492         
493         for (it= m_pNamedPropertyArray->begin();(it != m_pNamedPropertyArray->end()); it++)
494                 if (((*it).second)->IsModified())
495                         return true;
496         
497         return false;
498 }
499
500
501
502 //
503 // Get property number <inIndex>
504 //
505 CValue* CValue::GetProperty(int inIndex)
506 {
507
508         int count=0;
509         CValue* result = NULL;
510
511         if (m_pNamedPropertyArray)
512         {
513                 std::map<STR_String,CValue*>::iterator it;
514                 for (it= m_pNamedPropertyArray->begin(); (it != m_pNamedPropertyArray->end()); it++)
515                 {
516                         if (count++==inIndex)
517                         {
518                                 result = (*it).second;
519                                 break;
520                         }
521                 }
522
523         }
524         return result;
525 }
526
527
528
529 //
530 // Get the amount of properties assiocated with this value
531 //
532 int CValue::GetPropertyCount()
533 {
534         if (m_pNamedPropertyArray)
535                 return m_pNamedPropertyArray->size();
536         else
537                 return 0;
538 }
539
540
541
542
543
544 void CValue::CloneProperties(CValue *replica)
545 {
546         
547         if (m_pNamedPropertyArray)
548         {
549                 replica->m_pNamedPropertyArray=NULL;
550                 std::map<STR_String,CValue*>::iterator it;
551                 for (it= m_pNamedPropertyArray->begin(); (it != m_pNamedPropertyArray->end()); it++)
552                 {
553                         CValue *val = (*it).second->GetReplica();
554                         replica->SetProperty((*it).first,val);
555                         val->Release();
556                 }
557         }
558
559         
560 }
561
562 double*         CValue::GetVector3(bool bGetTransformedVec)
563 {
564         assertd(false); // don;t get vector from me
565         return m_sZeroVec;//::sZero;
566 }
567
568
569 /*---------------------------------------------------------------------------------------------------------------------
570         Reference Counting
571 ---------------------------------------------------------------------------------------------------------------------*/
572 //
573 // Add a reference to this value
574 //
575 CValue *CValue::AddRef()
576 {
577         // Increase global reference count, used to see at the end of the program
578         // if all CValue-derived classes have been dereferenced to 0
579         //debug(gRefCountValue++);
580 #ifdef _DEBUG
581         //gRefCountValue++;
582 #endif
583         m_refcount++; 
584         return this;
585 }
586
587
588
589 //
590 // Release a reference to this value (when reference count reaches 0, the value is removed from the heap)
591 //
592 int     CValue::Release()
593 {
594         // Decrease global reference count, used to see at the end of the program
595         // if all CValue-derived classes have been dereferenced to 0
596         //debug(gRefCountValue--);
597 #ifdef _DEBUG
598         //gRefCountValue--;
599 #endif
600         // Decrease local reference count, if it reaches 0 the object should be freed
601         if (--m_refcount > 0)
602         {
603                 // Reference count normal, return new reference count
604                 return m_refcount;
605         }
606         else
607         {
608                 // Reference count reached 0, delete ourselves and return 0
609 //              MT_assert(m_refcount==0, "Reference count reached sub-zero, object released too much");
610                 delete this;
611                 return 0;
612         }
613
614 }
615
616
617
618 //
619 // Disable reference counting for this value
620 //
621 void CValue::DisableRefCount()
622 {
623         assertd(m_refcount == 1);
624         m_refcount--;
625
626         //debug(gRefCountValue--);
627 #ifdef _DEBUG
628         //gRefCountValue--;
629 #endif
630         m_ValFlags.RefCountDisabled=true;
631 }
632
633
634
635 void CValue::AddDataToReplica(CValue *replica)
636 {
637         replica->m_refcount = 1;
638
639         //register with Python
640         _Py_NewReference(replica);
641
642 #ifdef _DEBUG
643         //gRefCountValue++;
644 #endif
645         replica->m_ValFlags.RefCountDisabled = false;
646
647         replica->ReplicaSetName(GetName());
648
649         //copy all props
650         CloneProperties(replica);
651 }
652
653
654
655 CValue* CValue::FindIdentifier(const STR_String& identifiername)
656 {
657
658         CValue* result = NULL;
659
660         int pos = 0;
661         // if a dot exists, explode the name into pieces to get the subcontext
662         if ((pos=identifiername.Find('.'))>=0)
663         {
664                 const STR_String rightstring = identifiername.Right(identifiername.Length() -1 - pos);
665                 const STR_String leftstring = identifiername.Left(pos);
666                 CValue* tempresult = GetProperty(leftstring);
667                 if (tempresult)
668                 {
669                         result=tempresult->FindIdentifier(rightstring);
670                 } 
671         } else
672         {
673                 result = GetProperty(identifiername);
674                 if (result)
675                         return result->AddRef();
676         }
677         if (!result)
678         {
679                 // warning here !!!
680                 result = new CErrorValue(identifiername+" not found");
681         }
682         return result;
683 }
684
685
686 #ifndef NO_EXP_PYTHON_EMBEDDING
687
688
689 static PyMethodDef      CValueMethods[] = 
690 {
691         //{ "new", CValue::PyMake , METH_VARARGS},
692         { NULL,NULL}    // Sentinel
693 };
694
695 PyAttributeDef CValue::Attributes[] = {
696         { NULL }        //Sentinel
697 };
698
699
700 PyObject*       CValue::_getattr(const char *attr)
701 {
702         CValue* resultattr = GetProperty(attr);
703         if (resultattr)
704         {
705                 PyObject* pyconvert = resultattr->ConvertValueToPython();
706         
707                 if (pyconvert)
708                         return pyconvert;
709                 else
710                         return resultattr; // also check if it's already in pythoninterpreter!
711         }
712         _getattr_up(PyObjectPlus);
713 }
714
715 CValue* CValue::ConvertPythonToValue(PyObject* pyobj)
716 {
717
718         CValue* vallie = NULL;
719
720         if (PyList_Check(pyobj))
721         {
722                 CListValue* listval = new CListValue();
723                 bool error = false;
724
725                 int i;
726                 int numitems = PyList_Size(pyobj);
727                 for (i=0;i<numitems;i++)
728                 {
729                         PyObject* listitem = PyList_GetItem(pyobj,i); /* borrowed ref */
730                         CValue* listitemval = ConvertPythonToValue(listitem);
731                         if (listitemval)
732                         {
733                                 listval->Add(listitemval);
734                         } else
735                         {
736                                 error = true;
737                         }
738                 }
739                 if (!error)
740                 {
741                         // jippie! could be converted
742                         vallie = listval;
743                 } else
744                 {
745                         // list could not be converted... bad luck
746                         listval->Release();
747                 }
748
749         } else
750         if (PyFloat_Check(pyobj))
751         {
752                 vallie = new CFloatValue( (float)PyFloat_AsDouble(pyobj) );
753         } else
754         if (PyInt_Check(pyobj))
755         {
756                 vallie = new CIntValue( (int)PyInt_AS_LONG(pyobj) );
757         } else
758         if (PyString_Check(pyobj))
759         {
760                 vallie = new CStringValue(PyString_AsString(pyobj),"");
761         } else
762         if (pyobj->ob_type==&CValue::Type || pyobj->ob_type==&CListValue::Type)
763         {
764                 vallie = ((CValue*) pyobj)->AddRef();
765         } else
766         {
767                 /* return an error value from the caller */
768                 PyErr_SetString(PyExc_TypeError, "This python value could not be assigned to a game engine property");
769         }
770         return vallie;
771
772 }
773
774 int     CValue::_delattr(const char *attr)
775 {
776         if (RemoveProperty(STR_String(attr)))
777                 return 0;
778         
779         PyErr_Format(PyExc_AttributeError, "attribute \"%s\" dosnt exist", attr);
780         return 1;
781 }
782
783 int     CValue::_setattr(const char *attr, PyObject* pyobj)
784 {
785         CValue* vallie = ConvertPythonToValue(pyobj);
786         if (vallie)
787         {
788                 CValue* oldprop = GetProperty(attr);
789                 
790                 if (oldprop)
791                         oldprop->SetValue(vallie);
792                 else
793                         SetProperty(attr, vallie);
794                 
795                 vallie->Release();
796         } else
797         {
798                 return 1; /* ConvertPythonToValue sets the error message */
799         }
800         
801         //PyObjectPlus::_setattr(attr,value);
802         return 0;
803 };
804
805 PyObject*       CValue::ConvertKeysToPython( void )
806 {
807         PyObject *pylist = PyList_New( 0 );
808         PyObject *pystr;
809         
810         if (m_pNamedPropertyArray)
811         {
812                 std::map<STR_String,CValue*>::iterator it;
813                 for (it= m_pNamedPropertyArray->begin(); (it != m_pNamedPropertyArray->end()); it++)
814                 {
815                         pystr = PyString_FromString( (*it).first );
816                         PyList_Append(pylist, pystr);
817                         Py_DECREF( pystr );
818                 }
819         }
820         return pylist;
821 }
822
823 /*
824 PyObject*       CValue::PyMake(PyObject* ignored,PyObject* args)
825 {
826
827         //if (!PyArg_ParseTuple(args,"s",&name)) return NULL;
828         Py_RETURN_NONE;//new CValue();
829 }
830 */
831
832 extern "C" {
833         void initCValue(void)
834         {
835                 Py_InitModule("CValue",CValueMethods);
836         }
837 }
838
839
840
841 #endif //NO_EXP_PYTHON_EMBEDDING
842
843 ///////////////////////////////////////////////////////////////////////////////////////////////
844 ///////////////////////////////////////////////////////////////////////////////////////////////
845 /* These implementations were moved out of the header */
846
847 void CValue::SetOwnerExpression(class CExpression* expr)
848 {
849         /* intentionally empty */
850 }
851
852 void CValue::SetColorOperator(VALUE_OPERATOR op)
853 {
854         /* intentionally empty */
855 }
856 void CValue::SetValue(CValue* newval)
857
858         // no one should get here
859         assertd(newval->GetNumber() == 10121969);       
860 }
861 ///////////////////////////////////////////////////////////////////////////////////////////////
862 ///////////////////////////////////////////////////////////////////////////////////////////////
863 /* deprecation warning management */
864 void CValue::SetDeprecationWarnings(bool ignoreDeprecationWarnings)
865 {
866         m_ignore_deprecation_warnings = ignoreDeprecationWarnings;
867 }
868
869 void CValue::ShowDeprecationWarning(const char* old_way,const char* new_way)
870 {
871         if (!m_ignore_deprecation_warnings) {
872                 printf("Method %s is deprecated, please use %s instead.\n", old_way, new_way);
873                 
874                 // import sys; print '\t%s:%d' % (sys._getframe(0).f_code.co_filename, sys._getframe(0).f_lineno)
875                 
876                 PyObject *getframe, *frame;
877                 PyObject *f_lineno, *f_code, *co_filename;
878                 
879                 getframe = PySys_GetObject("_getframe"); // borrowed
880                 if (getframe) {
881                         frame = PyObject_CallObject(getframe, NULL);
882                         if (frame) {
883                                 f_lineno= PyObject_GetAttrString(frame, "f_lineno");
884                                 f_code= PyObject_GetAttrString(frame, "f_code");
885                                 if (f_lineno && f_code) {
886                                         co_filename= PyObject_GetAttrString(f_code, "co_filename");
887                                         if (co_filename) {
888                                                 
889                                                 printf("\t%s:%d\n", PyString_AsString(co_filename), (int)PyInt_AsLong(f_lineno));
890                                                 
891                                                 Py_DECREF(f_lineno);
892                                                 Py_DECREF(f_code);
893                                                 Py_DECREF(co_filename);
894                                                 Py_DECREF(frame);
895                                                 return;
896                                         }
897                                 }
898                                 
899                                 Py_XDECREF(f_lineno);
900                                 Py_XDECREF(f_code);
901                                 Py_DECREF(frame);
902                         }
903                         
904                 }
905                 PyErr_Clear();
906                 printf("\tERROR - Could not access sys._getframe(0).f_lineno or sys._getframe().f_code.co_filename\n");
907         }
908 }
909