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