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" 
  29 #include "wx/wxexpr.h" 
  31 extern "C" void add_expr(char *); 
  32 extern "C" void LexFromFile(FILE *fd
); 
  33 extern "C" void LexFromString(char *buf
); 
  36 wxExprDatabase 
*thewxExprDatabase 
= NULL
; 
  37 wxExprErrorHandler currentwxExprErrorHandler
; 
  39 wxExpr::wxExpr(const wxString
& functor
) 
  46   wxExpr 
*pfunctor 
= new wxExpr(wxExprWord
, functor
); 
  51 wxExpr::wxExpr(wxExprType the_type
, const wxString
& word_or_string
) 
  58     value
.word 
= copystring((const wxChar 
*)word_or_string
); 
  61     value
.string 
= copystring((const wxChar 
*)word_or_string
); 
  76 wxExpr::wxExpr(wxExprType the_type
, wxChar 
*word_or_string
, bool allocate
) 
  83     value
.word 
= allocate 
? copystring(word_or_string
) : word_or_string
; 
  86     value
.string 
= allocate 
? copystring(word_or_string
) : word_or_string
; 
 101 wxExpr::wxExpr(long the_integer
) 
 103   type 
= wxExprInteger
; 
 104   value
.integer 
= the_integer
; 
 109 wxExpr::wxExpr(double the_real
) 
 112   value
.real 
= the_real
; 
 117 wxExpr::wxExpr(wxList 
*the_list
) 
 124   wxExpr 
*listExpr 
= new wxExpr(wxExprList
); 
 126   wxNode 
*node 
= the_list
->First(); 
 129     wxExpr 
*expr 
= (wxExpr 
*)node
->Data(); 
 130     listExpr
->Append(expr
); 
 138 wxExpr::~wxExpr(void) 
 149      delete[] value
.string
; 
 159      wxExpr 
*expr 
= value
.first
; 
 162        wxExpr 
*expr1 
= expr
->next
; 
 169    case wxExprNull
: break; 
 173 void wxExpr::Append(wxExpr 
*expr
) 
 183 void wxExpr::Insert(wxExpr 
*expr
) 
 185   expr
->next 
= value
.first
; 
 192 wxExpr 
*wxExpr::Copy(void) const 
 194   // This seems to get round an optimizer bug when 
 195   // using Watcom C++ 10a in WIN32 compilation mode. 
 196   // If these lines not present, the type seems to be 
 197   // interpreted wrongly as an integer. 
 198   // I don't want to turn optimization off since it's needed 
 199   // for reading in files quickly. 
 200 #if defined(__WATCOMC__) 
 208       return new wxExpr(value
.integer
); 
 210       return new wxExpr(value
.real
); 
 212       return new wxExpr(wxExprString
, wxString(value
.string
)); 
 214       return new wxExpr(wxExprWord
, wxString(value
.word
)); 
 217       wxExpr 
*expr 
= value
.first
; 
 218       wxExpr 
*new_list 
= new wxExpr(wxExprList
); 
 221         wxExpr 
*expr2 
= expr
->Copy(); 
 222         new_list
->Append(expr2
); 
 234 // Get the wxExpr (containing (= wxExpr Value) form) for the given word 
 235 //  or string, assuming that we have Attribute=Value, ... 
 236 wxExpr 
*wxExpr::GetAttributeValueNode(const wxString
& word
) const // Use only for a clause or list 
 238   if (type 
!= wxExprList
) 
 241   wxExpr 
*expr 
= value
.first
; 
 244     if (expr
->type 
== wxExprList
) 
 246       wxExpr 
*firstNode 
= expr
->value
.first
; 
 247       if ((firstNode
->type 
== wxExprWord
) && (firstNode
->value
.word
[0] == '=')) 
 249         wxExpr 
