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