00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifdef HAVE_CONFIG_H
00026 # include <config.h>
00027 #endif
00028
00029 #include <stdio.h>
00030 #include <cassert>
00031 #include "ucfun.h"
00032 #include "ucstmt.h"
00033 #include "utils.h"
00034 #include "opcodes.h"
00035 #include "ucexpr.h"
00036
00037 using std::strlen;
00038 using std::memcpy;
00039
00040 Uc_scope Uc_function::globals(0);
00041 vector<Uc_intrinsic_symbol *> Uc_function::intrinsics;
00042 int Uc_function::num_global_statics = 0;
00043 int Uc_function::add_answer = -1, Uc_function::remove_answer = -1,
00044 Uc_function::push_answers = -1, Uc_function::pop_answers = -1,
00045 Uc_function::show_face = -1, Uc_function::remove_face = -1;
00046
00047
00048
00049
00050
00051 Uc_function::Uc_function
00052 (
00053 Uc_function_symbol *p
00054 ) : top(0), proto(p), cur_scope(&top), num_parms(0),
00055 num_locals(0), num_statics(0), text_data(0), text_data_size(0),
00056 statement(0), reloffset(0)
00057 {
00058 char *nm = (char *) proto->get_name();
00059 add_global_function_symbol(proto);
00060 #if 0
00061 if (!globals.search(nm))
00062 globals.add(proto);
00063 else
00064 {
00065 char buf[100];
00066 sprintf(buf, "Name '%s' already defined", nm);
00067 Uc_location::yyerror(buf);
00068 }
00069 #endif
00070 const std::vector<char *>& parms = proto->get_parms();
00071 for (std::vector<char *>::const_iterator it = parms.begin();
00072 it != parms.end(); it++)
00073 add_symbol(*it);
00074 num_parms = num_locals;
00075 num_locals = 0;
00076 }
00077
00078
00079
00080
00081
00082 Uc_function::~Uc_function
00083 (
00084 )
00085 {
00086 delete statement;
00087 delete proto;
00088
00089 std::map<std::string, Uc_label*>::iterator iter;
00090 for (iter = labels.begin(); iter != labels.end(); ++iter)
00091 delete iter->second;
00092 }
00093
00094
00095
00096
00097
00098
00099
00100 bool Uc_function::is_dup
00101 (
00102 Uc_scope *scope,
00103 char *nm
00104 )
00105 {
00106 Uc_symbol *sym = scope->search(nm);
00107 if (sym)
00108 {
00109 char msg[180];
00110 sprintf(msg, "Symbol '%s' already declared", nm);
00111 Uc_location::yyerror(msg);
00112 return true;
00113 }
00114 return false;
00115 }
00116
00117
00118
00119
00120
00121
00122
00123 Uc_label *Uc_function::search_label(char *nm)
00124 {
00125 std::map<std::string,Uc_label*>::iterator iter;
00126 iter = labels.find(nm);
00127 if (iter != labels.end())
00128 return iter->second;
00129 return 0;
00130 }
00131
00132
00133
00134
00135
00136
00137
00138 Uc_var_symbol *Uc_function::add_symbol
00139 (
00140 char *nm
00141 )
00142 {
00143 if (is_dup(cur_scope, nm))
00144 return 0;
00145
00146 Uc_var_symbol *var = new Uc_var_symbol(nm, num_parms + num_locals++);
00147 cur_scope->add(var);
00148 return var;
00149 }
00150
00151
00152
00153
00154
00155 void Uc_function::add_static
00156 (
00157 char *nm
00158 )
00159 {
00160 if (is_dup(cur_scope, nm))
00161 return;
00162
00163 Uc_var_symbol *var = new Uc_static_var_symbol(nm, num_statics++);
00164 cur_scope->add(var);
00165 }
00166
00167
00168
00169
00170
00171 Uc_symbol *Uc_function::add_string_symbol
00172 (
00173 char *nm,
00174 char *text
00175 )
00176 {
00177 if (is_dup(cur_scope, nm))
00178 return 0;
00179
00180 Uc_symbol *sym = new Uc_string_symbol(nm, add_string(text));
00181 cur_scope->add(sym);
00182 return sym;
00183 }
00184
00185
00186
00187
00188
00189
00190
00191 Uc_symbol *Uc_function::add_int_const_symbol
00192 (
00193 char *nm,
00194 int value
00195 )
00196 {
00197 if (is_dup(cur_scope, nm))
00198 return 0;
00199
00200 Uc_const_int_symbol *var = new Uc_const_int_symbol(nm, value);
00201 cur_scope->add(var);
00202 return var;
00203 }
00204
00205
00206
00207
00208
00209
00210
00211 Uc_symbol *Uc_function::add_global_int_const_symbol
00212 (
00213 char *nm,
00214 int value
00215 )
00216 {
00217 if (is_dup(&globals, nm))
00218 return 0;
00219
00220 Uc_const_int_symbol *var = new Uc_const_int_symbol(nm, value);
00221 globals.add(var);
00222 return var;
00223 }
00224
00225
00226
00227
00228
00229 void Uc_function::add_global_static
00230 (
00231 char *nm
00232 )
00233 {
00234 if (is_dup(&globals, nm))
00235 return;
00236 num_global_statics++;
00237
00238 Uc_var_symbol *var = new Uc_static_var_symbol(nm,
00239 -num_global_statics);
00240 globals.add(var);
00241 }
00242
00243
00244
00245
00246
00247
00248
00249 int Uc_function::add_string
00250 (
00251 char *text
00252 )
00253 {
00254
00255 std::map<std::string, int>::const_iterator exist = text_map.find(text);
00256 if (exist != text_map.end())
00257 return (*exist).second;
00258 int offset = text_data_size;
00259 int textlen = strlen(text) + 1;
00260 char *new_text_data = new char[text_data_size + textlen];
00261 if (text_data_size)
00262 memcpy(new_text_data, text_data, text_data_size);
00263
00264 memcpy(new_text_data + text_data_size, text, textlen);
00265 delete text_data;
00266 text_data = new_text_data;
00267 text_data_size += textlen;
00268 text_map[text] = offset;
00269 return offset;
00270 }
00271
00272
00273
00274
00275
00276
00277
00278
00279 int Uc_function::find_string_prefix
00280 (
00281 Uc_location& loc,
00282 const char *text
00283 )
00284 {
00285 int len = strlen(text);
00286
00287 std::map<std::string, int>::const_iterator exist =
00288 text_map.lower_bound(text);
00289 if (exist == text_map.end() ||
00290 strncmp(text, (*exist).first.c_str(), len) != 0)
00291 {
00292 char *buf = new char[len + 100];
00293 sprintf(buf, "Prefix '%s' matches no string in this function",
00294 text);
00295 loc.error(buf);
00296 delete buf;
00297 return 0;
00298 }
00299 std::map<std::string, int>::const_iterator next = exist;
00300 ++next;
00301 if (next != text_map.end() &&
00302 strncmp(text, (*next).first.c_str(), len) == 0)
00303 {
00304 char *buf = new char[len + 100];
00305 sprintf(buf, "Prefix '%s' matches more than one string", text);
00306 loc.error(buf);
00307 delete buf;
00308 }
00309 return (*exist).second;
00310 }
00311
00312
00313
00314
00315
00316 void Uc_function::start_breakable
00317 (
00318 Uc_statement *s
00319 )
00320 {
00321 breakables.push_back(s);
00322 breaks.push_back(-1);
00323 }
00324
00325
00326
00327
00328
00329 void Uc_function::end_breakable
00330 (
00331 Uc_statement *s,
00332 vector<char>& stmt_code
00333 )
00334 {
00335
00336 assert(!breakables.empty() && s == breakables.back());
00337 breakables.pop_back();
00338 int stmtlen = stmt_code.size();
00339
00340
00341 while (!breaks.empty() && breaks.back() >= 0)
00342 {
00343 int break_offset = breaks.back();
00344 breaks.pop_back();
00345 assert(break_offset < stmtlen - 2);
00346
00347 Write2(stmt_code, break_offset + 1,
00348 stmtlen - (break_offset + 3));
00349 }
00350 assert(!breaks.empty() && breaks.back() == -1);
00351 breaks.pop_back();
00352 }
00353
00354
00355
00356
00357
00358
00359 void Uc_function::add_break
00360 (
00361 int op_offset
00362 )
00363 {
00364 assert(op_offset >= 0);
00365 if (breakables.empty())
00366 Uc_location::yyerror("'break' is not valid here");
00367 else
00368 breaks.push_back(op_offset);
00369 }
00370
00371
00372
00373
00374
00375
00376
00377 int Uc_function::link
00378 (
00379 Uc_function_symbol *fun
00380 )
00381 {
00382 for (std::vector<Uc_function_symbol *>::const_iterator it = links.begin();
00383 it != links.end(); it++)
00384 if (*it == fun)
00385 return (it - links.begin());
00386 int offset = links.size();
00387 links.push_back(fun);
00388 return offset;
00389 }
00390
00391
00392 void Uc_function::link_labels(vector<char>& code)
00393 {
00394 std::map<std::string, Uc_label*>::iterator iter;
00395 for (iter = labels.begin(); iter != labels.end(); ++iter) {
00396 Uc_label *label = iter->second;
00397 if (label->is_valid()) {
00398 int target = label->get_offset();
00399 std::vector<int>& references = label->get_references();
00400 std::vector<int>::iterator i;
00401 for (i = references.begin(); i != references.end(); ++i) {
00402 int offset = (*i) + 1;
00403 Write2(code, offset, target - (offset + 2));
00404 }
00405 }
00406 }
00407 }
00408
00409
00410
00411
00412
00413 void Uc_function::gen
00414 (
00415 std::ostream& out
00416 )
00417 {
00418
00419 Write2(out, proto->get_usecode_num());
00420 vector<char> code;
00421 code.reserve(30000);
00422 if (statement)
00423 statement->gen(code, this);
00424 code.push_back((char) UC_RET);
00425 link_labels(code);
00426 int codelen = code.size();
00427 int num_links = links.size();
00428
00429
00430
00431 int totallen = 2 + text_data_size + 2 + 2 + 2 + 2*num_links + codelen;
00432 Write2(out, totallen);
00433 Write2(out, text_data_size);
00434 out.write(text_data, text_data_size);
00435 Write2(out, num_parms);
00436 Write2(out, num_locals);
00437 Write2(out, num_links);
00438
00439 for (std::vector<Uc_function_symbol *>::const_iterator it =
00440 links.begin(); it != links.end(); it++)
00441 Write2(out, (*it)->get_usecode_num());
00442 char *ucstr = &code[0];
00443 out.write(ucstr, codelen);
00444 out.flush();
00445 }
00446
00447 #ifndef __STRING
00448 #if defined __STDC__ && __STDC__
00449 #define __STRING(x) #x
00450 #else
00451 #define __STRING(x) "x"
00452 #endif
00453 #endif
00454
00455
00456
00457
00458 #define USECODE_INTRINSIC_PTR(NAME) __STRING(UI_##NAME)
00459
00460 const char *bg_intrinsic_table[] =
00461 {
00462 #include "../bgintrinsics.h"
00463 };
00464
00465 const char *si_intrinsic_table[] =
00466 {
00467 #include "../siintrinsics.h"
00468 };
00469
00470
00471
00472
00473
00474 void Uc_function::set_intrinsics
00475 (
00476 Intrinsic_type ty
00477 )
00478 {
00479 int cnt;
00480 const char **table;
00481 if (ty == bg)
00482 {
00483 table = bg_intrinsic_table;
00484 cnt = sizeof(bg_intrinsic_table)/sizeof(bg_intrinsic_table[0]);
00485 add_answer = 5;
00486 remove_answer = 6;
00487 push_answers = 7;
00488 pop_answers = 8;
00489 }
00490 else
00491 {
00492 table = si_intrinsic_table;
00493 cnt = sizeof(si_intrinsic_table)/sizeof(si_intrinsic_table[0]);
00494 add_answer = 0xc;
00495 remove_answer = 0xd;
00496 push_answers = 0xe;
00497 pop_answers = 0xf;
00498 }
00499 show_face = 3;
00500 remove_face = 4;
00501 intrinsics.resize(cnt);
00502 for (int i = 0; i < cnt; i++)
00503 {
00504 char *nm = (char *)table[i];
00505 Uc_intrinsic_symbol *sym = new Uc_intrinsic_symbol(nm, i);
00506 intrinsics[i] = sym;
00507 if (!globals.search(nm))
00508
00509 globals.add(sym);
00510 }
00511 }
00512