*secondNode 
= firstNode
->next
; 
 250         if ((secondNode
->type 
== wxExprWord
) &&  
 251             (wxStrcmp((const wxChar 
*)word
, secondNode
->value
.word
) == 0)) 
 262 // Get the value (in wxExpr form) for the given word or string, assuming 
 263 // that we have Attribute=Value, ... 
 264 wxExpr 
*wxExpr::AttributeValue(const wxString
& word
) const // Use only for a clause or list 
 266   if (type 
!= wxExprList
) 
 269   wxExpr 
*attExpr 
= GetAttributeValueNode(word
); 
 270   if (attExpr 
&& attExpr
->value
.first 
&& attExpr
->value
.first
->next
) 
 271     return attExpr
->value
.first
->next
->next
; 
 275 wxString 
wxExpr::Functor(void) const // Use only for a clause 
 277   if ((type 
!= wxExprList
) || !value
.first
) 
 278     return wxString(_T("")); 
 280   if (value
.first
->type 
== wxExprWord
) 
 281     return wxString(value
.first
->value
.word
); 
 283     return wxString(_T("")); 
 286 bool wxExpr::IsFunctor(const wxString
& f
) const  // Use only for a clause 
 288   if ((type 
!= wxExprList
) || !value
.first
) 
 291   return (value
.first
->type 
== wxExprWord 
&&  
 292           (wxStrcmp((const wxChar 
*)f
, value
.first
->value
.word
) == 0)); 
 295 // Return nth argument of a clause (starting from 1) 
 296 wxExpr 
*wxExpr::Arg(wxExprType theType
, int arg
) const 
 298   wxExpr 
*expr 
= value
.first
; 
 300   for (i 
= 1; i 
< arg
; i
++) 
 304   if (expr 
&& (expr
->type 
== theType
)) 
 310 // Return nth argument of a list expression (starting from zero) 
 311 wxExpr 
*wxExpr::Nth(int arg
) const 
 313   if (type 
!= wxExprList
) 
 316   wxExpr 
*expr 
= value
.first
; 
 318   for (i 
= 0; i 
< arg
; i
++) 
 329   // Returns the number of elements in a list expression 
 330 int wxExpr::Number(void) const 
 332   if (type 
!= wxExprList
) 
 336   wxExpr 
*expr 
= value
.first
; 
 345 void wxExpr::DeleteAttributeValue(const wxString
& attribute
) 
 347   if (type 
!= wxExprList
) 
 350   wxExpr 
*expr 
= value
.first
; 
 351   wxExpr 
*lastExpr 
= this; 
 354     if (expr
->type 
== wxExprList
) 
 356       wxExpr 
*firstNode 
= expr
->value
.first
; 
 357       if ((firstNode
->type 
== wxExprWord
) && (firstNode
->value
.word
[0] == '=')) 
 359         wxExpr 
*secondNode 
= firstNode
->next
; 
 360         if ((secondNode
->type 
== wxExprWord
) &&  
 361             (wxStrcmp((const wxChar 
*)attribute
, secondNode
->value
.word
) == 0)) 
 363           wxExpr 
*nextExpr 
= expr
->next
; 
 366           lastExpr
->next 
= nextExpr
; 
 381 void wxExpr::AddAttributeValue(const wxString
& attribute
, wxExpr 
*val
) 
 383   if (type 
!= wxExprList
) 
 385 //    cout << "Error! tried to add an attribute-value pair to a nonlist wxExpr expression\n"; 
 388   // Warning - existing code may assume that any existing value 
 389   // is deleted first. For efficiency, we leave this to the application. 
 390 //  DeleteAttributeValue(attribute); 
 392   wxExpr 
*patt 
= new wxExpr(wxExprWord
, attribute
); 
 393   wxExpr 
*pequals 
= new wxExpr(wxExprWord
, _T("=")); 
 395   wxExpr 
*listExpr 
= new wxExpr(wxExprList
); 
 397   listExpr
->Append(pequals
); 
 398   listExpr
->Append(patt
); 
 399   listExpr
