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