1///////////////////////////////////////////////////////////////////////////// 2// Name: wxexpr.cpp 3// Purpose: wxExpr 4// Author: Julian Smart 5// Modified by: 6// Created: 04/01/98 7// RCS-ID: $Id: wxexpr.cpp 35650 2005-09-23 12:56:45Z MR $ 8// Copyright: (c) Julian Smart 9// Licence: wxWindows licence 10///////////////////////////////////////////////////////////////////////////// 11 12// For compilers that support precompilation, includes "wx/wx.h". 13#include "wx/wxprec.h" 14 15#ifdef __BORLANDC__ 16#pragma hdrstop 17#endif 18 19#include "wx/deprecated/setup.h" 20 21#if wxUSE_PROLOGIO 22 23#include <stdarg.h> 24#include <ctype.h> 25#include <string.h> 26 27#include "wx/utils.h" 28#include "wx/deprecated/expr.h" 29#include "wx/deprecated/wxexpr.h" 30 31#if !WXWIN_COMPATIBILITY_2_4 32static inline wxChar* copystring(const wxChar* s) 33 { return wxStrcpy(new wxChar[wxStrlen(s) + 1], s); } 34#endif 35 36extern "C" void add_expr(char *); 37extern "C" void LexFromFile(FILE *fd); 38extern "C" void LexFromString(char *buf); 39 40 41 42/* Rename all YACC/LEX stuff or we'll conflict with other 43 * applications 44 */ 45 46#define yyback PROIO_yyback 47#define yylook PROIO_yylook 48#define yywrap PROIO_yywrap 49#define yyoutput PROIO_yyoutput 50#define yylex PROIO_yylex 51#define yyerror PROIO_yyerror 52#define yyleng PROIO_yyleng 53#define yytext PROIO_yytext 54#define yymorfg PROIO_yymorfg 55#define yylineno PROIO_yylineno 56#define yytchar PROIO_yytchar 57#define yyin PROIO_yyin 58#define yyout PROIO_yyout 59#define yysvf PROIO_yysvf 60#define yyestate PROIO_yyestate 61#define yysvec PROIO_yysvec 62#define yybgin PROIO_yybgin 63#define yyprevious PROIO_yyprevious 64#define yylhs PROIO_yylhs 65#define yylen PROIO_yylen 66#define yydefred PROIO_yydefred 67#define yydgoto PROIO_yydgoto 68#define yysindex PROIO_yysindex 69#define yyrindex PROIO_yyrindex 70#define yygindex PROIO_yygindex 71#define yytable PROIO_yytable 72#define yycheck PROIO_yycheck 73#define yyname PROIO_yyname 74#define yyrule PROIO_yyrule 75#define yydebug PROIO_yydebug 76#define yynerrs PROIO_yynerrs 77#define yyerrflag PROIO_yyerrflag 78#define yychar PROIO_yychar 79#define yyvsp PROIO_yyvsp 80#define yyssp PROIO_yyssp 81#define yyval PROIO_yyval 82#define yylval PROIO_yylval 83#define yyss PROIO_yyss 84#define yyvs PROIO_yyvs 85#define yyparse PROIO_yyparse 86 87/* +++steve162e: more defines necessary */ 88#define yy_init_buffer PROIO_yy_init_buffer 89#define yy_create_buffer PROIO_yy_create_buffer 90#define yy_load_buffer_state PROIO_yy_load_buffer_state 91#define yyrestart PROIO_yyrestart 92#define yy_switch_to_buffer PROIO_yy_switch_to_buffer 93#define yy_delete_buffer PROIO_yy_delete_buffer 94/* ---steve162e */ 95 96/* WG 1/96: still more for flex 2.5 */ 97#define yy_scan_buffer PROIO_scan_buffer 98#define yy_scan_string PROIO_scan_string 99#define yy_scan_bytes PROIO_scan_bytes 100#define yy_flex_debug PROIO_flex_debug 101#define yy_flush_buffer PROIO_flush_buffer 102#if !defined(__VISAGECPP__) 103/* multiply defined??? */ 104#define yyleng PROIO_yyleng 105#define yytext PROIO_yytext 106#endif 107 108extern "C" WXDLLIMPEXP_DATA_DEPRECATED(FILE*) yyin; 109extern "C" WXDLLIMPEXP_DEPRECATED int yyparse(void); 110 111 112wxExprDatabase *thewxExprDatabase = NULL; 113wxExprErrorHandler currentwxExprErrorHandler; 114 115wxExpr::wxExpr(const wxString& functor) 116{ 117 type = wxExprList; 118 next = NULL; 119 last = NULL; 120 value.first = NULL; 121 122 wxExpr *pfunctor = new wxExpr(wxExprWord, functor); 123 Append(pfunctor); 124 client_data = NULL; 125} 126 127wxExpr::wxExpr(wxExprType the_type, const wxString& word_or_string) 128{ 129 type = the_type; 130 131 switch (the_type) 132 { 133 case wxExprWord: 134 value.word = copystring((const wxChar *)word_or_string); 135 break; 136 case wxExprString: 137 value.string = copystring((const wxChar *)word_or_string); 138 break; 139 case wxExprList: 140 last = NULL; 141 value.first = NULL; 142 break; 143 case wxExprReal: 144 case wxExprInteger: 145 case wxExprNull: 146 break; 147 } 148 client_data = NULL; 149 next = NULL; 150} 151 152wxExpr::wxExpr(wxExprType the_type, wxChar *word_or_string, bool allocate) 153{ 154 type = the_type; 155 156 switch (the_type) 157 { 158 case wxExprWord: 159 value.word = allocate ? copystring(word_or_string) : word_or_string; 160 break; 161 case wxExprString: 162 value.string = allocate ? copystring(word_or_string) : word_or_string; 163 break; 164 case wxExprList: 165 last = NULL; 166 value.first = NULL; 167 break; 168 case wxExprReal: 169 case wxExprInteger: 170 case wxExprNull: 171 break; 172 } 173 client_data = NULL; 174 next = NULL; 175} 176 177wxExpr::wxExpr(long the_integer) 178{ 179 type = wxExprInteger; 180 value.integer = the_integer; 181 client_data = NULL; 182 next = NULL; 183} 184 185wxExpr::wxExpr(double the_real) 186{ 187 type = wxExprReal; 188 value.real = the_real; 189 client_data = NULL; 190 next = NULL; 191} 192 193wxExpr::wxExpr(wxList *the_list) 194{ 195 type = wxExprList; 196 client_data = NULL; 197 last = NULL; 198 value.first = NULL; 199 200 wxExpr *listExpr = new wxExpr(wxExprList); 201 202 wxNode *node = the_list->GetFirst(); 203 while (node) 204 { 205 wxExpr *expr = (wxExpr *)node->GetData(); 206 listExpr->Append(expr); 207 node = node->GetNext(); 208 } 209 Append(listExpr); 210 211 delete the_list; 212} 213 214wxExpr::~wxExpr(void) 215{ 216 switch (type) 217 { 218 case wxExprInteger: 219 case wxExprReal: 220 { 221 break; 222 } 223 case wxExprString: 224 { 225 delete[] value.string; 226 break; 227 } 228 case wxExprWord: 229 { 230 delete[] value.word; 231 break; 232 } 233 case wxExprList: 234 { 235 wxExpr *expr = value.first; 236 while (expr) 237 { 238 wxExpr *expr1 = expr->next; 239 240 delete expr; 241 expr = expr1; 242 } 243 break; 244 } 245 case wxExprNull: break; 246 } 247} 248 249void wxExpr::Append(wxExpr *expr) 250{ 251 if (!value.first) 252 value.first = expr; 253 254 if (last) 255 last->next = expr; 256 last = expr; 257} 258 259void wxExpr::Insert(wxExpr *expr) 260{ 261 expr->next = value.first; 262 value.first = expr; 263 264 if (!last) 265 last = expr; 266} 267 268wxExpr *wxExpr::Copy(void) const 269{ 270 // This seems to get round an optimizer bug when 271 // using Watcom C++ 10a in WIN32 compilation mode. 272 // If these lines not present, the type seems to be 273 // interpreted wrongly as an integer. 274 // I don't want to turn optimization off since it's needed 275 // for reading in files quickly. 276#if defined(__WATCOMC__) 277 char buf[2]; 278 sprintf(buf, ""); 279#endif 280 281 switch (type) 282 { 283 case wxExprInteger: 284 return new wxExpr(value.integer); 285 case wxExprReal: 286 return new wxExpr(value.real); 287 case wxExprString: 288 return new wxExpr(wxExprString, wxString(value.string)); 289 case wxExprWord: 290 return new wxExpr(wxExprWord, wxString(value.word)); 291 case wxExprList: 292 { 293 wxExpr *expr = value.first; 294 wxExpr *new_list = new wxExpr(wxExprList); 295 while (expr) 296 { 297 wxExpr *expr2 = expr->Copy(); 298 new_list->Append(expr2); 299 expr = expr->next; 300 } 301 return new_list; 302 } 303 case wxExprNull: 304 break; 305 } 306 return NULL; 307} 308 309 310// Get the wxExpr (containing (= wxExpr Value) form) for the given word 311// or string, assuming that we have Attribute=Value, ... 312wxExpr *wxExpr::GetAttributeValueNode(const wxString& word) const // Use only for a clause or list 313{ 314 if (type != wxExprList) 315 return NULL; 316 317 wxExpr *expr = value.first; 318 while (expr) 319 { 320 if (expr->type == wxExprList) 321 { 322 wxExpr *firstNode = expr->value.first; 323 if ((firstNode->type == wxExprWord) && (firstNode->value.word[0] == '=')) 324 { 325 wxExpr *secondNode = firstNode->next; 326 if ((secondNode->type == wxExprWord) && 327 (wxStrcmp((const wxChar *)word, secondNode->value.word) == 0)) 328 { 329 return expr; 330 } 331 } 332 } 333 expr = expr->next; 334 } 335 return NULL; 336} 337 338// Get the value (in wxExpr form) for the given word or string, assuming 339// that we have Attribute=Value, ... 340wxExpr *wxExpr::AttributeValue(const wxString& word) const // Use only for a clause or list 341{ 342 if (type != wxExprList) 343 return NULL; 344 345 wxExpr *attExpr = GetAttributeValueNode(word); 346 if (attExpr && attExpr->value.first && attExpr->value.first->next) 347 return attExpr->value.first->next->next; 348 else return NULL; 349} 350 351wxString wxExpr::Functor(void) const // Use only for a clause 352{ 353 if ((type != wxExprList) || !value.first) 354 return wxString(wxT("")); 355 356 if (value.first->type == wxExprWord) 357 return wxString(value.first->value.word); 358 else 359 return wxString(wxT("")); 360} 361 362bool wxExpr::IsFunctor(const wxString& f) const // Use only for a clause 363{ 364 if ((type != wxExprList) || !value.first) 365 return false; 366 367 return (value.first->type == wxExprWord && 368 (wxStrcmp((const wxChar *)f, value.first->value.word) == 0)); 369} 370 371// Return nth argument of a clause (starting from 1) 372wxExpr *wxExpr::Arg(wxExprType theType, int arg) const 373{ 374 wxExpr *expr = value.first; 375 int i; 376 for (i = 1; i < arg; i++) 377 if (expr) 378 expr = expr->next; 379 380 if (expr && (expr->type == theType)) 381 return expr; 382 else 383 return NULL; 384} 385 386// Return nth argument of a list expression (starting from zero) 387wxExpr *wxExpr::Nth(int arg) const 388{ 389 if (type != wxExprList) 390 return NULL; 391 392 wxExpr *expr = value.first; 393 int i; 394 for (i = 0; i < arg; i++) 395 if (expr) 396 expr = expr->next; 397 else return NULL; 398 399 if (expr) 400 return expr; 401 else 402 return NULL; 403} 404 405 // Returns the number of elements in a list expression 406int wxExpr::Number(void) const 407{ 408 if (type != wxExprList) 409 return 0; 410 411 int i = 0; 412 wxExpr *expr = value.first; 413 while (expr) 414 { 415 expr = expr->next; 416 i ++; 417 } 418 return i; 419} 420 421void wxExpr::DeleteAttributeValue(const wxString& attribute) 422{ 423 if (type != wxExprList) 424 return; 425 426 wxExpr *expr = value.first; 427 wxExpr *lastExpr = this; 428 while (expr) 429 { 430 if (expr->type == wxExprList) 431 { 432 wxExpr *firstNode = expr->value.first; 433 if ((firstNode->type == wxExprWord) && (firstNode->value.word[0] == '=')) 434 { 435 wxExpr *secondNode = firstNode->next; 436 if ((secondNode->type == wxExprWord) && 437 (wxStrcmp((const wxChar *)attribute, secondNode->value.word) == 0)) 438 { 439 wxExpr *nextExpr = expr->next; 440 delete expr; 441 442 lastExpr->next = nextExpr; 443 444 if (last == expr) 445 last = lastExpr; 446 447 return; 448 } 449 } 450 } 451 lastExpr = expr; 452 expr = expr->next; 453 } 454 return; 455} 456 457void wxExpr::AddAttributeValue(const wxString& attribute, wxExpr *val) 458{ 459 if (type != wxExprList) 460 { 461// cout << "Error! tried to add an attribute-value pair to a nonlist wxExpr expression\n"; 462 return; 463 } 464 // Warning - existing code may assume that any existing value 465 // is deleted first. For efficiency, we leave this to the application. 466// DeleteAttributeValue(attribute); 467 468 wxExpr *patt = new wxExpr(wxExprWord, attribute); 469 wxExpr *pequals = new wxExpr(wxExprWord, wxT("=")); 470 471 wxExpr *listExpr = new wxExpr(wxExprList); 472 473 listExpr->Append(pequals); 474 listExpr->Append(patt); 475 listExpr->Append(val); 476 477 Append(listExpr); 478} 479 480void wxExpr::AddAttributeValue(const wxString& attribute, long val) 481{ 482 if (type != wxExprList) 483 { 484// cout << "Error! tried to add an attribute-value pair to a nonlist wxExpr expression\n"; 485 return; 486 } 487 // Warning - existing code may assume that any existing value 488 // is deleted first. For efficiency, we leave this to the application. 489// DeleteAttributeValue(attribute); 490 491 wxExpr *patt = new wxExpr(wxExprWord, attribute); 492 wxExpr *pval = new wxExpr(val); 493 wxExpr *pequals = new wxExpr(wxExprWord, wxT("=")); 494 495 wxExpr *listExpr = new wxExpr(wxExprList); 496 497 listExpr->Append(pequals); 498 listExpr->Append(patt); 499 listExpr->Append(pval); 500 501 Append(listExpr); 502} 503 504void wxExpr::AddAttributeValue(const wxString& attribute, double val) 505{ 506 if (type != wxExprList) 507 { 508// cout << "Error! tried to add an attribute-value pair to a nonlist wxExpr expression\n"; 509 return; 510 } 511 512// DeleteAttributeValue(attribute); 513 wxExpr *patt = new wxExpr(wxExprWord, attribute); 514 wxExpr *pval = new wxExpr(val); 515 wxExpr *pequals = new wxExpr(wxExprWord, wxT("=")); 516 517 wxExpr *listExpr = new wxExpr(wxExprList); 518 519 listExpr->Append(pequals); 520 listExpr->Append(patt); 521 listExpr->Append(pval); 522 523 Append(listExpr); 524} 525 526void wxExpr::AddAttributeValueString(const wxString& attribute, const wxString& val) 527{ 528 if (type != wxExprList) 529 { 530// cout << "Error! tried to add an attribute-value pair to a nonlist wxExpr expression\n"; 531 return; 532 } 533 534// DeleteAttributeValue(attribute); 535 536 wxExpr *patt = new wxExpr(wxExprWord, attribute); 537 wxExpr *pval = new wxExpr(wxExprString, val); 538 wxExpr *pequals = new wxExpr(wxExprWord, wxT("=")); 539 540 wxExpr *listExpr = new wxExpr(wxExprList); 541 542 listExpr->Append(pequals); 543 listExpr->Append(patt); 544 listExpr->Append(pval); 545 546 Append(listExpr); 547} 548 549void wxExpr::AddAttributeValueWord(const wxString& attribute, const wxString& val) 550{ 551 if (type != wxExprList) 552 { 553// cout << "Error! tried to add an attribute-value pair to a nonlist wxExpr expression\n"; 554 return; 555 } 556 557// DeleteAttributeValue(attribute); 558 559 wxExpr *patt = new wxExpr(wxExprWord, attribute); 560 wxExpr *pval = new wxExpr(wxExprWord, val); 561 wxExpr *pequals = new wxExpr(wxExprWord, wxT("=")); 562 563 wxExpr *listExpr = new wxExpr(wxExprList); 564 565 listExpr->Append(pequals); 566 listExpr->Append(patt); 567 listExpr->Append(pval); 568 569 Append(listExpr); 570} 571 572void wxExpr::AddAttributeValue(const wxString& attribute, wxList *val) 573{ 574 if (type != wxExprList) 575 { 576// cout << "Error! tried to add an attribute-value pair to a nonlist wxExpr expression\n"; 577 return; 578 } 579 if (!val) 580 return; 581 582// DeleteAttributeValue(attribute); 583 584 wxExpr *patt = new wxExpr(wxExprWord, attribute); 585 wxExpr *pval = new wxExpr(val); 586 wxExpr *pequals = new wxExpr(wxExprWord, wxT("=")); 587 588 wxExpr *listExpr = new wxExpr(wxExprList); 589 590 listExpr->Append(pequals); 591 listExpr->Append(patt); 592 listExpr->Append(pval); 593 594 Append(listExpr); 595} 596 597void wxExpr::AddAttributeValueStringList(const wxString& attribute, wxList *string_list) 598{ 599 if (type != wxExprList) 600 { 601// cout << "Error! tried to add an attribute-value pair to a nonlist wxExpr expression\n"; 602 return; 603 } 604 if (!string_list) 605 return; 606 607// DeleteAttributeValue(attribute); 608 609 // First make a list of wxExpr strings 610 wxExpr *listExpr = new wxExpr(wxExprList); 611 wxNode *node = string_list->GetFirst(); 612 while (node) 613 { 614 wxChar *string = (wxChar*)node->GetData(); 615 wxExpr *expr = new wxExpr(wxExprString, wxString(string)); 616 listExpr->Append(expr); 617 node = node->GetNext(); 618 } 619 620 // Now make an (=, Att, Value) triple 621 wxExpr *patt = new wxExpr(wxExprWord, attribute); 622 wxExpr *pequals = new wxExpr(wxExprWord, wxT("=")); 623 624 wxExpr *listExpr2 = new wxExpr(wxExprList); 625 626 listExpr2->Append(pequals); 627 listExpr2->Append(patt); 628 listExpr2->Append(listExpr); 629 630 Append(listExpr2); 631} 632 633bool wxExpr::GetAttributeValue(const wxString& att, int& var) const 634{ 635 wxExpr *expr = AttributeValue(att); 636 637 if (expr && (expr->Type() == wxExprInteger || expr->Type() == wxExprReal)) 638 { 639 var = (int)(expr->IntegerValue()); 640 return true; 641 } 642 else 643 return false; 644} 645 646bool wxExpr::GetAttributeValue(const wxString& att, long& var) const 647{ 648 wxExpr *expr = AttributeValue(att); 649 650 if (expr && (expr->Type() == wxExprInteger || expr->Type() == wxExprReal)) 651 { 652 var = expr->IntegerValue(); 653 return true; 654 } 655 else 656 return false; 657} 658 659bool wxExpr::GetAttributeValue(const wxString& att, float& var) const 660{ 661 wxExpr *expr = AttributeValue(att); 662 if (expr && (expr->Type() == wxExprInteger || expr->Type() == wxExprReal)) 663 { 664 var = (float) expr->RealValue(); 665 return true; 666 } 667 else 668 return false; 669} 670 671bool wxExpr::GetAttributeValue(const wxString& att, double& var) const 672{ 673 wxExpr *expr = AttributeValue(att); 674 if (expr && (expr->Type() == wxExprInteger || expr->Type() == wxExprReal)) 675 { 676 var = expr->RealValue(); 677 return true; 678 } 679 else 680 return false; 681} 682 683bool wxExpr::GetAttributeValue(const wxString& att, wxString& var) const // Word OR string -> string 684{ 685 wxExpr *expr = AttributeValue(att); 686 if (expr && expr->Type() == wxExprWord) 687 { 688 var = expr->WordValue(); 689 return true; 690 } 691 else if (expr && expr->Type() == wxExprString) 692 { 693 var = expr->StringValue(); 694 return true; 695 } 696 else 697 return false; 698} 699 700bool wxExpr::GetAttributeValue(const wxString& att, wxExpr **var) const 701{ 702 wxExpr *expr = AttributeValue(att); 703 if (expr) 704 { 705 *var = expr; 706 return true; 707 } 708 else 709 return false; 710} 711 712bool wxExpr::GetAttributeValueStringList(const wxString& att, wxList *var) const 713{ 714 wxExpr *expr = AttributeValue(att); 715 if (expr && expr->Type() == wxExprList) 716 { 717 wxExpr *string_expr = expr->value.first; 718 while (string_expr) 719 { 720 if (string_expr->Type() == wxExprString) 721 var->Append((wxObject *)copystring(string_expr->StringValue())); 722 723 string_expr = string_expr->next; 724 } 725 return true; 726 } 727 else 728 return false; 729} 730 731// Compatibility 732void wxExpr::AssignAttributeValue(wxChar *att, wxChar **var) const 733{ 734 wxString str; 735 if (GetAttributeValue(att, str)) 736 { 737 if (*var) 738 delete[] *var; 739 *var = copystring((const wxChar *) str); 740 } 741} 742 743void wxExpr::WriteClause(FILE* stream) // Write this expression as a top-level clause 744{ 745 if (type != wxExprList) 746 return; 747 748 wxExpr *node = value.first; 749 if (node) 750 { 751 node->WriteExpr(stream); 752 fprintf( stream, "(" ); 753 node = node->next; 754 bool first = true; 755 while (node) 756 { 757 if (!first) 758 fprintf( stream, " " ); 759 node->WriteExpr(stream); 760 node = node->next; 761 if (node) 762 fprintf( stream, ",\n" ); 763 first = false; 764 } 765 fprintf( stream, ").\n\n" ); 766 } 767} 768 769void wxExpr::WriteExpr(FILE* stream) // Write as any other subexpression 770{ 771 // This seems to get round an optimizer bug when 772 // using Watcom C++ 10a in WIN32 compilation mode. 773 // If these lines not present, the type seems to be 774 // interpreted wrongly as an integer. 775 // I don't want to turn optimization off since it's needed 776 // for reading in files quickly. 777#if defined(__WATCOMC__) 778 char buf[2]; 779 sprintf(buf, ""); 780#endif 781 782 switch (type) 783 { 784 case wxExprInteger: 785 { 786 fprintf( stream, "%ld", value.integer ); 787 break; 788 } 789 case wxExprReal: 790 { 791 double f = value.real; 792 fprintf( stream, "%.6g", f); 793 break; 794 } 795 case wxExprString: 796 { 797 fprintf( stream, "\"" ); 798 size_t i; 799 const wxWX2MBbuf val = wxConvLibc.cWX2MB(value.string); 800 size_t len = strlen(val); 801 for (i = 0; i < len; i++) 802 { 803 char ch = val[i]; 804 if (ch == '"' || ch == '\\') 805 fprintf( stream, "\\" ); 806 char tmp[2]; 807 tmp[0] = ch; 808 tmp[1] = 0; 809 fprintf( stream, tmp ); 810 } 811 fprintf( stream, "\"" ); 812 break; 813 } 814 case wxExprWord: 815 { 816 bool quote_it = false; 817 const wxWX2MBbuf val = wxConvLibc.cWX2MB(value.word); 818 size_t len = strlen(val); 819 if ((len == 0) || (len > 0 && (val[(size_t) 0] > 64 && val[(size_t) 0] < 91))) 820 quote_it = true; 821 else 822 { 823 size_t i; 824 for (i = 0; i < len; i++) 825 if ((!isalpha(val[i])) && (!isdigit(val[i])) && 826 (val[i] != '_')) 827 { quote_it = true; i = len; } 828 } 829 830 if (quote_it) 831 fprintf( stream ,"'" ); 832 833 fprintf( stream, val ); 834 835 if (quote_it) 836 fprintf( stream, "'" ); 837 838 break; 839 } 840 case wxExprList: 841 { 842 if (!value.first) 843 fprintf( stream, "[]" ); 844 else 845 { 846 wxExpr *expr = value.first; 847 848 if ((expr->Type() == wxExprWord) && (wxStrcmp(expr->WordValue(), wxT("=")) == 0)) 849 { 850 wxExpr *arg1 = expr->next; 851 wxExpr *arg2 = arg1->next; 852 arg1->WriteExpr(stream); 853 fprintf( stream, " = " ); 854 arg2->WriteExpr(stream); 855 } 856 else 857 { 858 fprintf( stream, "[" ); 859 while (expr) 860 { 861 expr->WriteExpr(stream); 862 expr = expr->next; 863 if (expr) 864 fprintf( stream, ", " ); 865 } 866 fprintf( stream, "]" ); 867 } 868 } 869 break; 870 } 871 case wxExprNull: break; 872 } 873} 874 875/* 876 * wxExpr 'database' (list of expressions) 877 */ 878 879IMPLEMENT_DYNAMIC_CLASS(wxExprDatabase, wxList) 880 881wxExprDatabase::wxExprDatabase(wxExprErrorHandler handler) 882{ 883 position = NULL; 884 hash_table = NULL; 885 currentwxExprErrorHandler = handler; 886 noErrors = 0; 887} 888 889wxExprDatabase::wxExprDatabase(wxExprType type, const wxString& attribute, int size, 890 wxExprErrorHandler handler) 891{ 892 position = NULL; 893 attribute_to_hash = attribute; 894 if (type == wxExprString) 895 hash_table = new wxHashTable(wxKEY_STRING, size); 896 else if (type == wxExprInteger) 897 hash_table = new wxHashTable(wxKEY_INTEGER, size); 898 else hash_table = NULL; 899 900 currentwxExprErrorHandler = handler; 901 noErrors = 0; 902} 903 904wxExprDatabase::~wxExprDatabase(void) 905{ 906 ClearDatabase(); 907 if (hash_table) 908 delete hash_table; 909} 910 911void wxExprDatabase::BeginFind(void) // Initialise a search 912{ 913 position = GetFirst(); 914} 915 916wxExpr *wxExprDatabase::FindClause(long id) // Find a term based on an integer id attribute 917 // e.g. node(id=23, type=rectangle, ....). 918{ 919 wxExpr *found = NULL; 920 while (position && !found) 921 { 922 wxExpr *term = (wxExpr *)position->GetData(); 923 924 if (term->Type() == wxExprList) 925 { 926 wxExpr *value = term->AttributeValue(wxT("id")); 927 if (value->Type() == wxExprInteger && value->IntegerValue() == id) 928 found = term; 929 } 930 position = position->GetNext(); 931 } 932 return found; 933} 934 935// Find on basis of attribute/value pairs, e.g. type=rectangle 936wxExpr *wxExprDatabase::FindClause(const wxString& word, const wxString& val) 937{ 938 wxExpr *found = NULL; 939 while (position && !found) 940 { 941 wxExpr *term = (wxExpr *)position->GetData(); 942 943 if (term->Type() == wxExprList) 944 { 945 wxExpr *value = term->AttributeValue(word); 946 if ((value->Type() == wxExprWord && value->WordValue() == val) || 947 (value->Type() == wxExprString && value->StringValue() == val)) 948 found = term; 949 } 950 position = position->GetNext(); 951 } 952 return found; 953} 954 955wxExpr *wxExprDatabase::FindClause(const wxString& word, long val) 956{ 957 wxExpr *found = NULL; 958 while (position && !found) 959 { 960 wxExpr *term = (wxExpr *)position->GetData(); 961 962 if (term->Type() == wxExprList) 963 { 964 wxExpr *value = term->AttributeValue(word); 965 if ((value->Type() == wxExprInteger) && (value->IntegerValue() == val)) 966 found = term; 967 } 968 position = position->GetNext(); 969 } 970 return found; 971} 972 973wxExpr *wxExprDatabase::FindClause(const wxString& word, double val) 974{ 975 wxExpr *found = NULL; 976 while (position && !found) 977 { 978 wxExpr *term = (wxExpr *)position->GetData(); 979 980 if (term->Type() == wxExprList) 981 { 982 wxExpr *value = term->AttributeValue(word); 983 if ((value->Type() == wxExprReal) && (value->RealValue() == val)) 984 found = term; 985 } 986 position = position->GetNext(); 987 } 988 return found; 989} 990 991wxExpr *wxExprDatabase::FindClauseByFunctor(const wxString& functor) 992{ 993 wxExpr *found = NULL; 994 while (position && !found) 995 { 996 wxExpr *term = (wxExpr *)position->GetData(); 997 998 if (term->Type() == wxExprList) 999 { 1000 if (term->Functor() == functor) 1001 found = term; 1002 } 1003 position = position->GetNext(); 1004 } 1005 return found; 1006} 1007 1008// If hashing is on, must store in hash table too 1009void wxExprDatabase::Append(wxExpr *clause) 1010{ 1011 wxList::Append((wxObject *)clause); 1012 if (hash_table) 1013 { 1014 wxString functor(clause->Functor()); 1015 wxExpr *expr = clause->AttributeValue(attribute_to_hash); 1016 if (expr) 1017 { 1018 long functor_key = hash_table->MakeKey(WXSTRINGCAST functor); 1019 long value_key; 1020 if (expr && expr->Type() == wxExprString) 1021 { 1022 value_key = hash_table->MakeKey(WXSTRINGCAST expr->StringValue()); 1023 hash_table->Put(functor_key + value_key, WXSTRINGCAST expr->StringValue(), (wxObject *)clause); 1024 } 1025 else if (expr && expr->Type() == wxExprInteger) 1026 { 1027 value_key = expr->IntegerValue(); 1028 hash_table->Put(functor_key + value_key, expr->IntegerValue(), (wxObject *)clause); 1029 } 1030 1031 } 1032 } 1033} 1034 1035wxExpr *wxExprDatabase::HashFind(const wxString& functor, long value) const 1036{ 1037 long key = hash_table->MakeKey(WXSTRINGCAST functor) + value; 1038 1039 // The key alone isn't guaranteed to be unique: 1040 // must supply value too. Let's assume the value of the 1041 // id is going to be reasonably unique. 1042 return (wxExpr *)hash_table->Get(key, value); 1043} 1044 1045wxExpr *wxExprDatabase::HashFind(const wxString& functor, const wxString& value) const 1046{ 1047 long key = hash_table->MakeKey(WXSTRINGCAST functor) + hash_table->MakeKey(WXSTRINGCAST value); 1048 return (wxExpr *)hash_table->Get(key, WXSTRINGCAST value); 1049} 1050 1051void wxExprDatabase::ClearDatabase(void) 1052{ 1053 noErrors = 0; 1054 wxNode *node = GetFirst(); 1055 while (node) 1056 { 1057 wxExpr *expr = (wxExpr *)node->GetData(); 1058 delete expr; 1059 delete node; 1060 node = GetFirst(); 1061 } 1062 1063 if (hash_table) 1064 hash_table->Clear(); 1065} 1066 1067bool wxExprDatabase::Read(const wxString& filename) 1068{ 1069 noErrors = 0; 1070 1071 FILE *f = wxFopen(filename, _T("r")); 1072 if (f) 1073 { 1074 thewxExprDatabase = this; 1075 1076 LexFromFile(f); 1077 yyparse(); 1078 fclose(f); 1079 1080 wxExprCleanUp(); 1081 return (noErrors == 0); 1082 } 1083 else 1084 { 1085 return false; 1086 } 1087} 1088 1089bool wxExprDatabase::ReadFromString(const wxString& buffer) 1090{ 1091 noErrors = 0; 1092 thewxExprDatabase = this; 1093 1094 const wxWX2MBbuf buf = buffer.mb_str(); 1095 LexFromString(wxMBSTRINGCAST buf); 1096 yyparse(); 1097 wxExprCleanUp(); 1098 return (noErrors == 0); 1099} 1100 1101bool wxExprDatabase::Write(const wxString& fileName) 1102{ 1103 FILE *stream = wxFopen( fileName, _T("w+")); 1104 1105 if (!stream) 1106 return false; 1107 1108 bool success = Write(stream); 1109 fclose(stream); 1110 return success; 1111} 1112 1113bool wxExprDatabase::Write(FILE *stream) 1114{ 1115 noErrors = 0; 1116 wxNode *node = GetFirst(); 1117 while (node) 1118 { 1119 wxExpr *expr = (wxExpr *)node->GetData(); 1120 expr->WriteClause(stream); 1121 node = node->GetNext(); 1122 } 1123 return (noErrors == 0); 1124} 1125 1126void add_expr(wxExpr * expr) 1127{ 1128 thewxExprDatabase->Append(expr); 1129} 1130 1131// Checks functor 1132bool wxExprIsFunctor(wxExpr *expr, const wxString& functor) 1133{ 1134 if (expr && (expr->Type() == wxExprList)) 1135 { 1136 wxExpr *first_expr = expr->value.first; 1137 1138 if (first_expr && (first_expr->Type() == wxExprWord) && 1139 (first_expr->WordValue() == functor)) 1140 return true; 1141 else 1142 return false; 1143 } 1144 else 1145 return false; 1146} 1147 1148/* 1149 * Called from parser 1150 * 1151 */ 1152 1153char *wxmake_integer(char *str) 1154{ 1155 wxExpr *x = new wxExpr(atol(str)); 1156 1157 return (char *)x; 1158} 1159 1160char *wxmake_real(char *str1, char *str2) 1161{ 1162 char buf[50]; 1163 1164 sprintf(buf, "%s.%s", str1, str2); 1165 double f = (double)atof(buf); 1166 wxExpr *x = new wxExpr(f); 1167 1168 return (char *)x; 1169} 1170 1171// extern "C" double exp10(double); 1172 1173char *wxmake_exp(char *str1, char *str2) 1174{ 1175 double mantissa = (double)atoi(str1); 1176 double exponent = (double)atoi(str2); 1177 1178 double d = mantissa * pow(10.0, exponent); 1179 1180 wxExpr *x = new wxExpr(d); 1181 1182 return (char *)x; 1183} 1184 1185char *wxmake_exp2(char *str1, char *str2, char *str3) 1186{ 1187 char buf[50]; 1188 1189 sprintf(buf, "%s.%s", str1, str2); 1190 double mantissa = (double)atof(buf); 1191 double exponent = (double)atoi(str3); 1192 1193 double d = mantissa * pow(10.0, exponent); 1194 1195 wxExpr *x = new wxExpr(d); 1196 1197 return (char *)x; 1198} 1199 1200char *wxmake_word(char *str) 1201{ 1202 wxExpr *x = new wxExpr(wxExprWord, wxString(str, wxConvLibc).c_str()); 1203 return (char *)x; 1204} 1205 1206char *wxmake_string(char *str) 1207{ 1208 wxChar *s, *t; 1209 size_t len, i; 1210 const wxMB2WXbuf sbuf = wxConvLibc.cMB2WX(str); 1211 1212// str++; /* skip leading quote */ 1213 len = wxStrlen(sbuf) - 1; /* ignore trailing quote */ 1214 1215 s = new wxChar[len + 1]; 1216 1217 t = s; 1218 for(i=1; i<len; i++) // 1 since we want to skip leading quote 1219 { 1220 if (sbuf[i] == wxT('\\') && sbuf[i+1] == wxT('"')) 1221 { 1222 *t++ = wxT('"'); 1223 i ++; 1224 } 1225 else if (sbuf[i] == wxT('\\') && sbuf[i+1] == wxT('\\')) 1226 { 1227 *t++ = wxT('\\'); 1228 i ++; 1229 } 1230 else 1231 *t++ = sbuf[i]; 1232 } 1233 1234 *t = wxT('\0'); 1235 1236 wxExpr *x = new wxExpr(wxExprString, s, false); 1237 return (char *)x; 1238} 1239 1240char *proio_cons(char * ccar, char * ccdr) 1241{ 1242 wxExpr *car = (wxExpr *)ccar; 1243 wxExpr *cdr = (wxExpr *)ccdr; 1244 1245 if (cdr == NULL) 1246 { 1247 cdr = new wxExpr(wxExprList); 1248 } 1249 if (car) 1250 cdr->Insert(car); 1251 return (char *)cdr; 1252} 1253 1254void process_command(char * cexpr) 1255{ 1256 wxExpr *expr = (wxExpr *)cexpr; 1257 add_expr(expr); 1258} 1259 1260void syntax_error(char *WXUNUSED(s)) 1261{ 1262 if (currentwxExprErrorHandler) 1263 (void)(*(currentwxExprErrorHandler))(WXEXPR_ERROR_SYNTAX, (char *)"syntax error"); 1264 if (thewxExprDatabase) thewxExprDatabase->noErrors += 1; 1265} 1266 1267#if 0 1268#ifdef _WINDLL 1269// char *__cdecl strdup(const char *s) 1270WXDLLEXPORT char *strdup(const char *s) 1271{ 1272 int len = strlen(s); 1273 char *new_s = (char *)malloc(sizeof(char)*(len+1)); 1274 strcpy(new_s, s); 1275 return new_s; 1276} 1277#endif 1278#endif 1279 1280#endif 1281 // wxUSE_PROLOGIO 1282