->Append(val
); 
 404 void wxExpr::AddAttributeValue(const wxString
& attribute
, long val
) 
 406   if (type 
!= wxExprList
) 
 408 //    cout << "Error! tried to add an attribute-value pair to a nonlist wxExpr expression\n"; 
 411   // Warning - existing code may assume that any existing value 
 412   // is deleted first. For efficiency, we leave this to the application. 
 413 //  DeleteAttributeValue(attribute); 
 415   wxExpr 
*patt 
= new wxExpr(wxExprWord
, attribute
); 
 416   wxExpr 
*pval 
= new wxExpr(val
); 
 417   wxExpr 
*pequals 
= new wxExpr(wxExprWord
, _T("=")); 
 419   wxExpr 
*listExpr 
= new wxExpr(wxExprList
); 
 421   listExpr
->Append(pequals
); 
 422   listExpr
->Append(patt
); 
 423   listExpr
->Append(pval
); 
 428 void wxExpr::AddAttributeValue(const wxString
& attribute
, double val
) 
 430   if (type 
!= wxExprList
) 
 432 //    cout << "Error! tried to add an attribute-value pair to a nonlist wxExpr expression\n"; 
 436 //  DeleteAttributeValue(attribute); 
 437   wxExpr 
*patt 
= new wxExpr(wxExprWord
, attribute
); 
 438   wxExpr 
*pval 
= new wxExpr(val
); 
 439   wxExpr 
*pequals 
= new wxExpr(wxExprWord
, _T("=")); 
 441   wxExpr 
*listExpr 
= new wxExpr(wxExprList
); 
 443   listExpr
->Append(pequals
); 
 444   listExpr
->Append(patt
); 
 445   listExpr
->Append(pval
); 
 450 void wxExpr::AddAttributeValueString(const wxString
& attribute
, const wxString
& val
) 
 452   if (type 
!= wxExprList
) 
 454 //    cout << "Error! tried to add an attribute-value pair to a nonlist wxExpr expression\n"; 
 458 //  DeleteAttributeValue(attribute); 
 460   wxExpr 
*patt 
= new wxExpr(wxExprWord
, attribute
); 
 461   wxExpr 
*pval 
= new wxExpr(wxExprString
, val
); 
 462   wxExpr 
*pequals 
= new wxExpr(wxExprWord
, _T("=")); 
 464   wxExpr 
*listExpr 
= new wxExpr(wxExprList
); 
 466   listExpr
->Append(pequals
); 
 467   listExpr
->Append(patt
); 
 468   listExpr
->Append(pval
); 
 473 void wxExpr::AddAttributeValueWord(const wxString
& attribute
, const wxString
& val
) 
 475   if (type 
!= wxExprList
) 
 477 //    cout << "Error! tried to add an attribute-value pair to a nonlist wxExpr expression\n"; 
 481 //  DeleteAttributeValue(attribute); 
 483   wxExpr 
*patt 
= new wxExpr(wxExprWord
, attribute
); 
 484   wxExpr 
*pval 
= new wxExpr(wxExprWord
, val
); 
 485   wxExpr 
*pequals 
= new wxExpr(wxExprWord
, _T("=")); 
 487   wxExpr 
*listExpr 
= new wxExpr(wxExprList
); 
 489   listExpr
->Append(pequals
); 
 490   listExpr
->Append(patt
); 
 491   listExpr
->Append(pval
); 
 496 void wxExpr::AddAttributeValue(const wxString
& attribute
, wxList 
*val
) 
 498   if (type 
!= wxExprList
) 
 500 //    cout << "Error! tried to add an attribute-value pair to a nonlist wxExpr expression\n"; 
 506 //  DeleteAttributeValue(attribute); 
 508   wxExpr 
*patt 
= new wxExpr(wxExprWord
, attribute
); 
 509   wxExpr 
*pval 
= new wxExpr(val
); 
 510   wxExpr 
