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