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