*pequals 
= new wxExpr(wxExprWord
, _T("=")); 
 512   wxExpr 
*listExpr 
= new wxExpr(wxExprList
); 
 514   listExpr
->Append(pequals
); 
 515   listExpr
->Append(patt
); 
 516   listExpr
->Append(pval
); 
 521 void wxExpr::AddAttributeValueStringList(const wxString
& attribute
, wxList 
*string_list
) 
 523   if (type 
!= wxExprList
) 
 525 //    cout << "Error! tried to add an attribute-value pair to a nonlist wxExpr expression\n"; 
 531 //  DeleteAttributeValue(attribute); 
 533   // First make a list of wxExpr strings 
 534   wxExpr 
*listExpr 
= new wxExpr(wxExprList
); 
 535   wxNode 
*node 
= string_list
->First(); 
 538     char *string 
= (char *)node
->Data(); 
 539     wxExpr 
*expr 
= new wxExpr(wxExprString
, wxString(string
)); 
 540     listExpr
->Append(expr
); 
 544   // Now make an (=, Att, Value) triple 
 545   wxExpr 
*patt 
= new wxExpr(wxExprWord
, attribute
); 
 546   wxExpr 
*pequals 
= new wxExpr(wxExprWord
, _T("=")); 
 548   wxExpr 
*listExpr2 
= new wxExpr(wxExprList
); 
 550   listExpr2
->Append(pequals
); 
 551   listExpr2
->Append(patt
); 
 552   listExpr2
->Append(listExpr
); 
 557 bool wxExpr::GetAttributeValue(const wxString
& att
, int& var
) const 
 559   wxExpr 
*expr 
= AttributeValue(att
); 
 561   if (expr 
&& (expr
->Type() == wxExprInteger 
|| expr
->Type() == wxExprReal
)) 
 563     var 
= (int)(expr
->IntegerValue()); 
 570 bool wxExpr::GetAttributeValue(const wxString
& att
, long& var
) const 
 572   wxExpr 
*expr 
= AttributeValue(att
); 
 574   if (expr 
&& (expr
->Type() == wxExprInteger 
|| expr
->Type() == wxExprReal
)) 
 576     var 
= expr
->IntegerValue(); 
 583 bool wxExpr::GetAttributeValue(const wxString
& att
, float& var
) const 
 585   wxExpr 
*expr 
= AttributeValue(att
); 
 586   if (expr 
&& (expr
->Type() == wxExprInteger 
|| expr
->Type() == wxExprReal
)) 
 588     var 
= (float) expr
->RealValue(); 
 595 bool wxExpr::GetAttributeValue(const wxString
& att
, double& var
) const 
 597   wxExpr 
*expr 
= AttributeValue(att
); 
 598   if (expr 
&& (expr
->Type() == wxExprInteger 
|| expr
->Type() == wxExprReal
)) 
 600     var 
= expr
->RealValue(); 
 607 bool wxExpr::GetAttributeValue(const wxString
& att
, wxString
& var
)  const // Word OR string -> string 
 609   wxExpr 
*expr 
= AttributeValue(att
); 
 610   if (expr 
&& expr
->Type() == wxExprWord
) 
 612     var 
= expr
->WordValue(); 
 615   else if (expr 
&& expr
->Type() == wxExprString
) 
 617     var 
= expr
->StringValue(); 
 624 bool wxExpr::GetAttributeValue(const wxString
& att
, wxExpr 
**var
) const 
 626   wxExpr 
*expr 
= AttributeValue(att
); 
 636 bool wxExpr::GetAttributeValueStringList(const wxString
& att
, wxList 
*var
) const 
 638   wxExpr 
*expr 
= AttributeValue(att
); 
 639   if (expr 
&& expr
->Type() == wxExprList
) 
 641     wxExpr 
*string_expr 
= expr
->value
.first
; 
 644       if (string_expr
->Type() == wxExprString
) 
 645         var
