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