]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/wxexpr.cpp
IsModified() function now works correctly
[wxWidgets.git] / src / common / wxexpr.cpp
... / ...
CommitLineData
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
33extern "C" void add_expr(char *);
34extern "C" void LexFromFile(FILE *fd);
35extern "C" void LexFromString(char *buf);
36
37wxExprDatabase *thewxExprDatabase = NULL;
38wxExprErrorHandler currentwxExprErrorHandler;
39
40IMPLEMENT_DYNAMIC_CLASS(wxExprDatabase, wxList)
41
42wxExpr::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
54wxExpr::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
79wxExpr::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
104wxExpr::wxExpr(long the_integer)
105{
106 type = wxExprInteger;
107 value.integer = the_integer;
108 client_data = NULL;
109 next = NULL;
110}
111
112wxExpr::wxExpr(float the_real)
113{
114 type = wxExprReal;
115 value.real = the_real;
116 client_data = NULL;
117 next = NULL;
118}
119
120wxExpr::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
141wxExpr::~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
176void 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
186void wxExpr::Insert(wxExpr *expr)
187{
188 expr->next = value.first;
189 value.first = expr;
190
191 if (!last)
192 last = expr;
193}
194
195wxExpr *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, ...
239wxExpr *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, ...
267wxExpr *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
278wxString 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
289bool 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)
299wxExpr *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)
314wxExpr *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
333int 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
348void 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
384void 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
407void 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
431void wxExpr::AddAttributeValue(const wxString& attribute, float 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
453void 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
476void 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
499void 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
524void 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
560bool 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
573bool 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
586bool 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 = expr->RealValue();
592 return TRUE;
593 }
594 else
595 return FALSE;
596}
597
598bool wxExpr::GetAttributeValue(const wxString& att, wxString& var) const // Word OR string -> string
599{
600 wxExpr *expr = AttributeValue(att);
601 if (expr && expr->Type() == wxExprWord)
602 {
603 var = expr->WordValue();
604 return TRUE;
605 }
606 else if (expr && expr->Type() == wxExprString)
607 {
608 var = expr->StringValue();
609 return TRUE;
610 }
611 else
612 return FALSE;
613}
614
615bool wxExpr::GetAttributeValue(const wxString& att, wxExpr **var) const
616{
617 wxExpr *expr = AttributeValue(att);
618 if (expr)
619 {
620 *var = expr;
621 return TRUE;
622 }
623 else
624 return FALSE;
625}
626
627bool wxExpr::GetAttributeValueStringList(const wxString& att, wxList *var) const
628{
629 wxExpr *expr = AttributeValue(att);
630 if (expr && expr->Type() == wxExprList)
631 {
632 wxExpr *string_expr = expr->value.first;
633 while (string_expr)
634 {
635 if (string_expr->Type() == wxExprString)
636 var->Append((wxObject *)copystring(string_expr->StringValue()));
637
638 string_expr = string_expr->next;
639 }
640 return TRUE;
641 }
642 else
643 return FALSE;
644}
645
646// Compatibility
647void wxExpr::AssignAttributeValue(char *att, char **var) const
648{
649 wxString str;
650 if (GetAttributeValue(att, str))
651 {
652 if (*var)
653 delete[] *var;
654 *var = copystring((const char *) str);
655 }
656}
657
658void wxExpr::WriteClause(ostream& stream) // Write this expression as a top-level clause
659{
660 if (type != wxExprList)
661 return;
662
663 wxExpr *node = value.first;
664 if (node)
665 {
666 node->WriteExpr(stream);
667 stream << "(";
668 node = node->next;
669 bool first = TRUE;
670 while (node)
671 {
672 if (!first)
673 stream << " ";
674 node->WriteExpr(stream);
675 node = node->next;
676 if (node) stream << ",\n";
677 first = FALSE;
678 }
679 stream << ").\n\n";
680 }
681}
682
683void wxExpr::WriteExpr(ostream& stream) // Write as any other subexpression
684{
685 // This seems to get round an optimizer bug when
686 // using Watcom C++ 10a in WIN32 compilation mode.
687 // If these lines not present, the type seems to be
688 // interpreted wrongly as an integer.
689 // I don't want to turn optimization off since it's needed
690 // for reading in files quickly.
691#if defined(__WATCOMC__)
692 char buf[2];
693 sprintf(buf, "");
694#endif
695
696 switch (type)
697 {
698 case wxExprInteger:
699 {
700 stream << value.integer;
701 break;
702 }
703 case wxExprReal:
704 {
705 float f = value.real;
706/* Now the parser can cope with this.
707 // Prevent printing in 'e' notation. Any better way?
708 if (fabs(f) < 0.00001)
709 f = 0.0;
710*/
711 char buf[40];
712 sprintf(buf, "%.6g", f);
713 stream << buf;
714 break;
715 }
716 case wxExprString:
717 {
718 stream << "\"";
719 int i;
720 int len = strlen(value.string);
721 for (i = 0; i < len; i++)
722 {
723 char ch = value.string[i];
724 if (ch == '"' || ch == '\\')
725 stream << "\\";
726 stream << ch;
727 }
728
729 stream << "\"";
730 break;
731 }
732 case wxExprWord:
733 {
734 bool quote_it = FALSE;
735 int len = strlen(value.word);
736 if ((len == 0) || (len > 0 && (value.word[0] > 64 && value.word[0] < 91)))
737 quote_it = TRUE;
738 else
739 {
740 int i;
741 for (i = 0; i < len; i++)
742 if ((!isalpha(value.word[i])) && (!isdigit(value.word[i])) &&
743 (value.word[i] != '_'))
744 { quote_it = TRUE; i = len; }
745 }
746
747 if (quote_it)
748 stream << "'";
749
750 stream << value.word;
751
752 if (quote_it)
753 stream << "'";
754
755 break;
756 }
757 case wxExprList:
758 {
759 if (!value.first)
760 stream << "[]";
761 else
762 {
763 wxExpr *expr = value.first;
764
765 if ((expr->Type() == wxExprWord) && (strcmp(expr->WordValue(), "=") == 0))
766 {
767 wxExpr *arg1 = expr->next;
768 wxExpr *arg2 = arg1->next;
769 arg1->WriteExpr(stream);
770 stream << " = ";
771 arg2->WriteExpr(stream);
772 }
773 else
774 {
775 stream << "[";
776 while (expr)
777 {
778 expr->WriteExpr(stream);
779 expr = expr->next;
780 if (expr) stream << ", ";
781 }
782 stream << "]";
783 }
784 }
785 break;
786 }
787 case wxExprNull: break;
788 }
789}
790
791void wxExpr::WriteLispExpr(ostream& stream)
792{
793 switch (type)
794 {
795 case wxExprInteger:
796 {
797 stream << value.integer;
798 break;
799 }
800 case wxExprReal:
801 {
802 stream << value.real;
803 break;
804 }
805 case wxExprString:
806 {
807 stream << "\"" << value.string << "\"";
808 break;
809 }
810 case wxExprWord:
811 {
812 stream << value.word;
813 break;
814 }
815 case wxExprList:
816 {
817 wxExpr *expr = value.first;
818
819 stream << "(";
820 while (expr)
821 {
822 expr->WriteLispExpr(stream);
823 expr = expr->next;
824 if (expr) stream << " ";
825 }
826
827 stream << ")";
828 break;
829 }
830 case wxExprNull: break;
831 }
832}
833
834// wxExpr 'database' (list of expressions)
835wxExprDatabase::wxExprDatabase(wxExprErrorHandler handler)
836{
837 position = NULL;
838 hash_table = NULL;
839 currentwxExprErrorHandler = handler;
840 noErrors = 0;
841}
842
843wxExprDatabase::wxExprDatabase(wxExprType type, const wxString& attribute, int size,
844 wxExprErrorHandler handler)
845{
846 position = NULL;
847 attribute_to_hash = attribute;
848 if (type == wxExprString)
849 hash_table = new wxHashTable(wxKEY_STRING, size);
850 else if (type == wxExprInteger)
851 hash_table = new wxHashTable(wxKEY_INTEGER, size);
852 else hash_table = NULL;
853
854 currentwxExprErrorHandler = handler;
855 noErrors = 0;
856}
857
858wxExprDatabase::~wxExprDatabase(void)
859{
860 ClearDatabase();
861 if (hash_table)
862 delete hash_table;
863}
864
865void wxExprDatabase::BeginFind(void) // Initialise a search
866{
867 position = First();
868}
869
870wxExpr *wxExprDatabase::FindClause(long id) // Find a term based on an integer id attribute
871 // e.g. node(id=23, type=rectangle, ....).
872{
873 wxExpr *found = NULL;
874 while (position && !found)
875 {
876 wxExpr *term = (wxExpr *)position->Data();
877
878 if (term->Type() == wxExprList)
879 {
880 wxExpr *value = term->AttributeValue("id");
881 if (value->Type() == wxExprInteger && value->IntegerValue() == id)
882 found = term;
883 }
884 position = position->Next();
885 }
886 return found;
887}
888
889// Find on basis of attribute/value pairs, e.g. type=rectangle
890wxExpr *wxExprDatabase::FindClause(const wxString& word, const wxString& val)
891{
892 wxExpr *found = NULL;
893 while (position && !found)
894 {
895 wxExpr *term = (wxExpr *)position->Data();
896
897 if (term->Type() == wxExprList)
898 {
899 wxExpr *value = term->AttributeValue(word);
900 if ((value->Type() == wxExprWord && value->WordValue() == val) ||
901 (value->Type() == wxExprString && value->StringValue() == val))
902 found = term;
903 }
904 position = position->Next();
905 }
906 return found;
907}
908
909wxExpr *wxExprDatabase::FindClause(const wxString& word, long val)
910{
911 wxExpr *found = NULL;
912 while (position && !found)
913 {
914 wxExpr *term = (wxExpr *)position->Data();
915
916 if (term->Type() == wxExprList)
917 {
918 wxExpr *value = term->AttributeValue(word);
919 if ((value->Type() == wxExprInteger) && (value->IntegerValue() == val))
920 found = term;
921 }
922 position = position->Next();
923 }
924 return found;
925}
926
927wxExpr *wxExprDatabase::FindClause(const wxString& word, float val)
928{
929 wxExpr *found = NULL;
930 while (position && !found)
931 {
932 wxExpr *term = (wxExpr *)position->Data();
933
934 if (term->Type() == wxExprList)
935 {
936 wxExpr *value = term->AttributeValue(word);
937 if ((value->Type() == wxExprReal) && (value->RealValue() == val))
938 found = term;
939 }
940 position = position->Next();
941 }
942 return found;
943}
944
945wxExpr *wxExprDatabase::FindClauseByFunctor(const wxString& functor)
946{
947 wxExpr *found = NULL;
948 while (position && !found)
949 {
950 wxExpr *term = (wxExpr *)position->Data();
951
952 if (term->Type() == wxExprList)
953 {
954 if (term->Functor() == functor)
955 found = term;
956 }
957 position = position->Next();
958 }
959 return found;
960}
961
962// If hashing is on, must store in hash table too
963void wxExprDatabase::Append(wxExpr *clause)
964{
965 wxList::Append((wxObject *)clause);
966 if (hash_table)
967 {
968 wxString functor(clause->Functor());
969 wxExpr *expr = clause->AttributeValue(attribute_to_hash);
970 if (expr)
971 {
972 long functor_key = hash_table->MakeKey((char *)(const char *)functor);
973 long value_key = 0;
974 if (expr && expr->Type() == wxExprString)
975 {
976 value_key = hash_table->MakeKey((char *)(const char *)expr->StringValue());
977 hash_table->Put(functor_key + value_key, (char *)(const char *)expr->StringValue(), (wxObject *)clause);
978 }
979 else if (expr && expr->Type() == wxExprInteger)
980 {
981 value_key = expr->IntegerValue();
982 hash_table->Put(functor_key + value_key, expr->IntegerValue(), (wxObject *)clause);
983 }
984
985 }
986 }
987}
988
989wxExpr *wxExprDatabase::HashFind(const wxString& functor, long value) const
990{
991 long key = hash_table->MakeKey((char *)(const char *)functor) + value;
992
993 // The key alone isn't guaranteed to be unique:
994 // must supply value too. Let's assume the value of the
995 // id is going to be reasonably unique.
996 return (wxExpr *)hash_table->Get(key, value);
997}
998
999wxExpr *wxExprDatabase::HashFind(const wxString& functor, const wxString& value) const
1000{
1001 long key = hash_table->MakeKey((char *)(const char *)functor) + hash_table->MakeKey((char *)(const char *)value);
1002 return (wxExpr *)hash_table->Get(key, (char *)(const char *)value);
1003}
1004
1005void wxExprDatabase::ClearDatabase(void)
1006{
1007 noErrors = 0;
1008 wxNode *node = First();
1009 while (node)
1010 {
1011 wxExpr *expr = (wxExpr *)node->Data();
1012 delete expr;
1013 delete node;
1014 node = First();
1015 }
1016
1017 if (hash_table)
1018 hash_table->Clear();
1019}
1020
1021bool wxExprDatabase::Read(const wxString& filename)
1022{
1023 noErrors = 0;
1024
1025 FILE *f = fopen((const char *)filename, "r");
1026 if (f)
1027 {
1028 thewxExprDatabase = this;
1029
1030 LexFromFile(f);
1031 yyparse();
1032 fclose(f);
1033
1034 wxExprCleanUp();
1035 return (noErrors == 0);
1036 }
1037 else
1038 {
1039 return FALSE;
1040 }
1041}
1042
1043bool wxExprDatabase::ReadFromString(const wxString& buffer)
1044{
1045 noErrors = 0;
1046 thewxExprDatabase = this;
1047
1048 LexFromString((char *)(const char *)buffer);
1049 yyparse();
1050 wxExprCleanUp();
1051 return (noErrors == 0);
1052}
1053
1054bool wxExprDatabase::Write(const wxString& fileName)
1055{
1056 ofstream str((char *)(const char *)fileName);
1057 if (str.bad())
1058 return FALSE;
1059 return Write(str);
1060}
1061
1062bool wxExprDatabase::Write(ostream& stream)
1063{
1064 noErrors = 0;
1065 wxNode *node = First();
1066 while (node)
1067 {
1068 wxExpr *expr = (wxExpr *)node->Data();
1069 expr->WriteClause(stream);
1070 node = node->Next();
1071 }
1072 return (noErrors == 0);
1073}
1074
1075void wxExprDatabase::WriteLisp(ostream& stream)
1076{
1077 noErrors = 0;
1078 wxNode *node = First();
1079 while (node)
1080 {
1081 wxExpr *expr = (wxExpr *)node->Data();
1082 expr->WriteLispExpr(stream);
1083 stream << "\n\n";
1084 node = node->Next();
1085 }
1086}
1087
1088void add_expr(wxExpr * expr)
1089{
1090 thewxExprDatabase->Append(expr);
1091}
1092
1093// Checks functor
1094bool wxExprIsFunctor(wxExpr *expr, const wxString& functor)
1095{
1096 if (expr && (expr->Type() == wxExprList))
1097 {
1098 wxExpr *first_expr = expr->value.first;
1099
1100 if (first_expr && (first_expr->Type() == wxExprWord) &&
1101 (first_expr->WordValue() == functor))
1102 return TRUE;
1103 else
1104 return FALSE;
1105 }
1106 else
1107 return FALSE;
1108}
1109
1110/*
1111 * Called from parser
1112 *
1113 */
1114
1115char *make_integer(char *str)
1116{
1117 wxExpr *x = new wxExpr(atol(str));
1118
1119 return (char *)x;
1120}
1121
1122char *make_real(char *str1, char *str2)
1123{
1124 char buf[50];
1125
1126 sprintf(buf, "%s.%s", str1, str2);
1127 float f = (float)atof(buf);
1128 wxExpr *x = new wxExpr(f);
1129
1130 return (char *)x;
1131}
1132
1133// extern "C" double exp10(double);
1134
1135char *make_exp(char *str1, char *str2)
1136{
1137 double mantissa = (double)atoi(str1);
1138 double exponent = (double)atoi(str2);
1139
1140 double d = mantissa * pow(10.0, exponent);
1141
1142 wxExpr *x = new wxExpr((float)d);
1143
1144 return (char *)x;
1145}
1146
1147char *make_exp2(char *str1, char *str2, char *str3)
1148{
1149 char buf[50];
1150
1151 sprintf(buf, "%s.%s", str1, str2);
1152 double mantissa = (double)atof(buf);
1153 double exponent = (double)atoi(str3);
1154
1155 double d = mantissa * pow(10.0, exponent);
1156
1157 wxExpr *x = new wxExpr((float)d);
1158
1159 return (char *)x;
1160}
1161
1162char *make_word(char *str)
1163{
1164 wxExpr *x = new wxExpr(wxExprWord, str);
1165 return (char *)x;
1166}
1167
1168char *make_string(char *str)
1169{
1170 char *s, *t;
1171 int len, i;
1172
1173 str++; /* skip leading quote */
1174 len = strlen(str) - 1; /* ignore trailing quote */
1175
1176 s = new char[len + 1];
1177
1178 t = s;
1179 for(i=0; i<len; i++)
1180 {
1181 if (str[i] == '\\' && str[i+1] == '"')
1182 {
1183 *t++ = '"';
1184 i ++;
1185 }
1186 else if (str[i] == '\\' && str[i+1] == '\\')
1187 {
1188 *t++ = '\\';
1189 i ++;
1190 }
1191 else
1192 *t++ = str[i];
1193 }
1194
1195 *t = '\0';
1196
1197 wxExpr *x = new wxExpr(wxExprString, s, FALSE);
1198 return (char *)x;
1199}
1200
1201char *proio_cons(char * ccar, char * ccdr)
1202{
1203 wxExpr *car = (wxExpr *)ccar;
1204 wxExpr *cdr = (wxExpr *)ccdr;
1205
1206 if (cdr == NULL)
1207 {
1208 cdr = new wxExpr(wxExprList);
1209 }
1210 if (car)
1211 cdr->Insert(car);
1212 return (char *)cdr;
1213}
1214
1215void process_command(char * cexpr)
1216{
1217 wxExpr *expr = (wxExpr *)cexpr;
1218 add_expr(expr);
1219}
1220
1221void syntax_error(char *s)
1222{
1223 if (currentwxExprErrorHandler)
1224 (void)(*(currentwxExprErrorHandler))(WXEXPR_ERROR_SYNTAX, "syntax error");
1225 if (thewxExprDatabase) thewxExprDatabase->noErrors += 1;
1226}
1227
1228#if 0
1229#ifdef _WINDLL
1230// char *__cdecl strdup(const char *s)
1231WXDLLEXPORT char *strdup(const char *s)
1232{
1233 int len = strlen(s);
1234 char *new_s = (char *)malloc(sizeof(char)*(len+1));
1235 strcpy(new_s, s);
1236 return new_s;
1237}
1238#endif
1239#endif
1240