->Append((wxObject 
*)copystring(string_expr
->StringValue())); 
 647       string_expr 
= string_expr
->next
; 
 656 void wxExpr::AssignAttributeValue(wxChar 
*att
, wxChar 
**var
) const 
 659   if (GetAttributeValue(att
, str
)) 
 663     *var 
= copystring((const wxChar 
*) str
); 
 667 void wxExpr::WriteClause(FILE* stream
)  // Write this expression as a top-level clause 
 669   if (type 
!= wxExprList
) 
 672   wxExpr 
*node 
= value
.first
; 
 675     node
->WriteExpr(stream
); 
 676     fprintf( stream
, "(" ); 
 682         fprintf( stream
, "  " ); 
 683       node
->WriteExpr(stream
); 
 686         fprintf( stream
, ",\n" ); 
 689     fprintf( stream
, ").\n\n" ); 
 693 void wxExpr::WriteExpr(FILE* stream
)    // Write as any other subexpression 
 695   // This seems to get round an optimizer bug when 
 696   // using Watcom C++ 10a in WIN32 compilation mode. 
 697   // If these lines not present, the type seems to be 
 698   // interpreted wrongly as an integer. 
 699   // I don't want to turn optimization off since it's needed 
 700   // for reading in files quickly. 
 701 #if defined(__WATCOMC__) 
 710       fprintf( stream
, "%ld", value
.integer 
); 
 715       double f 
= value
.real
; 
 716       fprintf( stream
, "%.6g", f
); 
 721       fprintf( stream
, "\"" ); 
 723       const wxWX2MBbuf val 
= wxConvLibc
.cWX2MB(value
.string
); 
 724       int len 
= strlen(val
); 
 725       for (i 
= 0; i 
< len
; i
++) 
 728         if (ch 
== '"' || ch 
== '\\') 
 729           fprintf( stream
, "\\" ); 
 733         fprintf( stream
, tmp 
); 
 735       fprintf( stream
, "\"" ); 
 740       bool quote_it 
= FALSE
; 
 741       const wxWX2MBbuf val 
= wxConvLibc
.cWX2MB(value
.word
); 
 742       int len 
