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