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