= strlen(val
); 
 743       if ((len 
== 0) || (len 
> 0 && (val
[0] > 64 && val
[0] < 91))) 
 748         for (i 
= 0; i 
< len
; i
++) 
 749           if ((!isalpha(val
[i
])) && (!isdigit(val
[i
])) && 
 751             { quote_it 
= TRUE
; i 
= len
; } 
 755         fprintf( stream 
,"'" ); 
 757       fprintf( stream
, (const char*) val 
); 
 760         fprintf( stream
, "'" ); 
 767         fprintf( stream
, "[]" ); 
 770         wxExpr 
*expr 
= value
.first
; 
 772         if ((expr
->Type() == wxExprWord
) && (wxStrcmp(expr
->WordValue(), _T("=")) == 0)) 
 774           wxExpr 
*arg1 
= expr
->next
; 
 775           wxExpr 
*arg2 
= arg1
->next
; 
 776           arg1
->WriteExpr(stream
); 
 777           fprintf( stream
, " = " ); 
 778           arg2
->WriteExpr(stream
); 
 782           fprintf( stream
, "[" ); 
 785             expr
->WriteExpr(stream
); 
 788               fprintf( stream
, ", " ); 
 790           fprintf( stream
, "]" ); 
 795    case wxExprNull
: break; 
 799 void wxExpr::WriteLispExpr(FILE* stream
) 
 805       fprintf( stream
, "%ld", value
.integer 
); 
 810       fprintf( stream
, "%.6g", value
.real 
); 
 815       fprintf( stream
, "\"" ); 
 816       const wxWX2MBbuf val 
= wxConvLibc
.cWX2MB(value
.string
); 
 817       fprintf( stream
, (const char*) val 
); 
 818       fprintf( stream
, "\"" ); 
 823       const wxWX2MBbuf val 
= wxConvLibc
.cWX2MB(value
.word
); 
 824       fprintf( stream
, (const char*) val 
); 
 829       wxExpr 
*expr 
= value
.first
; 
 831       fprintf( stream
, "(" ); 
 834         expr
->WriteLispExpr(stream
); 
 837           fprintf( stream
, " " ); 
 840       fprintf( stream
, ")" ); 
 843    case wxExprNull
: break; 
 848  * wxExpr 'database' (list of expressions) 
 851 #if !USE_SHARED_LIBRARIES 
 852 IMPLEMENT_DYNAMIC_CLASS(wxExprDatabase
, wxList
) 
 855 wxExprDatabase::wxExprDatabase(wxExprErrorHandler handler
) 
 859   currentwxExprErrorHandler 
= handler
; 
 863 wxExprDatabase::wxExprDatabase(wxExprType type
, const wxString
& attribute
, int size
, 
 864                                wxExprErrorHandler handler
) 
 867   attribute_to_hash 
= attribute
; 
 868   if (type 
== wxExprString
) 
 869     hash_table 
= new wxHashTable(wxKEY_STRING
, size
); 
 870   else if (type 
== wxExprInteger
) 
 871     hash_table 
= new wxHashTable(wxKEY_INTEGER
, size
); 
 872   else hash_table 
= NULL
; 
 874   currentwxExprErrorHandler 
= handler
; 
 878 wxExprDatabase::~wxExprDatabase(void) 
 885 void wxExprDatabase::BeginFind(void)          // Initialise a search 
 890 wxExpr 
*wxExprDatabase::FindClause(long id
)  // Find a term based on an integer id attribute 
 891                                  // e.g. node(id=23, type=rectangle, ....). 
 893   wxExpr 
*found 
= NULL
; 
 894   while (position 
&& !found
) 
 896     wxExpr 
*term 
= (wxExpr 
*)position
->Data(); 
 898     if (term
->Type() == wxExprList
) 
 900       wxExpr 
*value 
= term
->AttributeValue("id"); 
 901       if (value
->Type() == wxExprInteger 
&& value
->IntegerValue() == id
) 
 904     position 
= position
->Next(); 
 909 // Find on basis of attribute/value pairs, e.g. type=rectangle 
 910 wxExpr 
*wxExprDatabase::FindClause(const wxString
& word
, const wxString
& val
) 
 912   wxExpr 
*found 
= NULL
; 
 913   while (position 
&& !found
) 
 915     wxExpr 
*term 
= (wxExpr 
*)position
->Data(); 
 917     if (term
->Type() == wxExprList
) 
 919       wxExpr 
*value 
= term
->AttributeValue(word
); 
 920       if ((value
->Type() == wxExprWord 
&& value
->WordValue() == val
) || 
 921           (value
->Type() == wxExprString 
&& value
->StringValue() == val
)) 
 924     position 
= position
->Next(); 
 929 wxExpr 
*wxExprDatabase::FindClause(const wxString
& word
, long val
) 
 931   wxExpr 
*found 
= NULL
; 
 932   while (position 
&& !found
) 
 934     wxExpr 
*term 
= (wxExpr 
*)position
->Data(); 
 936     if (term
->Type() == wxExprList
) 
 938       wxExpr 
*value 
= term
->AttributeValue(word
); 
 939       if ((value
->Type() == wxExprInteger
) && (value
->IntegerValue() == val
)) 
 942     position 
= position
->Next(); 
 947 wxExpr 
*wxExprDatabase::FindClause(const wxString
& word
, double val
) 
 949   wxExpr 
*found 
= NULL
; 
 950   while (position 
&& !found
) 
 952     wxExpr 
*term 
= (wxExpr 
*)position
->Data(); 
 954     if (term
->Type() == wxExprList
) 
 956       wxExpr 
*value 
= term
->AttributeValue(word
); 
 957       if ((value
->Type() == wxExprReal
) && (value
->RealValue() == val
)) 
 960     position 
= position
->Next(); 
 965 wxExpr 
*wxExprDatabase::FindClauseByFunctor(const wxString
& functor
) 
 967   wxExpr 
*found 
= NULL
; 
 968   while (position 
&& !found
) 
 970     wxExpr 
*term 
= (wxExpr 
*)position
->Data(); 
 972     if (term
->Type() == wxExprList
) 
 974       if (term
->Functor() == functor
) 
 977     position 
= position
->Next(); 
 982 // If hashing is on, must store in hash table too 
 983 void wxExprDatabase::Append(wxExpr 
*clause
) 
 985   wxList::Append((wxObject 
*)clause
); 
 988     wxString 
functor(clause
->Functor()); 
 989     wxExpr 
*expr 
= clause
->AttributeValue(attribute_to_hash
); 
 992       long functor_key 
= hash_table
->MakeKey(WXSTRINGCAST functor
); 
 994       if (expr 
&& expr
->Type() == wxExprString
) 
 996         value_key 
= hash_table
->MakeKey(WXSTRINGCAST expr
->StringValue()); 
 997         hash_table
->Put(functor_key 
+ value_key
, WXSTRINGCAST expr
->StringValue(), (wxObject 
*)clause
); 
 999       else if (expr 
&& expr
->Type() == wxExprInteger
) 
1001         value_key 
= expr
->IntegerValue(); 
1002         hash_table
->Put(functor_key 
+ value_key
, expr
->IntegerValue(), (wxObject 
*)clause
); 
1009 wxExpr 
*wxExprDatabase::HashFind(const wxString
& functor
, long value
) const 
1011   long key 
= hash_table
->MakeKey(WXSTRINGCAST functor
) + value
; 
1013   // The key alone isn't guaranteed to be unique: 
1014   // must supply value too. Let's assume the value of the 
1015   // id is going to be reasonably unique. 
1016   return (wxExpr 
*)hash_table
->Get(key
, value
); 
1019 wxExpr 
*wxExprDatabase::HashFind(const wxString
& functor
, const wxString
& value
) const 
1021   long key 
= hash_table
->MakeKey(WXSTRINGCAST functor
) + hash_table
->MakeKey(WXSTRINGCAST value
); 
1022   return (wxExpr 
*)hash_table
->Get(key
, WXSTRINGCAST value
); 
1025 void wxExprDatabase::ClearDatabase(void) 
1028   wxNode 
*node 
= First(); 
1031     wxExpr 
*expr 
= (wxExpr 
*)node
->Data(); 
1038     hash_table
->Clear(); 
1041 bool wxExprDatabase::Read(const wxString
& filename
) 
1045   FILE *f 
= fopen(filename
.fn_str(), "r"); 
1048     thewxExprDatabase 
= this; 
1055     return (noErrors 
== 0); 
1063 bool wxExprDatabase::ReadFromString(const wxString
& buffer
) 
1066   thewxExprDatabase 
= this; 
1068   const wxWX2MBbuf buf 
= buffer
.mb_str(); 
1069   LexFromString(MBSTRINGCAST buf
); 
1072   return (noErrors 
== 0); 
1075 bool wxExprDatabase::Write(const wxString
& fileName
) 
1077   FILE *stream 
= fopen( fileName
.fn_str(), "w+" ); 
1082   return Write(stream
); 
1085 bool wxExprDatabase::Write(FILE *stream
) 
1088   wxNode 
*node 
= First(); 
1091     wxExpr 
*expr 
= (wxExpr 
*)node
->Data(); 
1092     expr
->WriteClause(stream
); 
1093     node 
= node
->Next(); 
1095   return (noErrors 
== 0); 
1098 void wxExprDatabase::WriteLisp(FILE* stream
) 
1101   wxNode 
*node 
= First(); 
1104     wxExpr 
*expr 
= (wxExpr 
*)node
->Data(); 
1105     expr
->WriteLispExpr(stream
); 
1106     fprintf( stream
, "\n\n" ); 
1107     node 
= node
->Next(); 
1111 void add_expr(wxExpr 
* expr
) 
1113   thewxExprDatabase
->Append(expr
); 
1117 bool wxExprIsFunctor(wxExpr 
*expr
, const wxString
& functor
) 
1119   if (expr 
&& (expr
->Type() == wxExprList
)) 
1121     wxExpr 
*first_expr 
= expr
->value
.first
; 
1123     if (first_expr 
&& (first_expr
->Type() == wxExprWord
) && 
1124        (first_expr
->WordValue() == functor
)) 
1134  * Called from parser 
1138 char *wxmake_integer(char *str
) 
1140   wxExpr 
*x 
= new wxExpr(atol(str
)); 
1145 char *wxmake_real(char *str1
, char *str2
) 
1149   sprintf(buf
, "%s.%s", str1
, str2
); 
1150   double f 
= (double)atof(buf
); 
1151   wxExpr 
*x 
= new wxExpr(f
); 
1156 // extern "C" double exp10(double); 
1158 char *wxmake_exp(char *str1
, char *str2
) 
1160   double mantissa 
= (double)atoi(str1
); 
1161   double exponent 
= (double)atoi(str2
); 
1163   double d 
= mantissa 
* pow(10.0, exponent
); 
1165   wxExpr 
*x 
= new wxExpr(d
); 
1170 char *wxmake_exp2(char *str1
, char *str2
, char *str3
) 
1174   sprintf(buf
, "%s.%s", str1
, str2
); 
1175   double mantissa 
= (double)atof(buf
); 
1176   double exponent 
= (double)atoi(str3
); 
1178   double d 
= mantissa 
* pow(10.0, exponent
); 
1180   wxExpr 
*x 
= new wxExpr(d
); 
1185 char *wxmake_word(char *str
) 
1187   wxExpr 
*x 
= new wxExpr(wxExprWord
, str
); 
1191 char *wxmake_string(char *str
) 
1195   const wxMB2WXbuf sbuf 
= wxConvLibc
.cMB2WX(str
); 
1197 //  str++;                      /* skip leading quote */ 
1198   len 
= wxStrlen(sbuf
) - 1;     /* ignore trailing quote */ 
1200   s 
= new wxChar
[len 
+ 1]; 
1203   for(i
=1; i
<len
; i
++) // 1 since we want to skip leading quote 
1205     if (sbuf
[i
] == _T('\\') && sbuf
[i
+1] == _T('"')) 
1210     else if (sbuf
[i
] == _T('\\') && sbuf
[i
+1] == _T('\\')) 
1221   wxExpr 
*x 
= new wxExpr(wxExprString
, s
, FALSE
); 
1225 char *proio_cons(char * ccar
, char * ccdr
) 
1227   wxExpr 
*car 
= (wxExpr 
*)ccar
; 
1228   wxExpr 
*cdr 
= (wxExpr 
*)ccdr
; 
1232     cdr 
= new wxExpr(wxExprList
); 
1239 void process_command(char * cexpr
) 
1241   wxExpr 
*expr 
= (wxExpr 
*)cexpr
; 
1245 void syntax_error(char *WXUNUSED(s
)) 
1247   if (currentwxExprErrorHandler
) 
1248     (void)(*(currentwxExprErrorHandler
))(WXEXPR_ERROR_SYNTAX
, "syntax error"); 
1249   if (thewxExprDatabase
) thewxExprDatabase
->noErrors 
+= 1; 
1254 // char *__cdecl strdup(const char *s) 
1255 WXDLLEXPORT 
char *strdup(const char *s
) 
1257   int len 
= strlen(s
); 
1258   char *new_s 
= (char *)malloc(sizeof(char)*(len
+1));