summaryrefslogtreecommitdiff
path: root/src/map/magic-interpreter-parser.ypp
diff options
context:
space:
mode:
authorBen Longbons <b.r.longbons@gmail.com>2013-06-11 21:55:13 -0700
committerBen Longbons <b.r.longbons@gmail.com>2013-06-11 23:27:33 -0700
commit8b5370313dcc00a45ea5c3e8b4c497bc00fd8e13 (patch)
tree15e8a4841af992e17794f26fc7991ed40c35bd51 /src/map/magic-interpreter-parser.ypp
parent8c6072df499ef9068346fbe8313b63dbba1e4e82 (diff)
downloadtmwa-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.ypp506
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);