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