1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "wxexpr.h"
16 // For compilers that support precompilation, includes "wx/wx.h".
17 #include "wx/wxprec.h"
39 #include "wx/wxexpr.h"
41 extern "C" void add_expr(char *);
42 extern "C" void LexFromFile(FILE *fd
);
43 extern "C" void LexFromString(char *buf
);
46 wxExprDatabase
*thewxExprDatabase
= NULL
;
47 wxExprErrorHandler currentwxExprErrorHandler
;
49 wxExpr::wxExpr(const wxString
& functor
)
56 wxExpr
*pfunctor
= new wxExpr(wxExprWord
, functor
);
61 wxExpr::wxExpr(wxExprType the_type
, const wxString
& word_or_string
)
68 value
.word
= copystring((const char *)word_or_string
);
71 value
.string
= copystring((const char *)word_or_string
);
86 wxExpr::wxExpr(wxExprType the_type
, char *word_or_string
, bool allocate
)
93 value
.word
= allocate
? copystring(word_or_string
) : word_or_string
;
96 value
.string
= allocate
? copystring(word_or_string
) : word_or_string
;
111 wxExpr::wxExpr(long the_integer
)
113 type
= wxExprInteger
;
114 value
.integer
= the_integer
;
119 wxExpr::wxExpr(double the_real
)
122 value
.real
= the_real
;
127 wxExpr::wxExpr(wxList
*the_list
)
134 wxExpr
*listExpr
= new wxExpr(wxExprList
);
136 wxNode
*node
= the_list
->First();
139 wxExpr
*expr
= (wxExpr
*)node
->Data();
140 listExpr
->Append(expr
);
148 wxExpr::~wxExpr(void)
159 delete[] value
.string
;
169 wxExpr
*expr
= value
.first
;
172 wxExpr
*expr1
= expr
->next
;
179 case wxExprNull
: break;
183 void wxExpr::Append(wxExpr
*expr
)
193 void wxExpr::Insert(wxExpr
*expr
)
195 expr
->next
= value
.first
;
202 wxExpr
*wxExpr::Copy(void) const
204 // This seems to get round an optimizer bug when
205 // using Watcom C++ 10a in WIN32 compilation mode.
206 // If these lines not present, the type seems to be
207 // interpreted wrongly as an integer.
208 // I don't want to turn optimization off since it's needed
209 // for reading in files quickly.
210 #if defined(__WATCOMC__)
218 return new wxExpr(value
.integer
);
220 return new wxExpr(value
.real
);
222 return new wxExpr(wxExprString
, wxString(value
.string
));
224 return new wxExpr(wxExprWord
, wxString(value
.word
));
227 wxExpr
*expr
= value
.first
;
228 wxExpr
*new_list
= new wxExpr(wxExprList
);
231 wxExpr
*expr2
= expr
->Copy();
232 new_list
->Append(expr2
);
244 // Get the wxExpr (containing (= wxExpr Value) form) for the given word
245 // or string, assuming that we have Attribute=Value, ...
246 wxExpr
*wxExpr::GetAttributeValueNode(const wxString
& word
) const // Use only for a clause or list
248 if (type
!= wxExprList
)
251 wxExpr
*expr
= value
.first
;
254 if (expr
->type
== wxExprList
)
256 wxExpr
*firstNode
= expr
->value
.first
;
257 if ((firstNode
->type
== wxExprWord
) && (firstNode
->value
.word
[0] == '='))
259 wxExpr
*secondNode
= firstNode
->next
;
260 if ((secondNode
->type
== wxExprWord
) &&
261 (strcmp((const char *)word
, secondNode
->value
.word
) == 0))
272 // Get the value (in wxExpr form) for the given word or string, assuming
273 // that we have Attribute=Value, ...
274 wxExpr
*wxExpr::AttributeValue(const wxString
& word
) const // Use only for a clause or list
276 if (type
!= wxExprList
)
279 wxExpr
*attExpr
= GetAttributeValueNode(word
);
280 if (attExpr
&& attExpr
->value
.first
&& attExpr
->value
.first
->next
)
281 return attExpr
->value
.first
->next
->next
;
285 wxString
wxExpr::Functor(void) const // Use only for a clause
287 if ((type
!= wxExprList
) || !value
.first
)
290 if (value
.first
->type
== wxExprWord
)
291 return wxString(value
.first
->value
.word
);
296 bool wxExpr::IsFunctor(const wxString
& f
) const // Use only for a clause
298 if ((type
!= wxExprList
) || !value
.first
)
301 return (value
.first
->type
== wxExprWord
&&
302 (strcmp((const char *)f
, value
.first
->value
.word
) == 0));
305 // Return nth argument of a clause (starting from 1)
306 wxExpr
*wxExpr::Arg(wxExprType theType
, int arg
) const
308 wxExpr
*expr
= value
.first
;
310 for (i
= 1; i
< arg
; i
++)
314 if (expr
&& (expr
->type
== theType
))
320 // Return nth argument of a list expression (starting from zero)
321 wxExpr
*wxExpr::Nth(int arg
) const
323 if (type
!= wxExprList
)
326 wxExpr
*expr
= value
.first
;
328 for (i
= 0; i
< arg
; i
++)
339 // Returns the number of elements in a list expression
340 int wxExpr::Number(void) const
342 if (type
!= wxExprList
)
346 wxExpr
*expr
= value
.first
;
355 void wxExpr::DeleteAttributeValue(const wxString
& attribute
)
357 if (type
!= wxExprList
)
360 wxExpr
*expr
= value
.first
;
361 wxExpr
*lastExpr
= this;
364 if (expr
->type
== wxExprList
)
366 wxExpr
*firstNode
= expr
->value
.first
;
367 if ((firstNode
->type
== wxExprWord
) && (firstNode
->value
.word
[0] == '='))
369 wxExpr
*secondNode
= firstNode
->next
;
370 if ((secondNode
->type
== wxExprWord
) &&
371 (strcmp((const char *)attribute
, secondNode
->value
.word
) == 0))
373 wxExpr
*nextExpr
= expr
->next
;
376 lastExpr
->next
= nextExpr
;
391 void wxExpr::AddAttributeValue(const wxString
& attribute
, wxExpr
*val
)
393 if (type
!= wxExprList
)
395 // cout << "Error! tried to add an attribute-value pair to a nonlist wxExpr expression\n";
398 // Warning - existing code may assume that any existing value
399 // is deleted first. For efficiency, we leave this to the application.
400 // DeleteAttributeValue(attribute);
402 wxExpr
*patt
= new wxExpr(wxExprWord
, attribute
);
403 wxExpr
*pequals
= new wxExpr(wxExprWord
, "=");
405 wxExpr
*listExpr
= new wxExpr(wxExprList
);
407 listExpr
->Append(pequals
);
408 listExpr
->Append(patt
);
409 listExpr
->Append(val
);
414 void wxExpr::AddAttributeValue(const wxString
& attribute
, long val
)
416 if (type
!= wxExprList
)
418 // cout << "Error! tried to add an attribute-value pair to a nonlist wxExpr expression\n";
421 // Warning - existing code may assume that any existing value
422 // is deleted first. For efficiency, we leave this to the application.
423 // DeleteAttributeValue(attribute);
425 wxExpr
*patt
= new wxExpr(wxExprWord
, attribute
);
426 wxExpr
*pval
= new wxExpr(val
);
427 wxExpr
*pequals
= new wxExpr(wxExprWord
, "=");
429 wxExpr
*listExpr
= new wxExpr(wxExprList
);
431 listExpr
->Append(pequals
);
432 listExpr
->Append(patt
);
433 listExpr
->Append(pval
);
438 void wxExpr::AddAttributeValue(const wxString
& attribute
, double val
)
440 if (type
!= wxExprList
)
442 // cout << "Error! tried to add an attribute-value pair to a nonlist wxExpr expression\n";
446 // DeleteAttributeValue(attribute);
447 wxExpr
*patt
= new wxExpr(wxExprWord
, attribute
);
448 wxExpr
*pval
= new wxExpr(val
);
449 wxExpr
*pequals
= new wxExpr(wxExprWord
, "=");
451 wxExpr
*listExpr
= new wxExpr(wxExprList
);
453 listExpr
->Append(pequals
);
454 listExpr
->Append(patt
);
455 listExpr
->Append(pval
);
460 void wxExpr::AddAttributeValueString(const wxString
& attribute
, const wxString
& val
)
462 if (type
!= wxExprList
)
464 // cout << "Error! tried to add an attribute-value pair to a nonlist wxExpr expression\n";
468 // DeleteAttributeValue(attribute);
470 wxExpr
*patt
= new wxExpr(wxExprWord
, attribute
);
471 wxExpr
*pval
= new wxExpr(wxExprString
, val
);
472 wxExpr
*pequals
= new wxExpr(wxExprWord
, "=");
474 wxExpr
*listExpr
= new wxExpr(wxExprList
);
476 listExpr
->Append(pequals
);
477 listExpr
->Append(patt
);
478 listExpr
->Append(pval
);
483 void wxExpr::AddAttributeValueWord(const wxString
& attribute
, const wxString
& val
)
485 if (type
!= wxExprList
)
487 // cout << "Error! tried to add an attribute-value pair to a nonlist wxExpr expression\n";
491 // DeleteAttributeValue(attribute);
493 wxExpr
*patt
= new wxExpr(wxExprWord
, attribute
);
494 wxExpr
*pval
= new wxExpr(wxExprWord
, val
);
495 wxExpr
*pequals
= new wxExpr(wxExprWord
, "=");
497 wxExpr
*listExpr
= new wxExpr(wxExprList
);
499 listExpr
->Append(pequals
);
500 listExpr
->Append(patt
);
501 listExpr
->Append(pval
);
506 void wxExpr::AddAttributeValue(const wxString
& attribute
, wxList
*val
)
508 if (type
!= wxExprList
)
510 // cout << "Error! tried to add an attribute-value pair to a nonlist wxExpr expression\n";
516 // DeleteAttributeValue(attribute);
518 wxExpr
*patt
= new wxExpr(wxExprWord
, attribute
);
519 wxExpr
*pval
= new wxExpr(val
);
520 wxExpr
*pequals
= new wxExpr(wxExprWord
, "=");
522 wxExpr
*listExpr
= new wxExpr(wxExprList
);
524 listExpr
->Append(pequals
);
525 listExpr
->Append(patt
);
526 listExpr
->Append(pval
);
531 void wxExpr::AddAttributeValueStringList(const wxString
& attribute
, wxList
*string_list
)
533 if (type
!= wxExprList
)
535 // cout << "Error! tried to add an attribute-value pair to a nonlist wxExpr expression\n";
541 // DeleteAttributeValue(attribute);
543 // First make a list of wxExpr strings
544 wxExpr
*listExpr
= new wxExpr(wxExprList
);
545 wxNode
*node
= string_list
->First();
548 char *string
= (char *)node
->Data();
549 wxExpr
*expr
= new wxExpr(wxExprString
, wxString(string
));
550 listExpr
->Append(expr
);
554 // Now make an (=, Att, Value) triple
555 wxExpr
*patt
= new wxExpr(wxExprWord
, attribute
);
556 wxExpr
*pequals
= new wxExpr(wxExprWord
, "=");
558 wxExpr
*listExpr2
= new wxExpr(wxExprList
);
560 listExpr2
->Append(pequals
);
561 listExpr2
->Append(patt
);
562 listExpr2
->Append(listExpr
);
567 bool wxExpr::GetAttributeValue(const wxString
& att
, int& var
) const
569 wxExpr
*expr
= AttributeValue(att
);
571 if (expr
&& (expr
->Type() == wxExprInteger
|| expr
->Type() == wxExprReal
))
573 var
= (int)(expr
->IntegerValue());
580 bool wxExpr::GetAttributeValue(const wxString
& att
, long& var
) const
582 wxExpr
*expr
= AttributeValue(att
);
584 if (expr
&& (expr
->Type() == wxExprInteger
|| expr
->Type() == wxExprReal
))
586 var
= expr
->IntegerValue();
593 bool wxExpr::GetAttributeValue(const wxString
& att
, float& var
) const
595 wxExpr
*expr
= AttributeValue(att
);
596 if (expr
&& (expr
->Type() == wxExprInteger
|| expr
->Type() == wxExprReal
))
598 var
= (float) expr
->RealValue();
605 bool wxExpr::GetAttributeValue(const wxString
& att
, double& var
) const
607 wxExpr
*expr
= AttributeValue(att
);
608 if (expr
&& (expr
->Type() == wxExprInteger
|| expr
->Type() == wxExprReal
))
610 var
= expr
->RealValue();
617 bool wxExpr::GetAttributeValue(const wxString
& att
, wxString
& var
) const // Word OR string -> string
619 wxExpr
*expr
= AttributeValue(att
);
620 if (expr
&& expr
->Type() == wxExprWord
)
622 var
= expr
->WordValue();
625 else if (expr
&& expr
->Type() == wxExprString
)
627 var
= expr
->StringValue();
634 bool wxExpr::GetAttributeValue(const wxString
& att
, wxExpr
**var
) const
636 wxExpr
*expr
= AttributeValue(att
);
646 bool wxExpr::GetAttributeValueStringList(const wxString
& att
, wxList
*var
) const
648 wxExpr
*expr
= AttributeValue(att
);
649 if (expr
&& expr
->Type() == wxExprList
)
651 wxExpr
*string_expr
= expr
->value
.first
;
654 if (string_expr
->Type() == wxExprString
)
655 var
->Append((wxObject
*)copystring(string_expr
->StringValue()));
657 string_expr
= string_expr
->next
;
666 void wxExpr::AssignAttributeValue(char *att
, char **var
) const
669 if (GetAttributeValue(att
, str
))
673 *var
= copystring((const char *) str
);
677 void wxExpr::WriteClause(ostream
& stream
) // Write this expression as a top-level clause
679 if (type
!= wxExprList
)
682 wxExpr
*node
= value
.first
;
685 node
->WriteExpr(stream
);
693 node
->WriteExpr(stream
);
695 if (node
) stream
<< ",\n";
702 void wxExpr::WriteExpr(ostream
& stream
) // Write as any other subexpression
704 // This seems to get round an optimizer bug when
705 // using Watcom C++ 10a in WIN32 compilation mode.
706 // If these lines not present, the type seems to be
707 // interpreted wrongly as an integer.
708 // I don't want to turn optimization off since it's needed
709 // for reading in files quickly.
710 #if defined(__WATCOMC__)
719 stream
<< value
.integer
;
724 double f
= value
.real
;
725 /* Now the parser can cope with this.
726 // Prevent printing in 'e' notation. Any better way?
727 if (fabs(f) < 0.00001)
731 sprintf(buf
, "%.6g", f
);
739 int len
= strlen(value
.string
);
740 for (i
= 0; i
< len
; i
++)
742 char ch
= value
.string
[i
];
743 if (ch
== '"' || ch
== '\\')
753 bool quote_it
= FALSE
;
754 int len
= strlen(value
.word
);
755 if ((len
== 0) || (len
> 0 && (value
.word
[0] > 64 && value
.word
[0] < 91)))
760 for (i
= 0; i
< len
; i
++)
761 if ((!isalpha(value
.word
[i
])) && (!isdigit(value
.word
[i
])) &&
762 (value
.word
[i
] != '_'))
763 { quote_it
= TRUE
; i
= len
; }
769 stream
<< value
.word
;
782 wxExpr
*expr
= value
.first
;
784 if ((expr
->Type() == wxExprWord
) && (strcmp(expr
->WordValue(), "=") == 0))
786 wxExpr
*arg1
= expr
->next
;
787 wxExpr
*arg2
= arg1
->next
;
788 arg1
->WriteExpr(stream
);
790 arg2
->WriteExpr(stream
);
797 expr
->WriteExpr(stream
);
799 if (expr
) stream
<< ", ";
806 case wxExprNull
: break;
810 void wxExpr::WriteLispExpr(ostream
& stream
)
816 stream
<< value
.integer
;
821 stream
<< value
.real
;
826 stream
<< "\"" << value
.string
<< "\"";
831 stream
<< value
.word
;
836 wxExpr
*expr
= value
.first
;
841 expr
->WriteLispExpr(stream
);
843 if (expr
) stream
<< " ";
849 case wxExprNull
: break;
854 * wxExpr 'database' (list of expressions)
857 #if !USE_SHARED_LIBRARIES
858 IMPLEMENT_DYNAMIC_CLASS(wxExprDatabase
, wxList
)
861 wxExprDatabase::wxExprDatabase(wxExprErrorHandler handler
)
865 currentwxExprErrorHandler
= handler
;
869 wxExprDatabase::wxExprDatabase(wxExprType type
, const wxString
& attribute
, int size
,
870 wxExprErrorHandler handler
)
873 attribute_to_hash
= attribute
;
874 if (type
== wxExprString
)
875 hash_table
= new wxHashTable(wxKEY_STRING
, size
);
876 else if (type
== wxExprInteger
)
877 hash_table
= new wxHashTable(wxKEY_INTEGER
, size
);
878 else hash_table
= NULL
;
880 currentwxExprErrorHandler
= handler
;
884 wxExprDatabase::~wxExprDatabase(void)
891 void wxExprDatabase::BeginFind(void) // Initialise a search
896 wxExpr
*wxExprDatabase::FindClause(long id
) // Find a term based on an integer id attribute
897 // e.g. node(id=23, type=rectangle, ....).
899 wxExpr
*found
= NULL
;
900 while (position
&& !found
)
902 wxExpr
*term
= (wxExpr
*)position
->Data();
904 if (term
->Type() == wxExprList
)
906 wxExpr
*value
= term
->AttributeValue("id");
907 if (value
->Type() == wxExprInteger
&& value
->IntegerValue() == id
)
910 position
= position
->Next();
915 // Find on basis of attribute/value pairs, e.g. type=rectangle
916 wxExpr
*wxExprDatabase::FindClause(const wxString
& word
, const wxString
& val
)
918 wxExpr
*found
= NULL
;
919 while (position
&& !found
)
921 wxExpr
*term
= (wxExpr
*)position
->Data();
923 if (term
->Type() == wxExprList
)
925 wxExpr
*value
= term
->AttributeValue(word
);
926 if ((value
->Type() == wxExprWord
&& value
->WordValue() == val
) ||
927 (value
->Type() == wxExprString
&& value
->StringValue() == val
))
930 position
= position
->Next();
935 wxExpr
*wxExprDatabase::FindClause(const wxString
& word
, long val
)
937 wxExpr
*found
= NULL
;
938 while (position
&& !found
)
940 wxExpr
*term
= (wxExpr
*)position
->Data();
942 if (term
->Type() == wxExprList
)
944 wxExpr
*value
= term
->AttributeValue(word
);
945 if ((value
->Type() == wxExprInteger
) && (value
->IntegerValue() == val
))
948 position
= position
->Next();
953 wxExpr
*wxExprDatabase::FindClause(const wxString
& word
, double val
)
955 wxExpr
*found
= NULL
;
956 while (position
&& !found
)
958 wxExpr
*term
= (wxExpr
*)position
->Data();
960 if (term
->Type() == wxExprList
)
962 wxExpr
*value
= term
->AttributeValue(word
);
963 if ((value
->Type() == wxExprReal
) && (value
->RealValue() == val
))
966 position
= position
->Next();
971 wxExpr
*wxExprDatabase::FindClauseByFunctor(const wxString
& functor
)
973 wxExpr
*found
= NULL
;
974 while (position
&& !found
)
976 wxExpr
*term
= (wxExpr
*)position
->Data();
978 if (term
->Type() == wxExprList
)
980 if (term
->Functor() == functor
)
983 position
= position
->Next();
988 // If hashing is on, must store in hash table too
989 void wxExprDatabase::Append(wxExpr
*clause
)
991 wxList::Append((wxObject
*)clause
);
994 wxString
functor(clause
->Functor());
995 wxExpr
*expr
= clause
->AttributeValue(attribute_to_hash
);
998 long functor_key
= hash_table
->MakeKey((char *)(const char *)functor
);
1000 if (expr
&& expr
->Type() == wxExprString
)
1002 value_key
= hash_table
->MakeKey((char *)(const char *)expr
->StringValue());
1003 hash_table
->Put(functor_key
+ value_key
, (char *)(const char *)expr
->StringValue(), (wxObject
*)clause
);
1005 else if (expr
&& expr
->Type() == wxExprInteger
)
1007 value_key
= expr
->IntegerValue();
1008 hash_table
->Put(functor_key
+ value_key
, expr
->IntegerValue(), (wxObject
*)clause
);
1015 wxExpr
*wxExprDatabase::HashFind(const wxString
& functor
, long value
) const
1017 long key
= hash_table
->MakeKey((char *)(const char *)functor
) + value
;
1019 // The key alone isn't guaranteed to be unique:
1020 // must supply value too. Let's assume the value of the
1021 // id is going to be reasonably unique.
1022 return (wxExpr
*)hash_table
->Get(key
, value
);
1025 wxExpr
*wxExprDatabase::HashFind(const wxString
& functor
, const wxString
& value
) const
1027 long key
= hash_table
->MakeKey((char *)(const char *)functor
) + hash_table
->MakeKey((char *)(const char *)value
);
1028 return (wxExpr
*)hash_table
->Get(key
, (char *)(const char *)value
);
1031 void wxExprDatabase::ClearDatabase(void)
1034 wxNode
*node
= First();
1037 wxExpr
*expr
= (wxExpr
*)node
->Data();
1044 hash_table
->Clear();
1047 bool wxExprDatabase::Read(const wxString
& filename
)
1051 FILE *f
= fopen((const char *)filename
, "r");
1054 thewxExprDatabase
= this;
1061 return (noErrors
== 0);
1069 bool wxExprDatabase::ReadFromString(const wxString
& buffer
)
1072 thewxExprDatabase
= this;
1074 LexFromString((char *)(const char *)buffer
);
1077 return (noErrors
== 0);
1080 bool wxExprDatabase::Write(const wxString
& fileName
)
1082 ofstream
str((char *)(const char *)fileName
);
1088 bool wxExprDatabase::Write(ostream
& stream
)
1091 wxNode
*node
= First();
1094 wxExpr
*expr
= (wxExpr
*)node
->Data();
1095 expr
->WriteClause(stream
);
1096 node
= node
->Next();
1098 return (noErrors
== 0);
1101 void wxExprDatabase::WriteLisp(ostream
& stream
)
1104 wxNode
*node
= First();
1107 wxExpr
*expr
= (wxExpr
*)node
->Data();
1108 expr
->WriteLispExpr(stream
);
1110 node
= node
->Next();
1114 void add_expr(wxExpr
* expr
)
1116 thewxExprDatabase
->Append(expr
);
1120 bool wxExprIsFunctor(wxExpr
*expr
, const wxString
& functor
)
1122 if (expr
&& (expr
->Type() == wxExprList
))
1124 wxExpr
*first_expr
= expr
->value
.first
;
1126 if (first_expr
&& (first_expr
->Type() == wxExprWord
) &&
1127 (first_expr
->WordValue() == functor
))
1137 * Called from parser
1141 char *wxmake_integer(char *str
)
1143 wxExpr
*x
= new wxExpr(atol(str
));
1148 char *wxmake_real(char *str1
, char *str2
)
1152 sprintf(buf
, "%s.%s", str1
, str2
);
1153 double f
= (double)atof(buf
);
1154 wxExpr
*x
= new wxExpr(f
);
1159 // extern "C" double exp10(double);
1161 char *wxmake_exp(char *str1
, char *str2
)
1163 double mantissa
= (double)atoi(str1
);
1164 double exponent
= (double)atoi(str2
);
1166 double d
= mantissa
* pow(10.0, exponent
);
1168 wxExpr
*x
= new wxExpr(d
);
1173 char *wxmake_exp2(char *str1
, char *str2
, char *str3
)
1177 sprintf(buf
, "%s.%s", str1
, str2
);
1178 double mantissa
= (double)atof(buf
);
1179 double exponent
= (double)atoi(str3
);
1181 double d
= mantissa
* pow(10.0, exponent
);
1183 wxExpr
*x
= new wxExpr(d
);
1188 char *wxmake_word(char *str
)
1190 wxExpr
*x
= new wxExpr(wxExprWord
, str
);
1194 char *wxmake_string(char *str
)
1199 str
++; /* skip leading quote */
1200 len
= strlen(str
) - 1; /* ignore trailing quote */
1202 s
= new char[len
+ 1];
1205 for(i
=0; i
<len
; i
++)
1207 if (str
[i
] == '\\' && str
[i
+1] == '"')
1212 else if (str
[i
] == '\\' && str
[i
+1] == '\\')
1223 wxExpr
*x
= new wxExpr(wxExprString
, s
, FALSE
);
1227 char *proio_cons(char * ccar
, char * ccdr
)
1229 wxExpr
*car
= (wxExpr
*)ccar
;
1230 wxExpr
*cdr
= (wxExpr
*)ccdr
;
1234 cdr
= new wxExpr(wxExprList
);
1241 void process_command(char * cexpr
)
1243 wxExpr
*expr
= (wxExpr
*)cexpr
;
1247 void syntax_error(char *WXUNUSED(s
))
1249 if (currentwxExprErrorHandler
)
1250 (void)(*(currentwxExprErrorHandler
))(WXEXPR_ERROR_SYNTAX
, "syntax error");
1251 if (thewxExprDatabase
) thewxExprDatabase
->noErrors
+= 1;
1256 // char *__cdecl strdup(const char *s)
1257 WXDLLEXPORT
char *strdup(const char *s
)
1259 int len
= strlen(s
);
1260 char *new_s
= (char *)malloc(sizeof(char)*(len
+1));