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