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