]> git.saurik.com Git - wxWidgets.git/blame - src/common/wxexpr.cpp
calling SetValue(GetValue()) didn't reset the modified flag (bug 678391)
[wxWidgets.git] / src / common / wxexpr.cpp
CommitLineData
10b959e3
JS
1/////////////////////////////////////////////////////////////////////////////
2// Name: wxexpr.cpp
3// Purpose: wxExpr
4// Author: Julian Smart
5// Modified by:
6// Created: 04/01/98
7// RCS-ID: $Id$
55d99c7a
JS
8// Copyright: (c) Julian Smart
9// Licence: wxWindows licence
10b959e3
JS
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation "wxexpr.h"
14#endif
15
16// For compilers that support precompilation, includes "wx/wx.h".
17#include "wx/wxprec.h"
18
19#ifdef __BORLANDC__
20#pragma hdrstop
21#endif
22
2b5f62a0 23#if wxUSE_PROLOGIO
461e93f9 24
10b959e3
JS
25#include <stdarg.h>
26#include <ctype.h>
27#include <string.h>
28
29#include "wx/utils.h"
10b959e3
JS
30#include "wx/expr.h"
31#include "wx/wxexpr.h"
32
33extern "C" void add_expr(char *);
34extern "C" void LexFromFile(FILE *fd);
35extern "C" void LexFromString(char *buf);
36
f780dc86 37
8b766d97
VZ
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
105extern "C" WXDLLEXPORT_DATA(FILE*) yyin;
106extern "C" WXDLLEXPORT int yyparse(void);
107
108
10b959e3
JS
109wxExprDatabase *thewxExprDatabase = NULL;
110wxExprErrorHandler currentwxExprErrorHandler;
111
10b959e3
JS
112wxExpr::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
124wxExpr::wxExpr(wxExprType the_type, const wxString& word_or_string)
125{
126 type = the_type;
127
128 switch (the_type)
129 {
130 case wxExprWord:
1ec11a06 131 value.word = copystring((const wxChar *)word_or_string);
10b959e3
JS
132 break;
133 case wxExprString:
1ec11a06 134 value.string = copystring((const wxChar *)word_or_string);
10b959e3
JS
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
1ec11a06 149wxExpr::wxExpr(wxExprType the_type, wxChar *word_or_string, bool allocate)
10b959e3
JS
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
174wxExpr::wxExpr(long the_integer)
175{
176 type = wxExprInteger;
177 value.integer = the_integer;
178 client_data = NULL;
179 next = NULL;
180}
181
12ed6eb5 182wxExpr::wxExpr(double the_real)
10b959e3
JS
183{
184 type = wxExprReal;
185 value.real = the_real;
186 client_data = NULL;
187 next = NULL;
188}
189
190wxExpr::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
211wxExpr::~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
246void 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
256void wxExpr::Insert(wxExpr *expr)
257{
258 expr->next = value.first;
259 value.first = expr;
260
261 if (!last)
262 last = expr;
263}
264
265wxExpr *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, ...
309wxExpr *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) &&
1ec11a06 324 (wxStrcmp((const wxChar *)word, secondNode->value.word) == 0))
10b959e3
JS
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, ...
337wxExpr *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
348wxString wxExpr::Functor(void) const // Use only for a clause
349{
350 if ((type != wxExprList) || !value.first)
223d09f6 351 return wxString(wxT(""));
10b959e3
JS
352
353 if (value.first->type == wxExprWord)
354 return wxString(value.first->value.word);
355 else
223d09f6 356 return wxString(wxT(""));
10b959e3
JS
357}
358
359bool 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 &&
1ec11a06 365 (wxStrcmp((const wxChar *)f, value.first->value.word) == 0));
10b959e3
JS
366}
367
368// Return nth argument of a clause (starting from 1)
369wxExpr *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)
384wxExpr *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
403int 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
418void 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) &&
1ec11a06 434 (wxStrcmp((const wxChar *)attribute, secondNode->value.word) == 0))
10b959e3
JS
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
454void 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);
223d09f6 466 wxExpr *pequals = new wxExpr(wxExprWord, wxT("="));
10b959e3
JS
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
477void 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);
223d09f6 490 wxExpr *pequals = new wxExpr(wxExprWord, wxT("="));
10b959e3
JS
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
12ed6eb5 501void wxExpr::AddAttributeValue(const wxString& attribute, double val)
10b959e3
JS
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);
223d09f6 512 wxExpr *pequals = new wxExpr(wxExprWord, wxT("="));
10b959e3
JS
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
523void 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);
223d09f6 535 wxExpr *pequals = new wxExpr(wxExprWord, wxT("="));
10b959e3
JS
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
546void 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);
223d09f6 558 wxExpr *pequals = new wxExpr(wxExprWord, wxT("="));
10b959e3
JS
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
569void 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);
223d09f6 583 wxExpr *pequals = new wxExpr(wxExprWord, wxT("="));
10b959e3
JS
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
594void 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 {
bf604268 611 wxChar *string = (wxChar*)node->GetData();
10b959e3
JS
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);
223d09f6 619 wxExpr *pequals = new wxExpr(wxExprWord, wxT("="));
10b959e3
JS
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
630bool 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
643bool 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
656bool wxExpr::GetAttributeValue(const wxString& att, float& var) const
12ed6eb5
JS
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
668bool wxExpr::GetAttributeValue(const wxString& att, double& var) const
10b959e3
JS
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
680bool 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
697bool 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
709bool 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
1ec11a06 729void wxExpr::AssignAttributeValue(wxChar *att, wxChar **var) const
10b959e3
JS
730{
731 wxString str;
732 if (GetAttributeValue(att, str))
733 {
734 if (*var)
735 delete[] *var;
1ec11a06 736 *var = copystring((const wxChar *) str);
10b959e3
JS
737 }
738}
739
fd15d8f1 740void wxExpr::WriteClause(FILE* stream) // Write this expression as a top-level clause
10b959e3
JS
741{
742 if (type != wxExprList)
743 return;
744
745 wxExpr *node = value.first;
746 if (node)
747 {
748 node->WriteExpr(stream);
fd15d8f1 749 fprintf( stream, "(" );
10b959e3
JS
750 node = node->next;
751 bool first = TRUE;
752 while (node)
753 {
754 if (!first)
fd15d8f1 755 fprintf( stream, " " );
10b959e3
JS
756 node->WriteExpr(stream);
757 node = node->next;
fd15d8f1
RR
758 if (node)
759 fprintf( stream, ",\n" );
10b959e3
JS
760 first = FALSE;
761 }
fd15d8f1 762 fprintf( stream, ").\n\n" );
10b959e3
JS
763 }
764}
765
fd15d8f1 766void wxExpr::WriteExpr(FILE* stream) // Write as any other subexpression
10b959e3
JS
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 {
fd15d8f1 783 fprintf( stream, "%ld", value.integer );
10b959e3
JS
784 break;
785 }
786 case wxExprReal:
787 {
12ed6eb5 788 double f = value.real;
fd15d8f1 789 fprintf( stream, "%.6g", f);
10b959e3
JS
790 break;
791 }
792 case wxExprString:
793 {
fd15d8f1 794 fprintf( stream, "\"" );
f6bcfd97 795 size_t i;
dcf924a3 796 const wxWX2MBbuf val = wxConvLibc.cWX2MB(value.string);
f6bcfd97 797 size_t len = strlen(val);
10b959e3
JS
798 for (i = 0; i < len; i++)
799 {
1ec11a06 800 char ch = val[i];
10b959e3 801 if (ch == '"' || ch == '\\')
f6bcfd97
BP
802 fprintf( stream, "\\" );
803 char tmp[2];
804 tmp[0] = ch;
805 tmp[1] = 0;
fd15d8f1 806 fprintf( stream, tmp );
10b959e3 807 }
fd15d8f1 808 fprintf( stream, "\"" );
10b959e3
JS
809 break;
810 }
811 case wxExprWord:
812 {
813 bool quote_it = FALSE;
dcf924a3 814 const wxWX2MBbuf val = wxConvLibc.cWX2MB(value.word);
f6bcfd97
BP
815 size_t len = strlen(val);
816 if ((len == 0) || (len > 0 && (val[(size_t) 0] > 64 && val[(size_t) 0] < 91)))
10b959e3
JS
817 quote_it = TRUE;
818 else
819 {
f6bcfd97 820 size_t i;
10b959e3 821 for (i = 0; i < len; i++)
1ec11a06
OK
822 if ((!isalpha(val[i])) && (!isdigit(val[i])) &&
823 (val[i] != '_'))
10b959e3
JS
824 { quote_it = TRUE; i = len; }
825 }
826
827 if (quote_it)
fd15d8f1 828 fprintf( stream ,"'" );
10b959e3 829
f6bcfd97 830 fprintf( stream, val );
10b959e3
JS
831
832 if (quote_it)
fd15d8f1 833 fprintf( stream, "'" );
10b959e3
JS
834
835 break;
836 }
837 case wxExprList:
838 {
839 if (!value.first)
fd15d8f1 840 fprintf( stream, "[]" );
10b959e3
JS
841 else
842 {
843 wxExpr *expr = value.first;
844
223d09f6 845 if ((expr->Type() == wxExprWord) && (wxStrcmp(expr->WordValue(), wxT("=")) == 0))
10b959e3
JS
846 {
847 wxExpr *arg1 = expr->next;
848 wxExpr *arg2 = arg1->next;
849 arg1->WriteExpr(stream);
fd15d8f1 850 fprintf( stream, " = " );
10b959e3
JS
851 arg2->WriteExpr(stream);
852 }
853 else
854 {
fd15d8f1 855 fprintf( stream, "[" );
10b959e3
JS
856 while (expr)
857 {
858 expr->WriteExpr(stream);
859 expr = expr->next;
fd15d8f1 860 if (expr)
f6bcfd97 861 fprintf( stream, ", " );
10b959e3 862 }
fd15d8f1 863 fprintf( stream, "]" );
10b959e3
JS
864 }
865 }
866 break;
867 }
868 case wxExprNull: break;
869 }
870}
871
8a0a092b
RR
872/*
873 * wxExpr 'database' (list of expressions)
874 */
875
8a0a092b 876IMPLEMENT_DYNAMIC_CLASS(wxExprDatabase, wxList)
8a0a092b 877
10b959e3
JS
878wxExprDatabase::wxExprDatabase(wxExprErrorHandler handler)
879{
880 position = NULL;
881 hash_table = NULL;
882 currentwxExprErrorHandler = handler;
883 noErrors = 0;
884}
885
886wxExprDatabase::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
901wxExprDatabase::~wxExprDatabase(void)
902{
903 ClearDatabase();
904 if (hash_table)
905 delete hash_table;
906}
907
908void wxExprDatabase::BeginFind(void) // Initialise a search
909{
910 position = First();
911}
912
913wxExpr *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 {
bf604268 923 wxExpr *value = term->AttributeValue(wxT("id"));
10b959e3
JS
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
933wxExpr *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
952wxExpr *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
12ed6eb5 970wxExpr *wxExprDatabase::FindClause(const wxString& word, double val)
10b959e3
JS
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
988wxExpr *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
1006void 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 {
1ec11a06 1015 long functor_key = hash_table->MakeKey(WXSTRINGCAST functor);
10b959e3
JS
1016 long value_key = 0;
1017 if (expr && expr->Type() == wxExprString)
1018 {
1ec11a06
OK
1019 value_key = hash_table->MakeKey(WXSTRINGCAST expr->StringValue());
1020 hash_table->Put(functor_key + value_key, WXSTRINGCAST expr->StringValue(), (wxObject *)clause);
10b959e3
JS
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
1032wxExpr *wxExprDatabase::HashFind(const wxString& functor, long value) const
1033{
1ec11a06 1034 long key = hash_table->MakeKey(WXSTRINGCAST functor) + value;
10b959e3
JS
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
1042wxExpr *wxExprDatabase::HashFind(const wxString& functor, const wxString& value) const
1043{
1ec11a06
OK
1044 long key = hash_table->MakeKey(WXSTRINGCAST functor) + hash_table->MakeKey(WXSTRINGCAST value);
1045 return (wxExpr *)hash_table->Get(key, WXSTRINGCAST value);
10b959e3
JS
1046}
1047
1048void 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
1064bool wxExprDatabase::Read(const wxString& filename)
1065{
1066 noErrors = 0;
1067
f6bcfd97 1068 FILE *f = wxFopen(filename, _T("r"));
10b959e3
JS
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
1086bool wxExprDatabase::ReadFromString(const wxString& buffer)
1087{
1088 noErrors = 0;
1089 thewxExprDatabase = this;
1090
fde7d98e 1091 const wxWX2MBbuf buf = buffer.mb_str();
e90c1d2a 1092 LexFromString(wxMBSTRINGCAST buf);
10b959e3
JS
1093 yyparse();
1094 wxExprCleanUp();
1095 return (noErrors == 0);
1096}
1097
1098bool wxExprDatabase::Write(const wxString& fileName)
1099{
f6bcfd97 1100 FILE *stream = wxFopen( fileName, _T("w+"));
fd15d8f1
RR
1101
1102 if (!stream)
10b959e3 1103 return FALSE;
fd15d8f1 1104
469eb89e
JS
1105 bool success = Write(stream);
1106 fclose(stream);
1107 return success;
10b959e3
JS
1108}
1109
fd15d8f1 1110bool wxExprDatabase::Write(FILE *stream)
10b959e3
JS
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
10b959e3
JS
1123void add_expr(wxExpr * expr)
1124{
1125 thewxExprDatabase->Append(expr);
1126}
1127
1128// Checks functor
1129bool 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
5b077d48 1150char *wxmake_integer(char *str)
10b959e3
JS
1151{
1152 wxExpr *x = new wxExpr(atol(str));
1153
1154 return (char *)x;
1155}
1156
5b077d48 1157char *wxmake_real(char *str1, char *str2)
10b959e3
JS
1158{
1159 char buf[50];
1160
1161 sprintf(buf, "%s.%s", str1, str2);
12ed6eb5 1162 double f = (double)atof(buf);
10b959e3
JS
1163 wxExpr *x = new wxExpr(f);
1164
1165 return (char *)x;
1166}
1167
1168// extern "C" double exp10(double);
1169
5b077d48 1170char *wxmake_exp(char *str1, char *str2)
10b959e3
JS
1171{
1172 double mantissa = (double)atoi(str1);
1173 double exponent = (double)atoi(str2);
1174
1175 double d = mantissa * pow(10.0, exponent);
1176
12ed6eb5 1177 wxExpr *x = new wxExpr(d);
10b959e3
JS
1178
1179 return (char *)x;
1180}
1181
5b077d48 1182char *wxmake_exp2(char *str1, char *str2, char *str3)
10b959e3
JS
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
12ed6eb5 1192 wxExpr *x = new wxExpr(d);
10b959e3
JS
1193
1194 return (char *)x;
1195}
1196
5b077d48 1197char *wxmake_word(char *str)
10b959e3 1198{
bf604268 1199 wxExpr *x = new wxExpr(wxExprWord, wxString(str, wxConvLibc).c_str());
10b959e3
JS
1200 return (char *)x;
1201}
1202
5b077d48 1203char *wxmake_string(char *str)
10b959e3 1204{
1ec11a06 1205 wxChar *s, *t;
f6bcfd97 1206 size_t len, i;
dcf924a3 1207 const wxMB2WXbuf sbuf = wxConvLibc.cMB2WX(str);
10b959e3 1208
63863e09 1209// str++; /* skip leading quote */
1ec11a06 1210 len = wxStrlen(sbuf) - 1; /* ignore trailing quote */
10b959e3 1211
1ec11a06 1212 s = new wxChar[len + 1];
10b959e3
JS
1213
1214 t = s;
63863e09 1215 for(i=1; i<len; i++) // 1 since we want to skip leading quote
10b959e3 1216 {
223d09f6 1217 if (sbuf[i] == wxT('\\') && sbuf[i+1] == wxT('"'))
10b959e3 1218 {
223d09f6 1219 *t++ = wxT('"');
10b959e3
JS
1220 i ++;
1221 }
223d09f6 1222 else if (sbuf[i] == wxT('\\') && sbuf[i+1] == wxT('\\'))
10b959e3 1223 {
223d09f6 1224 *t++ = wxT('\\');
10b959e3
JS
1225 i ++;
1226 }
1227 else
1ec11a06 1228 *t++ = sbuf[i];
10b959e3
JS
1229 }
1230
223d09f6 1231 *t = wxT('\0');
10b959e3
JS
1232
1233 wxExpr *x = new wxExpr(wxExprString, s, FALSE);
1234 return (char *)x;
1235}
1236
1237char *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
1251void process_command(char * cexpr)
1252{
1253 wxExpr *expr = (wxExpr *)cexpr;
1254 add_expr(expr);
1255}
1256
8fdca65c 1257void syntax_error(char *WXUNUSED(s))
10b959e3
JS
1258{
1259 if (currentwxExprErrorHandler)
90350682 1260 (void)(*(currentwxExprErrorHandler))(WXEXPR_ERROR_SYNTAX, (char *)"syntax error");
10b959e3
JS
1261 if (thewxExprDatabase) thewxExprDatabase->noErrors += 1;
1262}
1263
1264#if 0
1265#ifdef _WINDLL
1266// char *__cdecl strdup(const char *s)
1267WXDLLEXPORT 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
461e93f9
JS
1277#endif
1278 // wxUSE_PROLOGIO