ucsym.cc

Go to the documentation of this file.
00001 
00007 /*
00008 Copyright (C) 2000 The Exult Team
00009 
00010 This program is free software; you can redistribute it and/or
00011 modify it under the terms of the GNU General Public License
00012 as published by the Free Software Foundation; either version 2
00013 of the License, or (at your option) any later version.
00014 
00015 This program is distributed in the hope that it will be useful,
00016 but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 GNU General Public License for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with this program; if not, write to the Free Software
00022 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00023 */
00024 
00025 #ifdef HAVE_CONFIG_H
00026 #  include <config.h>
00027 #endif
00028 
00029 
00030 #include <stdio.h>
00031 #include "ucsym.h"
00032 #include "opcodes.h"
00033 #include "utils.h"
00034 #include "ucexpr.h"
00035 #include "ucfun.h"
00036 
00037 using std::strcmp;
00038 
00039 int Uc_function_symbol::last_num = -1;
00040 Uc_function_symbol::Sym_nums Uc_function_symbol::nums_used;
00041 
00042 /*
00043  *  Assign value on stack.
00044  *
00045  *  Output: 0 if can't do this.
00046  */
00047 
00048 int Uc_symbol::gen_assign
00049   (
00050   vector<char>& out
00051   )
00052   {
00053   return 0;
00054   }
00055 
00056 /*
00057  *  Generate code to push variable's value on stack.
00058  *
00059  *  Output: 0 if can't do this.
00060  */
00061 
00062 int Uc_symbol::gen_value
00063   (
00064   vector<char>& out
00065   )
00066   {
00067   return 0;
00068   }
00069 
00070 /*
00071  *  Generate function call.
00072  *
00073  *  Output: 0 if can't do this.
00074  */
00075 
00076 int Uc_symbol::gen_call
00077   (
00078   vector<char>& out,
00079   Uc_function *fun,
00080   bool orig,      // Call original (not one from patch).
00081   Uc_expression *itemref,   // Non-NULL for CALLE.
00082   Uc_array_expression *parms, // Parameter list.
00083   bool retvalue     // True if a function.
00084   )
00085   {
00086   return 0;
00087   }
00088 
00089 /*
00090  *  Create an expression with this value.
00091  */
00092 
00093 Uc_expression *Uc_symbol::create_expression
00094   (
00095   )
00096   {
00097   return 0;
00098   }
00099 
00100 /*
00101  *  Assign value on stack.
00102  *
00103  *  Output: 0 if can't do this.
00104  */
00105 
00106 int Uc_var_symbol::gen_assign
00107   (
00108   vector<char>& out
00109   )
00110   {
00111   out.push_back((char) UC_POP);
00112   Write2(out, offset);
00113   return 1;
00114   }
00115 
00116 /*
00117  *  Generate code to push variable's value on stack.
00118  *
00119  *  Output: 0 if can't do this.
00120  */
00121 
00122 int Uc_var_symbol::gen_value
00123   (
00124   vector<char>& out
00125   )
00126   {
00127   out.push_back((char) UC_PUSH);
00128   Write2(out, offset);
00129   return 1;
00130   }
00131 
00132 /*
00133  *  Create an expression with this value.
00134  */
00135 
00136 Uc_expression *Uc_var_symbol::create_expression
00137   (
00138   )
00139   {
00140   return new Uc_var_expression(this);
00141   }
00142 
00143 /*
00144  *  Assign value on stack.
00145  *
00146  *  Output: 0 if can't do this.
00147  */
00148 
00149 int Uc_static_var_symbol::gen_assign
00150   (
00151   vector<char>& out
00152   )
00153   {
00154   out.push_back((char) UC_POPSTATIC);
00155   Write2(out, offset);
00156   return 1;
00157   }
00158 
00159 /*
00160  *  Generate code to push variable's value on stack.
00161  *
00162  *  Output: 0 if can't do this.
00163  */
00164 
00165 int Uc_static_var_symbol::gen_value
00166   (
00167   vector<char>& out
00168   )
00169   {
00170   out.push_back((char) UC_PUSHSTATIC);
00171   Write2(out, offset);
00172   return 1;
00173   }
00174 
00175 /*
00176  *  Generate code to push variable's value on stack.
00177  *
00178  *  Output: 0 if can't do this.
00179  */
00180 
00181 int Uc_const_int_symbol::gen_value
00182   (
00183   vector<char>& out
00184   )
00185   {
00186   out.push_back((char) UC_PUSHI);
00187   Write2(out, value);
00188   return 1;
00189   }
00190 
00191 /*
00192  *  Create an expression with this value.
00193  */
00194 
00195 Uc_expression *Uc_const_int_symbol::create_expression
00196   (
00197   )
00198   {
00199   return new Uc_int_expression(value);
00200   }
00201 
00202 /*
00203  *  Generate code to push variable's value on stack.
00204  *
00205  *  Output: 0 if can't do this.
00206  */
00207 
00208 int Uc_string_symbol::gen_value
00209   (
00210   vector<char>& out
00211   )
00212   {
00213   out.push_back((char) UC_PUSHS);
00214   Write2(out, offset);
00215   return 1;
00216   }
00217 
00218 /*
00219  *  Create an expression with this value.
00220  */
00221 
00222 Uc_expression *Uc_string_symbol::create_expression
00223   (
00224   )
00225   {
00226   return new Uc_string_expression(offset);
00227   }
00228 
00229 /*
00230  *  Generate function call.
00231  *
00232  *  Output: 0 if can't do this.
00233  */
00234 
00235 int Uc_intrinsic_symbol::gen_call
00236   (
00237   vector<char>& out,
00238   Uc_function *fun,
00239   bool orig,      // Call original (not one from patch).
00240   Uc_expression *itemref,   // Non-NULL for CALLE.
00241   Uc_array_expression *parms, // Parameter list.
00242   bool retvalue     // True if a function.
00243   )
00244   {
00245   int parmcnt = 0;
00246   if (itemref)      // Makes no sense for intrinsice.
00247     Uc_location::yyerror("Can't use ITEM for intrinsic");
00248           // Want to push parm. values.
00249   const std::vector<Uc_expression *>& exprs = parms->get_exprs();
00250           // Push backwards, so #0 pops first.
00251   for (std::vector<Uc_expression *>::const_reverse_iterator it = 
00252       exprs.rbegin(); it != exprs.rend(); it++)
00253     {
00254     Uc_expression *expr = *it;
00255     expr->gen_value(out);
00256     parmcnt++;
00257     }
00258           // ++++ parmcnt == num_parms.
00259           // Opcode depends on val. returned.
00260   out.push_back((char) (retvalue ? UC_CALLIS : UC_CALLI));
00261   Write2(out, intrinsic_num); // Intrinsic # is 2 bytes.
00262   out.push_back((char) parmcnt);  // Parm. count is 1.
00263   return 1;
00264   }
00265 
00266 /*
00267  *  Create new function.
00268  */
00269 
00270 Uc_function_symbol::Uc_function_symbol
00271   (
00272   char *nm, 
00273   int num,      // Function #, or -1 to assign
00274           //  1 + last_num.
00275   std::vector<char *>& p
00276   ) :  Uc_symbol(nm), parms(p), usecode_num(num)
00277   {
00278   last_num = usecode_num = num >= 0 ? num : (last_num + 1);
00279           // Keep track of #'s used.
00280   Sym_nums::const_iterator it = nums_used.find(usecode_num);
00281   if (it == nums_used.end())  // Unused?  That's good.
00282     nums_used[usecode_num] = this;
00283   else
00284     {
00285     char buf[256];
00286     sprintf(buf, "Function 0x%x already used for '%s'.",
00287         usecode_num, ((*it).second)->get_name());
00288     Uc_location::yyerror(buf);
00289     }
00290   }
00291 
00292 /*
00293  *  Generate function call.
00294  *
00295  *  Output: 0 if can't do this.
00296  */
00297 
00298 int Uc_function_symbol::gen_call
00299   (
00300   vector<char>& out,
00301   Uc_function *fun,
00302   bool orig,      // Call original (not one from patch).
00303   Uc_expression *itemref,   // Non-NULL for CALLE.
00304   Uc_array_expression *aparms,  // Actual parameter list.
00305   bool /* retvalue */   // True if a function.
00306   )
00307   {
00308   int parmcnt = 0;
00309           // Want to push parm. values.
00310   const std::vector<Uc_expression *>& exprs = aparms->get_exprs();
00311           // Push forwards, so #0 pops last.
00312   for (std::vector<Uc_expression *>::const_iterator it = exprs.begin(); 
00313             it != exprs.end(); it++)
00314     {
00315     Uc_expression *expr = *it;
00316     expr->gen_value(out);
00317     parmcnt++;
00318     }
00319   if (parmcnt != parms.size())
00320     {
00321     char buf[100];
00322     sprintf(buf,
00323       "# parms. passed (%d) doesn't match '%s' count (%d)",
00324       parmcnt, get_name(), parms.size());
00325     }       
00326   if (orig)
00327     {
00328     if (!itemref)
00329       {
00330       Uc_item_expression item;
00331       item.gen_value(out);
00332       }
00333     else
00334       itemref->gen_value(out);
00335     out.push_back((char) UC_CALLO);
00336     Write2(out, usecode_num); // Use fun# directly.
00337     }
00338   else if (itemref) // Doing CALLE?  Push item onto stack.
00339     {
00340     itemref->gen_value(out);
00341     out.push_back((char) UC_CALLE);
00342     Write2(out, usecode_num); // Use fun# directly.
00343     }
00344   else        // Normal CALL.
00345     {     // Called function sets return.
00346     out.push_back((char) UC_CALL);
00347           // Get offset in function's list.
00348     int link = fun->link(this);
00349     Write2(out, link);
00350     }
00351   return 1;
00352   }
00353 
00354 
00355 bool String_compare::operator()(char * const &x, char * const &y) const
00356   { return strcmp(x, y) < 0; }
00357 
00358 /*
00359  *  Delete.
00360  */
00361 
00362 Uc_scope::~Uc_scope
00363   (
00364   )
00365   {
00366   for (std::map<char *, Uc_symbol *, String_compare>::iterator it = symbols.begin();
00367         it != symbols.end(); it++)
00368     delete (*it).second;
00369   for (std::vector<Uc_scope *>::iterator it = scopes.begin();
00370         it != scopes.end(); it++)
00371     delete *it;
00372   }
00373 
00374 /*
00375  *  Search upwards through scope.
00376  *
00377  *  Output: ->symbol if found, else 0.
00378  */
00379 
00380 Uc_symbol *Uc_scope::search_up
00381   (
00382   char *nm
00383   )
00384   {
00385   Uc_symbol *found = search(nm);  // First look here.
00386   if (found)
00387     return found;
00388   if (parent)     // Look upwards.
00389     return parent->search_up(nm);
00390   else
00391     return 0;
00392   }
00393 
00394 /*
00395  *  Add a function symbol.
00396  *
00397  *  Output: 0 if already there.  Errors reported.
00398  */
00399 
00400 int Uc_scope::add_function_symbol
00401   (
00402   Uc_function_symbol *fun
00403   )
00404   {
00405   char buf[150];
00406   const char *nm = fun->get_name();
00407   Uc_symbol *found = search(nm);  // Already here?
00408   if (!found)     // If not, that's good.
00409     {
00410     add(fun);
00411     return 1;
00412     }
00413   Uc_function_symbol *fun2 = dynamic_cast<Uc_function_symbol *> (found);
00414   if (!fun2)      // Non-function name.
00415     {
00416     sprintf(buf, "'%s' already declared", nm);
00417     Uc_location::yyerror(buf);
00418     }
00419   else if (fun->get_usecode_num() != fun2->get_usecode_num() ||
00420     fun->get_num_parms() != fun2->get_num_parms())
00421     {
00422     sprintf(buf, "Decl. of '%s' doesn't match previous decl", nm);
00423     Uc_location::yyerror(buf);
00424     }
00425   return 0;
00426   }
00427 
00428 

Generated on Mon Jul 9 14:42:51 2007 for ExultEngine by  doxygen 1.5.1