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