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