]> git.saurik.com Git - wxWidgets.git/blame - src/common/wxexpr.cpp
wxGTK now chooses the best visual X offers,
[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
3f4a0c5b 9// Licence: wxWindows license
10b959e3
JS
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
3f4a0c5b 24 #include <fstream.h>
fbc535ff 25#else
3f4a0c5b 26 #include <fstream>
fbc535ff
JS
27#endif
28
10b959e3
JS
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
38extern "C" void add_expr(char *);
39extern "C" void LexFromFile(FILE *fd);
40extern "C" void LexFromString(char *buf);
41
f780dc86 42
10b959e3
JS
43wxExprDatabase *thewxExprDatabase = NULL;
44wxExprErrorHandler currentwxExprErrorHandler;
45
10b959e3
JS
46wxExpr::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
58wxExpr::wxExpr(wxExprType the_type, const wxString& word_or_string)
59{
60 type = the_type;
61
62 switch (the_type)
63 {
64 case wxExprWord:
1ec11a06 65 value.word = copystring((const wxChar *)word_or_string);
10b959e3
JS
66 break;
67 case wxExprString:
1ec11a06 68 value.string = copystring((const wxChar *)word_or_string);
10b959e3
JS
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
1ec11a06 83wxExpr::wxExpr(wxExprType the_type, wxChar *word_or_string, bool allocate)
10b959e3
JS
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
108wxExpr::wxExpr(long the_integer)
109{
110 type = wxExprInteger;
111 value.integer = the_integer;
112 client_data = NULL;
113 next = NULL;
114}
115
12ed6eb5 116wxExpr::wxExpr(double the_real)
10b959e3
JS
117{
118 type = wxExprReal;
119 value.real = the_real;
120 client_data = NULL;
121 next = NULL;
122}
123
124wxExpr::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
145wxExpr::~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
180void 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
190void wxExpr::Insert(wxExpr *expr)
191{
192 expr->next = value.first;
193 value.first = expr;
194
195 if (!last)
196 last = expr;
197}
198
199wxExpr *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, ...
243wxExpr *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) &&
1ec11a06 258 (wxStrcmp((const wxChar *)word, secondNode->value.word) == 0))
10b959e3
JS
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, ...
271wxExpr *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
282wxString wxExpr::Functor(void) const // Use only for a clause
283{
284 if ((type != wxExprList) || !value.first)
1ec11a06 285 return wxString(_T(""));
10b959e3
JS
286
287 if (value.first->type == wxExprWord)
288 return wxString(value.first->value.word);
289 else
1ec11a06 290 return wxString(_T(""));
10b959e3
JS
291}
292
293bool 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 &&
1ec11a06 299 (wxStrcmp((const wxChar *)f, value.first->value.word) == 0));
10b959e3
JS
300}
301
302// Return nth argument of a clause (starting from 1)
303wxExpr *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)
318wxExpr *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
337int 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
352void 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) &&
1ec11a06 368 (wxStrcmp((const wxChar *)attribute, secondNode->value.word) == 0))
10b959e3
JS
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
388void 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);
1ec11a06 400 wxExpr *pequals = new wxExpr(wxExprWord, _T("="));
10b959e3
JS
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
411void 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);
1ec11a06 424 wxExpr *pequals = new wxExpr(wxExprWord, _T("="));
10b959e3
JS
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
12ed6eb5 435void wxExpr::AddAttributeValue(const wxString& attribute, double val)
10b959e3
JS
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);
1ec11a06 446 wxExpr *pequals = new wxExpr(wxExprWord, _T("="));
10b959e3
JS
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
457void 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);
1ec11a06 469 wxExpr *pequals = new wxExpr(wxExprWord, _T("="));
10b959e3
JS
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
480void 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);
1ec11a06 492 wxExpr *pequals = new wxExpr(wxExprWord, _T("="));
10b959e3
JS
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
503void 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);
1ec11a06 517 wxExpr *pequals = new wxExpr(wxExprWord, _T("="));
10b959e3
JS
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
528void 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);
1ec11a06 553 wxExpr *pequals = new wxExpr(wxExprWord, _T("="));
10b959e3
JS
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
564bool 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
577bool 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
590bool wxExpr::GetAttributeValue(const wxString& att, float& var) const
12ed6eb5
JS
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
602bool wxExpr::GetAttributeValue(const wxString& att, double& var) const
10b959e3
JS
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
614bool 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
631bool 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
643bool 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
1ec11a06 663void wxExpr::AssignAttributeValue(wxChar *att, wxChar **var) const
10b959e3
JS
664{
665 wxString str;
666 if (GetAttributeValue(att, str))
667 {
668 if (*var)
669 delete[] *var;
1ec11a06 670 *var = copystring((const wxChar *) str);
10b959e3
JS
671 }
672}
673
674void 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
699void 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 {
12ed6eb5 721 double f = value.real;
10b959e3
JS
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;
dcf924a3 736 const wxWX2MBbuf val = wxConvLibc.cWX2MB(value.string);
1ec11a06 737 int len = strlen(val);
10b959e3
JS
738 for (i = 0; i < len; i++)
739 {
1ec11a06 740 char ch = val[i];
10b959e3
JS
741 if (ch == '"' || ch == '\\')
742 stream << "\\";
743 stream << ch;
744 }
745
746 stream << "\"";
747 break;
748 }
749 case wxExprWord:
750 {
751 bool quote_it = FALSE;
dcf924a3 752 const wxWX2MBbuf val = wxConvLibc.cWX2MB(value.word);
1ec11a06
OK
753 int len = strlen(val);
754 if ((len == 0) || (len > 0 && (val[0] > 64 && val[0] < 91)))
10b959e3
JS
755 quote_it = TRUE;
756 else
757 {
758 int i;
759 for (i = 0; i < len; i++)
1ec11a06
OK
760 if ((!isalpha(val[i])) && (!isdigit(val[i])) &&
761 (val[i] != '_'))
10b959e3
JS
762 { quote_it = TRUE; i = len; }
763 }
764
765 if (quote_it)
766 stream << "'";
767
1ec11a06 768 stream << val;
10b959e3
JS
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
1ec11a06 783 if ((expr->Type() == wxExprWord) && (wxStrcmp(expr->WordValue(), _T("=")) == 0))
10b959e3
JS
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
8a0a092b
RR
852/*
853 * wxExpr 'database' (list of expressions)
854 */
855
856#if !USE_SHARED_LIBRARIES
857IMPLEMENT_DYNAMIC_CLASS(wxExprDatabase, wxList)
858#endif
859
10b959e3
JS
860wxExprDatabase::wxExprDatabase(wxExprErrorHandler handler)
861{
862 position = NULL;
863 hash_table = NULL;
864 currentwxExprErrorHandler = handler;
865 noErrors = 0;
866}
867
868wxExprDatabase::wxExprDatabase(wxExprType type, const wxString& attribute, int size,
869 wxExprErrorHandler handler)
870{
871 position = NULL;
872 attribute_to_hash = attribute;
873 if (type == wxExprString)
874 hash_table = new wxHashTable(wxKEY_STRING, size);
875 else if (type == wxExprInteger)
876 hash_table = new wxHashTable(wxKEY_INTEGER, size);
877 else hash_table = NULL;
878
879 currentwxExprErrorHandler = handler;
880 noErrors = 0;
881}
882
883wxExprDatabase::~wxExprDatabase(void)
884{
885 ClearDatabase();
886 if (hash_table)
887 delete hash_table;
888}
889
890void wxExprDatabase::BeginFind(void) // Initialise a search
891{
892 position = First();
893}
894
895wxExpr *wxExprDatabase::FindClause(long id) // Find a term based on an integer id attribute
896 // e.g. node(id=23, type=rectangle, ....).
897{
898 wxExpr *found = NULL;
899 while (position && !found)
900 {
901 wxExpr *term = (wxExpr *)position->Data();
902
903 if (term->Type() == wxExprList)
904 {
905 wxExpr *value = term->AttributeValue("id");
906 if (value->Type() == wxExprInteger && value->IntegerValue() == id)
907 found = term;
908 }
909 position = position->Next();
910 }
911 return found;
912}
913
914// Find on basis of attribute/value pairs, e.g. type=rectangle
915wxExpr *wxExprDatabase::FindClause(const wxString& word, const wxString& val)
916{
917 wxExpr *found = NULL;
918 while (position && !found)
919 {
920 wxExpr *term = (wxExpr *)position->Data();
921
922 if (term->Type() == wxExprList)
923 {
924 wxExpr *value = term->AttributeValue(word);
925 if ((value->Type() == wxExprWord && value->WordValue() == val) ||
926 (value->Type() == wxExprString && value->StringValue() == val))
927 found = term;
928 }
929 position = position->Next();
930 }
931 return found;
932}
933
934wxExpr *wxExprDatabase::FindClause(const wxString& word, long val)
935{
936 wxExpr *found = NULL;
937 while (position && !found)
938 {
939 wxExpr *term = (wxExpr *)position->Data();
940
941 if (term->Type() == wxExprList)
942 {
943 wxExpr *value = term->AttributeValue(word);
944 if ((value->Type() == wxExprInteger) && (value->IntegerValue() == val))
945 found = term;
946 }
947 position = position->Next();
948 }
949 return found;
950}
951
12ed6eb5 952wxExpr *wxExprDatabase::FindClause(const wxString& word, double val)
10b959e3
JS
953{
954 wxExpr *found = NULL;
955 while (position && !found)
956 {
957 wxExpr *term = (wxExpr *)position->Data();
958
959 if (term->Type() == wxExprList)
960 {
961 wxExpr *value = term->AttributeValue(word);
962 if ((value->Type() == wxExprReal) && (value->RealValue() == val))
963 found = term;
964 }
965 position = position->Next();
966 }
967 return found;
968}
969
970wxExpr *wxExprDatabase::FindClauseByFunctor(const wxString& functor)
971{
972 wxExpr *found = NULL;
973 while (position && !found)
974 {
975 wxExpr *term = (wxExpr *)position->Data();
976
977 if (term->Type() == wxExprList)
978 {
979 if (term->Functor() == functor)
980 found = term;
981 }
982 position = position->Next();
983 }
984 return found;
985}
986
987// If hashing is on, must store in hash table too
988void wxExprDatabase::Append(wxExpr *clause)
989{
990 wxList::Append((wxObject *)clause);
991 if (hash_table)
992 {
993 wxString functor(clause->Functor());
994 wxExpr *expr = clause->AttributeValue(attribute_to_hash);
995 if (expr)
996 {
1ec11a06 997 long functor_key = hash_table->MakeKey(WXSTRINGCAST functor);
10b959e3
JS
998 long value_key = 0;
999 if (expr && expr->Type() == wxExprString)
1000 {
1ec11a06
OK
1001 value_key = hash_table->MakeKey(WXSTRINGCAST expr->StringValue());
1002 hash_table->Put(functor_key + value_key, WXSTRINGCAST expr->StringValue(), (wxObject *)clause);
10b959e3
JS
1003 }
1004 else if (expr && expr->Type() == wxExprInteger)
1005 {
1006 value_key = expr->IntegerValue();
1007 hash_table->Put(functor_key + value_key, expr->IntegerValue(), (wxObject *)clause);
1008 }
1009
1010 }
1011 }
1012}
1013
1014wxExpr *wxExprDatabase::HashFind(const wxString& functor, long value) const
1015{
1ec11a06 1016 long key = hash_table->MakeKey(WXSTRINGCAST functor) + value;
10b959e3
JS
1017
1018 // The key alone isn't guaranteed to be unique:
1019 // must supply value too. Let's assume the value of the
1020 // id is going to be reasonably unique.
1021 return (wxExpr *)hash_table->Get(key, value);
1022}
1023
1024wxExpr *wxExprDatabase::HashFind(const wxString& functor, const wxString& value) const
1025{
1ec11a06
OK
1026 long key = hash_table->MakeKey(WXSTRINGCAST functor) + hash_table->MakeKey(WXSTRINGCAST value);
1027 return (wxExpr *)hash_table->Get(key, WXSTRINGCAST value);
10b959e3
JS
1028}
1029
1030void wxExprDatabase::ClearDatabase(void)
1031{
1032 noErrors = 0;
1033 wxNode *node = First();
1034 while (node)
1035 {
1036 wxExpr *expr = (wxExpr *)node->Data();
1037 delete expr;
1038 delete node;
1039 node = First();
1040 }
1041
1042 if (hash_table)
1043 hash_table->Clear();
1044}
1045
1046bool wxExprDatabase::Read(const wxString& filename)
1047{
1048 noErrors = 0;
1049
1ec11a06 1050 FILE *f = fopen(filename.fn_str(), "r");
10b959e3
JS
1051 if (f)
1052 {
1053 thewxExprDatabase = this;
1054
1055 LexFromFile(f);
1056 yyparse();
1057 fclose(f);
1058
1059 wxExprCleanUp();
1060 return (noErrors == 0);
1061 }
1062 else
1063 {
1064 return FALSE;
1065 }
1066}
1067
1068bool wxExprDatabase::ReadFromString(const wxString& buffer)
1069{
1070 noErrors = 0;
1071 thewxExprDatabase = this;
1072
fde7d98e 1073 const wxWX2MBbuf buf = buffer.mb_str();
1ec11a06 1074 LexFromString(MBSTRINGCAST buf);
10b959e3
JS
1075 yyparse();
1076 wxExprCleanUp();
1077 return (noErrors == 0);
1078}
1079
1080bool wxExprDatabase::Write(const wxString& fileName)
1081{
1ec11a06 1082 ofstream str(MBSTRINGCAST fileName.mb_str());
10b959e3
JS
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 1195{
1ec11a06 1196 wxChar *s, *t;
10b959e3 1197 int len, i;
dcf924a3 1198 const wxMB2WXbuf sbuf = wxConvLibc.cMB2WX(str);
10b959e3 1199
63863e09 1200// str++; /* skip leading quote */
1ec11a06 1201 len = wxStrlen(sbuf) - 1; /* ignore trailing quote */
10b959e3 1202
1ec11a06 1203 s = new wxChar[len + 1];
10b959e3
JS
1204
1205 t = s;
63863e09 1206 for(i=1; i<len; i++) // 1 since we want to skip leading quote
10b959e3 1207 {
1ec11a06 1208 if (sbuf[i] == _T('\\') && sbuf[i+1] == _T('"'))
10b959e3 1209 {
1ec11a06 1210 *t++ = _T('"');
10b959e3
JS
1211 i ++;
1212 }
1ec11a06 1213 else if (sbuf[i] == _T('\\') && sbuf[i+1] == _T('\\'))
10b959e3 1214 {
1ec11a06 1215 *t++ = _T('\\');
10b959e3
JS
1216 i ++;
1217 }
1218 else
1ec11a06 1219 *t++ = sbuf[i];
10b959e3
JS
1220 }
1221
1ec11a06 1222 *t = _T('\0');
10b959e3
JS
1223
1224 wxExpr *x = new wxExpr(wxExprString, s, FALSE);
1225 return (char *)x;
1226}
1227
1228char *proio_cons(char * ccar, char * ccdr)
1229{
1230 wxExpr *car = (wxExpr *)ccar;
1231 wxExpr *cdr = (wxExpr *)ccdr;
1232
1233 if (cdr == NULL)
1234 {
1235 cdr = new wxExpr(wxExprList);
1236 }
1237 if (car)
1238 cdr->Insert(car);
1239 return (char *)cdr;
1240}
1241
1242void process_command(char * cexpr)
1243{
1244 wxExpr *expr = (wxExpr *)cexpr;
1245 add_expr(expr);
1246}
1247
8fdca65c 1248void syntax_error(char *WXUNUSED(s))
10b959e3
JS
1249{
1250 if (currentwxExprErrorHandler)
1251 (void)(*(currentwxExprErrorHandler))(WXEXPR_ERROR_SYNTAX, "syntax error");
1252 if (thewxExprDatabase) thewxExprDatabase->noErrors += 1;
1253}
1254
1255#if 0
1256#ifdef _WINDLL
1257// char *__cdecl strdup(const char *s)
1258WXDLLEXPORT char *strdup(const char *s)
1259{
1260 int len = strlen(s);
1261 char *new_s = (char *)malloc(sizeof(char)*(len+1));
1262 strcpy(new_s, s);
1263 return new_s;
1264}
1265#endif
1266#endif
1267