home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / src / common / wxexpr.cpp < prev    next >
C/C++ Source or Header  |  2002-11-09  |  30KB  |  1,279 lines

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