diff options
author | Ben Longbons <b.r.longbons@gmail.com> | 2013-06-11 21:55:13 -0700 |
---|---|---|
committer | Ben Longbons <b.r.longbons@gmail.com> | 2013-06-11 23:27:33 -0700 |
commit | 8b5370313dcc00a45ea5c3e8b4c497bc00fd8e13 (patch) | |
tree | 15e8a4841af992e17794f26fc7991ed40c35bd51 /src/map/magic-interpreter-parser.ypp | |
parent | 8c6072df499ef9068346fbe8313b63dbba1e4e82 (diff) | |
download | tmwa-8b5370313dcc00a45ea5c3e8b4c497bc00fd8e13.tar.gz tmwa-8b5370313dcc00a45ea5c3e8b4c497bc00fd8e13.tar.bz2 tmwa-8b5370313dcc00a45ea5c3e8b4c497bc00fd8e13.tar.xz tmwa-8b5370313dcc00a45ea5c3e8b4c497bc00fd8e13.zip |
Allegedly remove all manual memory management
Diffstat (limited to 'src/map/magic-interpreter-parser.ypp')
-rw-r--r-- | src/map/magic-interpreter-parser.ypp | 506 |
1 files changed, 212 insertions, 294 deletions
diff --git a/src/map/magic-interpreter-parser.ypp b/src/map/magic-interpreter-parser.ypp index 2baa854..2cec1f2 100644 --- a/src/map/magic-interpreter-parser.ypp +++ b/src/map/magic-interpreter-parser.ypp @@ -7,8 +7,10 @@ { #include "magic-interpreter-parser.hpp" +#include <cassert> #include <cstdarg> // exception to "no va_list" rule, even after cxxstdio +#include "../common/const_array.hpp" #include "../common/cxxstdio.hpp" #include "itemdb.hpp" @@ -17,22 +19,26 @@ // I still don't get why this is necessary. #define YYLEX_PARAM 0, 0 +#pragma GCC diagnostic warning "-Wall" +#pragma GCC diagnostic warning "-Wextra" +#pragma GCC diagnostic warning "-Wformat" + static -int intern_id(const char *id_name); +size_t intern_id(const_string id_name); static -expr_t *fun_expr(const char *name, int args_nr, expr_t **args, int line, int column); +dumb_ptr<expr_t> fun_expr(const std::string& name, const_array<dumb_ptr<expr_t>> argv, int line, int column); static -expr_t *dot_expr(expr_t *lhs, int id); +dumb_ptr<expr_t> dot_expr(dumb_ptr<expr_t> lhs, int id); static -void BIN_EXPR(expr_t *& x, const char *name, expr_t *arg1, expr_t *arg2, int line, int column) +void BIN_EXPR(dumb_ptr<expr_t> & x, const std::string& name, dumb_ptr<expr_t> arg1, dumb_ptr<expr_t> arg2, int line, int column) { - expr_t *e[2]; + dumb_ptr<expr_t> e[2]; e[0] = arg1; e[1] = arg2; - x = fun_expr(name, 2, e, line, column); + x = fun_expr(name, const_array<dumb_ptr<expr_t>>(e, 2), line, column); } static @@ -41,47 +47,47 @@ int failed_flag = 0; static void magic_frontend_error(const char *msg); -static +static __attribute__((format(printf, 3, 4))) void fail(int line, int column, const char *fmt, ...); static -spell_t *new_spell(spellguard_t *guard); +dumb_ptr<spell_t> new_spell(dumb_ptr<spellguard_t> guard); static -spellguard_t *spellguard_implication(spellguard_t *a, spellguard_t *b); +dumb_ptr<spellguard_t> spellguard_implication(dumb_ptr<spellguard_t> a, dumb_ptr<spellguard_t> b); static -spellguard_t *new_spellguard(SPELLGUARD ty); +dumb_ptr<spellguard_t> new_spellguard(SPELLGUARD ty); static -effect_t *new_effect(EFFECT ty); +dumb_ptr<effect_t> new_effect(EFFECT ty); static -effect_t *set_effect_continuation(effect_t *src, effect_t *continuation); +dumb_ptr<effect_t> set_effect_continuation(dumb_ptr<effect_t> src, dumb_ptr<effect_t> continuation); static -void add_spell(spell_t *spell, int line_nr); +void add_spell(dumb_ptr<spell_t> spell, int line_nr); static -void add_teleport_anchor(teleport_anchor_t *anchor, int line_nr); +void add_teleport_anchor(dumb_ptr<teleport_anchor_t> anchor, int line_nr); static -effect_t *op_effect(char *name, int args_nr, expr_t **args, int line, int column); +dumb_ptr<effect_t> op_effect(const std::string& name, const_array<dumb_ptr<expr_t>> argv, int line, int column); // in magic-interpreter-lexer.cpp int magic_frontend_lex(YYSTYPE *, YYLTYPE *); static -void install_proc(proc_t *proc); +void install_proc(dumb_ptr<proc_t> proc); static -effect_t *call_proc(char *name, int args_nr, expr_t **args, int line_nr, int column); +dumb_ptr<effect_t> call_proc(const_string name, dumb_ptr<std::vector<dumb_ptr<expr_t>>> argvp, int line_nr, int column); static -void bind_constant(char *name, val_t *val, int line_nr); +void bind_constant(const std::string& name, val_t *val, int line_nr); static -val_t *find_constant(char *name); +val_t *find_constant(const std::string& name); } // %code @@ -95,23 +101,29 @@ val_t *find_constant(char *name); SPELL_FLAG spell_flags; SPELLARG spell_arg; FOREACH_FILTER foreach_filter; - char *s; + dumb_string s; int op; - magic_conf_t *magic_conf; + // magic_conf_t *magic_conf; val_t value; - expr_t *expr; + dumb_ptr<expr_t> expr; e_location_t location; e_area_t area; args_rec_t arg_list; - struct { int letdefs_nr; letdef_t *letdefs; } letdefs; - spell_t *spell; + dumb_ptr<std::vector<letdef_t>> letdefvp; + dumb_ptr<spell_t> spell; struct { int id; SPELLARG ty; } spellarg_def; letdef_t vardef; - spellguard_t *spellguard; - component_t *components; - struct {int id, count; } component; - effect_t *effect; - proc_t *proc; + dumb_ptr<spellguard_t> spellguard; + dumb_ptr<component_t> components; + struct { int id, count; } component; + dumb_ptr<effect_t> effect; + dumb_ptr<proc_t> proc; + + // evil hackery + YYSTYPE() { memset(this, '\0', sizeof(*this)); } + ~YYSTYPE() = default; + YYSTYPE(const YYSTYPE& rhs) = default; + YYSTYPE& operator = (const YYSTYPE& rhs) = default; } // %union %expect 7 @@ -193,7 +205,7 @@ val_t *find_constant(char *name); %type <area> area %type <arg_list> arg_list %type <arg_list> arg_list_ne -%type <letdefs> defs +%type <letdefvp> defs %type <spell> spelldef %type <spellarg_def> argopt %type <vardef> def @@ -257,7 +269,7 @@ proc_formals_list : /* empty */ { - CREATE($$, proc_t, 1); + $$ = dumb_ptr<proc_t>::make(); } | proc_formals_list_ne @@ -272,17 +284,16 @@ proc_formals_list_ne : ID { - CREATE($$, proc_t, 1); - $$->args_nr = 1; - $$->args = (int*)malloc(sizeof(int)); - $$->args[0] = intern_id($1); + $$ = dumb_ptr<proc_t>::make(); + $$->argv.push_back(intern_id($1)); + $1.delete_(); } | proc_formals_list_ne ',' ID { $$ = $1; - $$->args = (int *)realloc($$->args, sizeof(int) * (1 + $$->args_nr)); - $$->args[$$->args_nr++] = intern_id($3); + $$->argv.push_back(intern_id($3)); + $3.delete_(); } ; @@ -292,56 +303,59 @@ spellconf_option : ID '=' expr { - int var_id; - if (find_constant($1)) + if (find_constant($1.str())) { - fail(@1.first_line, 0, "Attempt to redefine constant `%s' as global\n", $1); - free($1); + fail(@1.first_line, 0, "Attempt to redefine constant `%s' as global\n", $1.c_str()); } else { - var_id = intern_id($1); - magic_eval(&magic_default_env, &magic_conf.vars[var_id], $3); + int var_id = intern_id($1); + magic_eval(dumb_ptr<env_t>(&magic_default_env), &magic_conf.varv[var_id].val, $3); } + $1.delete_(); } | CONST ID '=' expr { val_t var; - magic_eval(&magic_default_env, &var, $4); - bind_constant($2, &var, @1.first_line); + magic_eval(dumb_ptr<env_t>(&magic_default_env), &var, $4); + bind_constant($2.str(), &var, @1.first_line); + $2.delete_(); } | TELEPORT_ANCHOR ID ':' expr '=' expr { - teleport_anchor_t *anchor; - CREATE(anchor, teleport_anchor_t, 1); - anchor->name = $2; - anchor->invocation = magic_eval_str(&magic_default_env, $4); - anchor->location = $6; + auto anchor = dumb_ptr<teleport_anchor_t>::make(); + anchor->name = $2.str(); + $2.delete_(); + anchor->invocation = magic_eval_str(dumb_ptr<env_t>(&magic_default_env), $4); + anchor->location = $6; - if (!failed_flag) - add_teleport_anchor(anchor, @1.first_line); - else - free(anchor); - failed_flag = 0; + if (!failed_flag) + add_teleport_anchor(anchor, @1.first_line); + else + anchor.delete_(); + failed_flag = 0; } | PROCEDURE ID '(' proc_formals_list ')' '=' effect_list { - proc_t *proc = $4; - proc->name = $2; - proc->body = $7; - if (!failed_flag) - install_proc(proc); - failed_flag = 0; + dumb_ptr<proc_t> proc = $4; + proc->name = $2.str(); + $2.delete_(); + proc->body = $7; + if (!failed_flag) + install_proc(proc); + proc.delete_(); + failed_flag = 0; } | spell_flags SPELL ID argopt ':' expr '=' spelldef { - spell_t *spell = $8; - spell->name = $3; - spell->invocation = magic_eval_str(&magic_default_env, $6); + dumb_ptr<spell_t> spell = $8; + spell->name = $3.str(); + $3.delete_(); + spell->invocation = magic_eval_str(dumb_ptr<env_t>(&magic_default_env), $6); spell->arg = $4.id; spell->spellarg_ty = $4.ty; spell->flags = $1; @@ -394,6 +408,7 @@ argopt | '(' ID ':' arg_ty ')' { $$.id = intern_id($2); + $2.delete_(); $$.ty = $4; } @@ -448,8 +463,8 @@ expr | ID { - val_t *val; - if ((val = find_constant($1))) + val_t *val = find_constant($1.str()); + if (val) { $$ = magic_new_expr(EXPR::VAL); $$->e.e_val = *val; @@ -459,6 +474,7 @@ expr $$ = magic_new_expr(EXPR::ID); $$->e.e_id = intern_id($1); } + $1.delete_(); } | area @@ -560,15 +576,14 @@ expr | expr NEQ expr { BIN_EXPR($$, "=", $1, $3, @1.first_line, @1.first_column); - $$ = fun_expr("not", 1, &$$, @1.first_line, @1.first_column); + $$ = fun_expr("not", const_array<dumb_ptr<expr_t>>(&$$, 1), @1.first_line, @1.first_column); } | ID '(' arg_list ')' { - $$ = fun_expr($1, $3.args_nr, $3.args, @1.first_line, @1.first_column); - if ($3.args) - free($3.args); - free($1); + $$ = fun_expr($1.str(), *$3.argvp, @1.first_line, @1.first_column); + $3.argvp.delete_(); + $1.delete_(); // allocated from m-i-lexer.lpp } | '(' expr ')' @@ -579,6 +594,7 @@ expr | expr '.' ID { $$ = dot_expr($1, intern_id($3)); + $3.delete_(); } ; @@ -588,7 +604,7 @@ arg_list : /* empty */ { - $$.args_nr = 0; + $$.argvp.new_(); } | arg_list_ne @@ -603,15 +619,15 @@ arg_list_ne : expr { - CREATE($$.args, expr_t *, 1); - $$.args_nr = 1; - $$.args[0] = $1; + $$.argvp.new_(); + $$.argvp->push_back($1); } | arg_list_ne ',' expr { - RECREATE($$.args, expr_t *, 1 + $$.args_nr); - $$.args[$$.args_nr++] = $3; + // yikes! Fate is officially banned from ever touching my code again. + $$ = $1; + $$.argvp->push_back($3); } ; @@ -667,8 +683,8 @@ spelldef | LET defs IN spellbody_list { $$ = new_spell($4); - $$->letdefs_nr = $2.letdefs_nr; - $$->letdefs = $2.letdefs; + $$->letdefv = std::move(*$2); + $2.delete_(); $$->spellguard = $4; } @@ -679,16 +695,13 @@ defs : semicolons { - $$.letdefs_nr = 0; - CREATE($$.letdefs, letdef_t, 1); + $$.new_(); } | defs def semicolons { $$ = $1; - $$.letdefs_nr++; - RECREATE($$.letdefs, letdef_t, $$.letdefs_nr); - $$.letdefs[$1.letdefs_nr] = $2; + $$->push_back($2); } ; @@ -698,16 +711,16 @@ def : ID '=' expr { - if (find_constant($1)) + if (find_constant($1.str())) { - fail(@1.first_line, @1.first_column, "Attempt to re-define constant `%s' as LET-bound variable.\n", $1); - free($1); + fail(@1.first_line, @1.first_column, "Attempt to re-define constant `%s' as LET-bound variable.\n", $1.c_str()); } else { $$.id = intern_id($1); $$.expr = $3; } + $1.delete_(); } ; @@ -722,7 +735,7 @@ spellbody_list | spellbody '|' spellbody_list { - spellguard_t *sg = new_spellguard(SPELLGUARD::CHOICE); + dumb_ptr<spellguard_t> sg = new_spellguard(SPELLGUARD::CHOICE); sg->next = $1; sg->s.s_alt = $3; $$ = sg; @@ -745,7 +758,7 @@ spellbody | EFFECT_ effect_list maybe_trigger maybe_end { - spellguard_t *sg = new_spellguard(SPELLGUARD::EFFECT); + dumb_ptr<spellguard_t> sg = new_spellguard(SPELLGUARD::EFFECT); sg->s.s_effect.effect = $2; sg->s.s_effect.at_trigger = $3; sg->s.s_effect.at_end = $4; @@ -794,7 +807,7 @@ spellguard | spellguard OR spellguard { - spellguard_t *sg = new_spellguard(SPELLGUARD::CHOICE); + dumb_ptr<spellguard_t> sg = new_spellguard(SPELLGUARD::CHOICE); sg->next = $1; sg->s.s_alt = $3; $$ = sg; @@ -906,15 +919,15 @@ item_name : STRING { - struct item_data *item = itemdb_searchname($1); + struct item_data *item = itemdb_searchname($1.c_str()); if (!item) { - fail(@1.first_line, @1.first_column, "Unknown item `%s'\n", $1); + fail(@1.first_line, @1.first_column, "Unknown item `%s'\n", $1.c_str()); $$ = 0; } else $$ = item->nameid; - free($1); + $1.delete_(); } | INT @@ -989,10 +1002,9 @@ effect | ID '=' expr ';' { - if (find_constant($1)) + if (find_constant($1.str())) { - fail(@1.first_line, @1.first_column, "Attempt to re-define constant `%s' in assignment.", $1); - free($1); + fail(@1.first_line, @1.first_column, "Attempt to re-define constant `%s' in assignment.", $1.c_str()); } else { @@ -1000,12 +1012,14 @@ effect $$->e.e_assign.id = intern_id($1); $$->e.e_assign.expr = $3; } + $1.delete_(); } | FOREACH selection ID IN expr DO effect { $$ = new_effect(EFFECT::FOREACH); $$->e.e_foreach.id = intern_id($3); + $3.delete_(); $$->e.e_foreach.area = $5; $$->e.e_foreach.body = $7; $$->e.e_foreach.filter = $2; @@ -1015,6 +1029,7 @@ effect { $$ = new_effect(EFFECT::FOR); $$->e.e_for.id = intern_id($2); + $2.delete_(); $$->e.e_for.start = $4; $$->e.e_for.stop = $6; $$->e.e_for.body = $8; @@ -1044,23 +1059,23 @@ effect | ID '(' arg_list ')' ';' { - $$ = op_effect($1, $3.args_nr, $3.args, @1.first_line, @1.first_column); - free($1); + $$ = op_effect($1.str(), *$3.argvp, @1.first_line, @1.first_column); + $1.delete_(); } | SCRIPT_DATA { $$ = new_effect(EFFECT::SCRIPT); - $$->e.e_script = parse_script($1, @1.first_line); - free($1); + $$->e.e_script = dumb_ptr<const ScriptBuffer>(parse_script($1.c_str(), @1.first_line).release()); + $1.delete_(); if ($$->e.e_script == NULL) fail(@1.first_line, @1.first_column, "Failed to compile script\n"); } | CALL ID '(' arg_list ')' ';' { - $$ = call_proc($2, $4.args_nr, $4.args, @1.first_line, @1.first_column); - free($2); + $$ = call_proc($2, $4.argvp, @1.first_line, @1.first_column); + $2.delete_(); } ; @@ -1083,84 +1098,63 @@ effect_list %% -/* We do incremental realloc here to store our results. Since this happens only once - * during startup for a relatively manageable set of configs, it should be fine. */ - -static -int intern_id(const char *id_name) +size_t intern_id(const_string id_name_) { - int i; - for (i = 0; i < magic_conf.vars_nr; i++) - if (!strcmp(id_name, magic_conf.var_name[i])) - { - free((char*)id_name); + std::string id_name(id_name_.begin(), id_name_.end()); + size_t i; + for (i = 0; i < magic_conf.varv.size(); i++) + if (id_name == magic_conf.varv[i].name) return i; - } + // i = magic_conf.varv.size(); /* Must add new */ - i = magic_conf.vars_nr++; - RECREATE(magic_conf.var_name, const char *, magic_conf.vars_nr); - magic_conf.var_name[i] = id_name; - RECREATE(magic_conf.vars, val_t, magic_conf.vars_nr); - magic_conf.vars[i].ty = TYPE::UNDEF; + magic_conf_t::mcvar new_var {}; + new_var.name = id_name; + new_var.val.ty = TYPE::UNDEF; + magic_conf.varv.push_back(new_var); return i; } -static -void add_spell(spell_t *spell, int line_nr) +void add_spell(dumb_ptr<spell_t> spell, int line_nr) { - int index = magic_conf.spells_nr; - int i; - - for (i = 0; i < index; i++) + auto pair1 = magic_conf.spells_by_name.insert({spell->name, spell}); + if (!pair1.second) { - if (!strcmp(magic_conf.spells[i]->name, spell->name)) - { - fail(line_nr, 0, "Attempt to redefine spell `%s'\n", spell->name); - return; - } - if (!strcmp(magic_conf.spells[i]->invocation, spell->invocation)) - { - fail(line_nr, 0, "Attempt to redefine spell invocation `%s' between spells `%s' and `%s'\n", - spell->invocation, magic_conf.spells[i]->name, spell->name); - return; - } + fail(line_nr, 0, "Attempt to redefine spell `%s'\n", spell->name.c_str()); + return; } - magic_conf.spells_nr++; - RECREATE(magic_conf.spells, spell_t *, magic_conf.spells_nr); - magic_conf.spells[index] = spell; + auto pair2 = magic_conf.spells_by_invocation.insert({spell->invocation, spell}); + if (!pair2.second) + { + fail(line_nr, 0, "Attempt to redefine spell invocation `%s' between spells `%s' and `%s'\n", + spell->invocation.c_str(), pair1.first->second->name.c_str(), spell->name.c_str()); + magic_conf.spells_by_name.erase(pair1.first); + return; + } } -static -void add_teleport_anchor(teleport_anchor_t *anchor, int line_nr) +void add_teleport_anchor(dumb_ptr<teleport_anchor_t> anchor, int line_nr) { - int index = magic_conf.anchors_nr; - int i; - - for (i = 0; i < index; i++) + auto pair1 = magic_conf.anchors_by_name.insert({anchor->name, anchor}); + if (!pair1.second) { - if (!strcmp(magic_conf.anchors[i]->name, anchor->name)) - { - fail(line_nr, 0, "Attempt to redefine teleport anchor `%s'\n", anchor->name); - return; - } - if (!strcmp(magic_conf.anchors[i]->invocation, anchor->invocation)) - { - fail(line_nr, 0, "Attempt to redefine anchor invocation `%s' between anchors `%s' and `%s'\n", - anchor->invocation, magic_conf.anchors[i]->name, anchor->name); - return; - } + fail(line_nr, 0, "Attempt to redefine teleport anchor `%s'\n", anchor->name.c_str()); + return; } - magic_conf.anchors_nr++; - RECREATE(magic_conf.anchors, teleport_anchor_t *, magic_conf.anchors_nr); - magic_conf.anchors[index] = anchor; + auto pair2 = magic_conf.anchors_by_invocation.insert({anchor->name, anchor}); + if (!pair2.second) + { + fail(line_nr, 0, "Attempt to redefine anchor invocation `%s' between anchors `%s' and `%s'\n", + anchor->invocation.c_str(), pair1.first->second->name.c_str(), anchor->name.c_str()); + magic_conf.anchors_by_name.erase(pair1.first); + return; + } } -static __attribute__((format(printf, 3, 4))) void fail(int line, int column, const char *fmt, ...) { va_list ap; @@ -1170,43 +1164,41 @@ void fail(int line, int column, const char *fmt, ...) failed_flag = 1; } -static -expr_t *dot_expr(expr_t *expr, int id) +dumb_ptr<expr_t> dot_expr(dumb_ptr<expr_t> expr, int id) { - expr_t *retval = magic_new_expr(EXPR::SPELLFIELD); + dumb_ptr<expr_t> retval = magic_new_expr(EXPR::SPELLFIELD); retval->e.e_field.id = id; retval->e.e_field.expr = expr; return retval; } -static -expr_t *fun_expr(const char *name, int args_nr, expr_t **args, int line, int column) +dumb_ptr<expr_t> fun_expr(const std::string& name, const_array<dumb_ptr<expr_t>> argv, int line, int column) { int id; - expr_t *expr; + dumb_ptr<expr_t> expr; fun_t *fun = magic_get_fun(name, &id); if (!fun) - fail(line, column, "Unknown function `%s'\n", name); - else if (strlen(fun->signature) != args_nr) + fail(line, column, "Unknown function `%s'\n", name.c_str()); + else if (strlen(fun->signature) != argv.size()) { - fail(line, column, "Incorrect number of arguments to function `%s': Expected %zu, found %d\n", name, strlen(fun->signature), args_nr); + fail(line, column, "Incorrect number of arguments to function `%s': Expected %zu, found %zu\n", + name.c_str(), strlen(fun->signature), argv.size()); fun = NULL; } if (fun) { - int i; - expr = magic_new_expr(EXPR::FUNAPP); expr->e.e_funapp.line_nr = line; expr->e.e_funapp.column = column; expr->e.e_funapp.id = id; - expr->e.e_funapp.args_nr = args_nr; - for (i = 0; i < args_nr; i++) - expr->e.e_funapp.args[i] = args[i]; + assert (argv.size() < MAX_ARGS); + expr->e.e_funapp.args_nr = argv.size(); + + std::copy(argv.begin(), argv.end(), expr->e.e_funapp.args); } else { @@ -1218,29 +1210,26 @@ expr_t *fun_expr(const char *name, int args_nr, expr_t **args, int line, int col return expr; } -static -spell_t *new_spell(spellguard_t *guard) +dumb_ptr<spell_t> new_spell(dumb_ptr<spellguard_t> guard) { static int spell_counter = 0; - spell_t *retval = (spell_t*)calloc(1, sizeof(spell_t)); - retval->index = ++spell_counter; + auto retval = dumb_ptr<spell_t>::make(); + retval->index_ = ++spell_counter; retval->spellguard = guard; return retval; } -static -spellguard_t *new_spellguard(SPELLGUARD ty) +dumb_ptr<spellguard_t> new_spellguard(SPELLGUARD ty) { - spellguard_t *retval = (spellguard_t *)calloc(1, sizeof(spellguard_t)); + dumb_ptr<spellguard_t> retval = dumb_ptr<spellguard_t>::make(); retval->ty = ty; return retval; } -static -spellguard_t *spellguard_implication(spellguard_t *a, spellguard_t *b) +dumb_ptr<spellguard_t> spellguard_implication(dumb_ptr<spellguard_t> a, dumb_ptr<spellguard_t> b) { - spellguard_t *retval = a; + dumb_ptr<spellguard_t> retval = a; if (a == b) { @@ -1269,18 +1258,16 @@ spellguard_t *spellguard_implication(spellguard_t *a, spellguard_t *b) return retval; } -static -effect_t *new_effect(EFFECT ty) +dumb_ptr<effect_t> new_effect(EFFECT ty) { - effect_t *effect = (effect_t *) calloc(1, sizeof(effect_t)); + auto effect = dumb_ptr<effect_t>::make(); effect->ty = ty; return effect; } -static -effect_t *set_effect_continuation(effect_t *src, effect_t *continuation) +dumb_ptr<effect_t> set_effect_continuation(dumb_ptr<effect_t> src, dumb_ptr<effect_t> continuation) { - effect_t *retval = src; + dumb_ptr<effect_t> retval = src; /* This function is completely analogous to `spellguard_implication' above; read the control flow implications above first before pondering it. */ if (src == continuation) @@ -1301,33 +1288,31 @@ effect_t *set_effect_continuation(effect_t *src, effect_t *continuation) return retval; } -static -effect_t *op_effect(char *name, int args_nr, expr_t **args, int line, int column) +dumb_ptr<effect_t> op_effect(const std::string& name, const_array<dumb_ptr<expr_t>> argv, int line, int column) { int id; - effect_t *effect; + dumb_ptr<effect_t> effect; op_t *op = magic_get_op(name, &id); if (!op) - fail(line, column, "Unknown operation `%s'\n", name); - else if (strlen(op->signature) != args_nr) + fail(line, column, "Unknown operation `%s'\n", name.c_str()); + else if (strlen(op->signature) != argv.size()) { - fail(line, column, "Incorrect number of arguments to operation `%s': Expected %zu, found %d\n", name, strlen(op->signature), args_nr); + fail(line, column, "Incorrect number of arguments to operation `%s': Expected %zu, found %zu\n", + name.c_str(), strlen(op->signature), argv.size()); op = NULL; } if (op) { - int i; - effect = new_effect(EFFECT::OP); effect->e.e_op.line_nr = line; effect->e.e_op.column = column; effect->e.e_op.id = id; - effect->e.e_op.args_nr = args_nr; + assert (argv.size() < MAX_ARGS); + effect->e.e_op.args_nr = argv.size(); - for (i = 0; i < args_nr; i++) - effect->e.e_op.args[i] = args[i]; + std::copy(argv.begin(), argv.end(), effect->e.e_op.args); } else /* failure */ effect = new_effect(EFFECT::SKIP); @@ -1336,99 +1321,55 @@ effect_t *op_effect(char *name, int args_nr, expr_t **args, int line, int column } -proc_t *procs = NULL; -int procs_nr = 0; +std::map<std::string, proc_t> procs; -// I think this is a memory leak, or undefined behavior -static -void install_proc(proc_t *proc) +// I think this was a memory leak (or undefined behavior) +void install_proc(dumb_ptr<proc_t> proc) { - if (!procs) - { - procs = proc; - procs_nr = 1; - } - else - { - RECREATE(procs, proc_t, 1 + procs_nr); - procs[procs_nr++] = *proc; - } + procs.insert({proc->name, std::move(*proc)}); } -static -effect_t *call_proc(char *name, int args_nr, expr_t **args, int line_nr, int column) +dumb_ptr<effect_t> call_proc(const_string name_, dumb_ptr<std::vector<dumb_ptr<expr_t>>> argvp, int line_nr, int column) { - proc_t *p = NULL; - int i; - effect_t *retval; - - for (i = 0; i < procs_nr; i++) - if (!strcmp(procs[i].name, name)) - { - p = &procs[i]; - break; - } - - if (!p) + std::string name(name_.begin(), name_.end()); + auto pi = procs.find(name); + if (pi == procs.end()) { - fail(line_nr, column, "Unknown procedure `%s'\n", name); + fail(line_nr, column, "Unknown procedure `%s'\n", name.c_str()); return new_effect(EFFECT::SKIP); } - if (p->args_nr != args_nr) + proc_t *p = &pi->second; + + if (p->argv.size() != argvp->size()) { - fail(line_nr, column, "Procedure %s/%d invoked with %d parameters\n", name, p->args_nr, args_nr); + fail(line_nr, column, "Procedure %s/%zu invoked with %zu parameters\n", + name.c_str(), p->argv.size(), argvp->size()); return new_effect(EFFECT::SKIP); } - retval = new_effect(EFFECT::CALL); + dumb_ptr<effect_t> retval = new_effect(EFFECT::CALL); retval->e.e_call.body = p->body; - retval->e.e_call.args_nr = args_nr; - retval->e.e_call.formals = p->args; - retval->e.e_call.actuals = args; + retval->e.e_call.formalv = &p->argv; + retval->e.e_call.actualvp = argvp; return retval; } -struct const_def_rec -{ - char *name; - val_t val; -} *const_defs = NULL; - -int const_defs_nr = 0; +std::map<std::string, val_t> const_defm; -static -void bind_constant(char *name, val_t *val, int line_nr) +void bind_constant(const std::string& name, val_t *val, int line_nr) { - if (find_constant(name)) + if (!const_defm.insert({name, *val}).second) { - fail(line_nr, 0, "Redefinition of constant `%s'\n", name); - return; + fail(line_nr, 0, "Redefinition of constant `%s'\n", name.c_str()); } - - if (!const_defs) - const_defs = (struct const_def_rec *)malloc(sizeof(struct const_def_rec)); - else - const_defs = (struct const_def_rec *)realloc(const_defs, - (const_defs_nr + 1) * sizeof(struct const_def_rec)); - - const_defs[const_defs_nr].name = name; - const_defs[const_defs_nr].val = *val; - ++const_defs_nr; } -static -val_t *find_constant(char *name) +val_t *find_constant(const std::string& name) { - int i; - for (i = 0; i < const_defs_nr; i++) - { - if (!strcmp(const_defs[i].name, name)) - { - free(name); - return &const_defs[i].val; - } - } + auto it = const_defm.find(name); + if (it != const_defm.end()) + return &it->second; return NULL; } @@ -1455,20 +1396,6 @@ int magic_init(const char *conffile) { error_flag = 0; - magic_conf.vars_nr = 0; - // can these be left NULL ? I'm afraid to change anything. - magic_conf.var_name = (const char **)malloc(1); - magic_conf.vars = (val_t *)malloc(1); - - magic_conf.obscure_chance = 95; - magic_conf.min_casttime = 100; - - magic_conf.spells_nr = 0; - CREATE(magic_conf.spells, spell_t *, 1); - - magic_conf.anchors_nr = 0; - CREATE(magic_conf.anchors, teleport_anchor_t *, 1); - INTERN_ASSERT("min_casttime", VAR_MIN_CASTTIME); INTERN_ASSERT("obscure_chance", VAR_OBSCURE_CHANCE); INTERN_ASSERT("caster", VAR_CASTER); @@ -1487,23 +1414,14 @@ int magic_init(const char *conffile) } magic_frontend_parse(); - if (magic_conf.vars[VAR_MIN_CASTTIME].ty == TYPE::INT) - magic_conf.min_casttime = magic_conf.vars[VAR_MIN_CASTTIME].v.v_int; - - if (magic_conf.vars[VAR_OBSCURE_CHANCE].ty == TYPE::INT) - magic_conf.obscure_chance = magic_conf.vars[VAR_OBSCURE_CHANCE].v.v_int; + PRINTF("[magic-conf] Magic initialised. %zu spells, %zu teleport anchors.\n", + magic_conf.spells_by_name.size(), magic_conf.anchors_by_name.size()); - PRINTF("[magic-conf] Magic initialised; obscure at %d%%. %d spells, %d teleport anchors.\n", - magic_conf.obscure_chance, magic_conf.spells_nr, magic_conf.anchors_nr); - - if (procs) - free(procs); return error_flag; } extern int magic_frontend_lineno; -static void magic_frontend_error(const char *msg) { FPRINTF(stderr, "[magic-conf] Parse error: %s at line %d\n", msg, magic_frontend_lineno); |