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