summaryrefslogtreecommitdiff
path: root/src/map/magic-interpreter-parser.y
diff options
context:
space:
mode:
authorBen Longbons <b.r.longbons@gmail.com>2012-08-30 16:16:25 -0700
committerBen Longbons <b.r.longbons@gmail.com>2012-08-30 17:03:31 -0700
commit41974ae5265fbc23a06f276f9e008d5dad020e0b (patch)
tree9d595215172e87e2d83b74f7bf3430b3040e780e /src/map/magic-interpreter-parser.y
parent21742909143df9159b2401c3e2a39cc0b2bad620 (diff)
downloadtmwa-41974ae5265fbc23a06f276f9e008d5dad020e0b.tar.gz
tmwa-41974ae5265fbc23a06f276f9e008d5dad020e0b.tar.bz2
tmwa-41974ae5265fbc23a06f276f9e008d5dad020e0b.tar.xz
tmwa-41974ae5265fbc23a06f276f9e008d5dad020e0b.zip
Rename files for C++ conversion. Does not compile.
After updating, you can remove these files, as shown in 'git status': Untracked files: (use "git add <file>..." to include in what will be committed) src/map/magic-interpreter-lexer.c src/map/magic-interpreter-parser.c src/map/magic-interpreter-parser.h
Diffstat (limited to 'src/map/magic-interpreter-parser.y')
-rw-r--r--src/map/magic-interpreter-parser.y1089
1 files changed, 0 insertions, 1089 deletions
diff --git a/src/map/magic-interpreter-parser.y b/src/map/magic-interpreter-parser.y
deleted file mode 100644
index 9df0f3e..0000000
--- a/src/map/magic-interpreter-parser.y
+++ /dev/null
@@ -1,1089 +0,0 @@
-%{
-#include "magic-interpreter.h"
-#include "magic-expr.h"
-#include <stdarg.h>
-
-magic_conf_t magic_conf;
-
-static int
-intern_id(const char *id_name);
-
-
-static expr_t *
-fun_expr(const char *name, int args_nr, expr_t **args, int line, int column);
-
-static expr_t *
-dot_expr(expr_t *lhs, int id);
-
-#define BIN_EXPR(x, name, arg1, arg2, line, column) { expr_t *e[2]; e[0] = arg1; e[1] = arg2; x = fun_expr(name, 2, e, line, column); }
-
-static int failed_flag = 0;
-
-static void
-magic_frontend_error(const char *msg);
-
-static void
-fail(int line, int column, const char *fmt, ...);
-
-static spell_t *
-new_spell(spellguard_t *guard);
-
-static spellguard_t *
-spellguard_implication(spellguard_t *a, spellguard_t *b);
-
-static spellguard_t *
-new_spellguard(int ty);
-
-static effect_t *
-new_effect(int ty);
-
-static effect_t *
-set_effect_continuation(effect_t *src, effect_t *continuation);
-
-static void
-add_spell(spell_t *spell, int line_nr);
-
-static void
-add_teleport_anchor(teleport_anchor_t *anchor, int line_nr);
-
-static effect_t *
-op_effect(char *name, int args_nr, expr_t **args, int line, int column);
-
-int
-magic_frontend_lex(void);
-
-static void
-install_proc(proc_t *proc);
-
-static effect_t *
-call_proc(char *name, int args_nr, expr_t **args, int line_nr, int column);
-
-static void
-bind_constant(char *name, val_t *val, int line_nr);
-
-static val_t *
-find_constant(char *name);
-
-
-%}
-
-%name-prefix="magic_frontend_"
-
-%locations
-
-%union {
- int i;
- char *s;
- int op;
- magic_conf_t *magic_conf;
- val_t value;
- 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;
- struct { int id, ty; } spellarg_def;
- letdef_t vardef;
- spellguard_t *spellguard;
- component_t *components;
- struct {int id, count; } component;
- effect_t *effect;
- proc_t *proc;
-};
-
-%expect 7
-
-%token <i> INT
-%token <s> STRING
-%token <s> ID
-%token <i> DIR
-
-%token '='
-%token '<'
-%token '>'
-%token '+'
-%token '-'
-%token '*'
-%token '/'
-%token '%'
-%token '@'
-%token ','
-%token '.'
-%token ':'
-%token ';'
-%token '|'
-%token '['
-%token ']'
-%token '&'
-%token '^'
-
-%token CONST
-%token PROCEDURE
-%token CALL
-%token SILENT
-%token LOCAL
-%token NONMAGIC
-%token SHL
-%token SHR
-%token EQ
-%token NEQ
-%token GTE
-%token LTE
-%token ANDAND
-%token OROR
-%token <s> SCRIPT_DATA
-%token TO
-%token TOWARDS
-%token TELEPORT_ANCHOR
-%token SPELL
-%token LET
-%token IN
-%token END
-%token DARROW
-%token STRING_TY
-%token REQUIRE
-%token CATALYSTS
-%token COMPONENTS
-%token MANA
-%token CASTTIME
-%token SKIP
-%token ABORT
-%token BREAK
-%token EFFECT
-%token ATEND
-%token ATTRIGGER
-%token PC_F
-%token NPC_F
-%token MOB_F
-%token ENTITY_F
-%token TARGET_F
-%token IF
-%token THEN
-%token ELSE
-%token FOREACH
-%token FOR
-%token DO
-%token SLEEP
-
-%type <value> value
-%type <location> location
-%type <area> area
-%type <arg_list> arg_list
-%type <arg_list> arg_list_ne
-%type <letdefs> defs
-%type <spell> spelldef
-%type <spellarg_def> argopt
-%type <vardef> def
-%type <spellguard> spellbody_list
-%type <spellguard> spellbody
-%type <spellguard> spellguard
-%type <spellguard> spellguard_list
-%type <spellguard> prereq
-%type <component> item
-%type <components> items
-%type <components> item_list
-%type <i> item_name
-%type <i> selection;
-%type <effect> effect
-%type <effect> effect_list
-%type <effect> maybe_trigger
-%type <effect> maybe_end
-%type <i> spell_flags;
-
-%type <expr> expr
-%type <i> arg_ty
-%type <proc> proc_formals_list
-%type <proc> proc_formals_list_ne
-
-%left OROR
-%left ANDAND
-%left '<' '>' GTE LTE NEQ EQ
-%left '+' '-'
-%left '*' '/' '%'
-%left SHL SHR '&' '^' '|'
-%right '='
-%left OR
-%left DARROW
-%left '.'
-
-%%
-
-spellconf : /* empty */
- {}
- | spellconf_option semicolons spellconf
- {}
- ;
-
-
-semicolons : /* empty */
- {}
- | semicolons ';'
- {}
- ;
-
-
-proc_formals_list : /* empty */
- { CREATE ($$, proc_t, 1); }
- | proc_formals_list_ne
- { $$ = $1; }
- ;
-
-proc_formals_list_ne : ID
- { CREATE ($$, proc_t, 1);
- $$->args_nr = 1;
- $$->args = (int*)malloc(sizeof(int));
- $$->args[0] = intern_id($1);
- }
- | proc_formals_list_ne ',' ID
- { $$ = $1;
- $$->args = (int*)realloc($$->args, sizeof(int) * (1 + $$->args_nr));
- $$->args[$$->args_nr++] = intern_id($3);
- }
- ;
-
-spellconf_option : ID '=' expr
- {
- int var_id;
- if (find_constant($1)) {
- fail(@1.first_line, 0, "Attempt to redefine constant `%s' as global\n", $1);
- free($1);
- } else {
- var_id = intern_id($1);
- magic_eval(&magic_default_env, &magic_conf.vars[var_id], $3);
- }
- }
- | CONST ID '=' expr
- {
- val_t var;
- magic_eval(&magic_default_env, &var, $4);
- bind_constant($2, &var, @1.first_line);
- }
- | 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;
-
- if (!failed_flag)
- add_teleport_anchor(anchor, @1.first_line);
- else
- free(anchor);
- 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;
- }
- | spell_flags SPELL ID argopt ':' expr '=' spelldef
- { spell_t *spell = $8;
- spell->name = $3;
- spell->invocation = magic_eval_str(&magic_default_env, $6);
- spell->arg = $4.id;
- spell->spellarg_ty = $4.ty;
- spell->flags = $1;
- if (!failed_flag)
- add_spell(spell, @1.first_line);
- failed_flag = 0;
- }
-
-spell_flags : /* empty */
- { $$ = 0; }
- | LOCAL spell_flags
- { if ($2 & SPELL_FLAG_LOCAL)
- fail(@1.first_line, @1.first_column, "`LOCAL' specified more than once");
- $$ = $2 | SPELL_FLAG_LOCAL;
- }
- | NONMAGIC spell_flags
- { if ($2 & SPELL_FLAG_NONMAGIC)
- fail(@1.first_line, @1.first_column, "`NONMAGIC' specified more than once");
- $$ = $2 | SPELL_FLAG_NONMAGIC;
- }
- | SILENT spell_flags
- { if ($2 & SPELL_FLAG_SILENT)
- fail(@1.first_line, @1.first_column, "`SILENT' specified more than once");
- $$ = $2 | SPELL_FLAG_SILENT;
- }
-
-
-argopt : /* empty */
- { $$.ty = SPELLARG_NONE; }
- | '(' ID ':' arg_ty ')'
- { $$.id = intern_id($2);
- $$.ty = $4; }
- ;
-
-
-arg_ty : PC_F
- { $$ = SPELLARG_PC; }
- | STRING_TY
- { $$ = SPELLARG_STRING; }
- ;
-
-
-value : DIR
- { $$.ty = TY_DIR;
- $$.v.v_int = $1; }
- | INT
- { $$.ty = TY_INT;
- $$.v.v_int = $1; }
- | STRING
- { $$.ty = TY_STRING;
- $$.v.v_string = $1; }
- ;
-
-
-expr : value
- { $$ = magic_new_expr(EXPR_VAL);
- $$->e.e_val = $1; }
- | ID
- {
- val_t *val;
- if ((val = find_constant($1))) {
- $$ = magic_new_expr(EXPR_VAL);
- $$->e.e_val = *val;
- } else {
- $$ = magic_new_expr(EXPR_ID);
- $$->e.e_id = intern_id($1);
- }
- }
- | area
- { $$ = magic_new_expr(EXPR_AREA);
- $$->e.e_area = $1; }
- | expr '+' expr
- { BIN_EXPR($$, "+", $1, $3, @1.first_line, @1.first_column); }
- | expr '-' expr
- { BIN_EXPR($$, "-", $1, $3, @1.first_line, @1.first_column); }
- | expr '*' expr
- { BIN_EXPR($$, "*", $1, $3, @1.first_line, @1.first_column); }
- | expr '%' expr
- { BIN_EXPR($$, "%", $1, $3, @1.first_line, @1.first_column); }
- | expr '/' expr
- { BIN_EXPR($$, "/", $1, $3, @1.first_line, @1.first_column); }
- | expr '<' expr
- { BIN_EXPR($$, ">", $3, $1, @1.first_line, @1.first_column); }
- | expr '>' expr
- { BIN_EXPR($$, ">", $1, $3, @1.first_line, @1.first_column); }
- | expr '&' expr
- { BIN_EXPR($$, "&", $1, $3, @1.first_line, @1.first_column); }
- | expr '^' expr
- { BIN_EXPR($$, "^", $1, $3, @1.first_line, @1.first_column); }
- | expr '|' expr
- { BIN_EXPR($$, "|", $1, $3, @1.first_line, @1.first_column); }
- | expr SHL expr
- { BIN_EXPR($$, "<<", $1, $3, @1.first_line, @1.first_column); }
- | expr SHR expr
- { BIN_EXPR($$, ">>", $1, $3, @1.first_line, @1.first_column); }
- | expr LTE expr
- { BIN_EXPR($$, ">=", $3, $1, @1.first_line, @1.first_column); }
- | expr GTE expr
- { BIN_EXPR($$, ">=", $1, $3, @1.first_line, @1.first_column); }
- | expr ANDAND expr
- { BIN_EXPR($$, "&&", $1, $3, @1.first_line, @1.first_column); }
- | expr OROR expr
- { BIN_EXPR($$, "||", $1, $3, @1.first_line, @1.first_column); }
- | expr EQ expr
- { BIN_EXPR($$, "=", $1, $3, @1.first_line, @1.first_column); }
- | expr '=' expr
- { BIN_EXPR($$, "=", $1, $3, @1.first_line, @1.first_column); }
- | expr NEQ expr
- { BIN_EXPR($$, "=", $1, $3, @1.first_line, @1.first_column);
- $$ = fun_expr("not", 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); }
- | '(' expr ')'
- { $$ = $2; }
- | expr '.' ID
- { $$ = dot_expr($1, intern_id($3)); }
- ;
-
-arg_list : /* empty */
- { $$.args_nr = 0; }
- | arg_list_ne
- { $$ = $1; }
- ;
-
-
-arg_list_ne : expr
- { CREATE($$.args, expr_t *, 1);
- $$.args_nr = 1;
- $$.args[0] = $1;
- }
- | arg_list_ne ',' expr
- { RECREATE($$.args, expr_t *, 1 + $$.args_nr);
- $$.args[$$.args_nr++] = $3;
- }
- ;
-
-
-location : '@' '(' expr ',' expr ',' expr ')'
- { $$.m = $3; $$.x = $5; $$.y = $7; }
- ;
-
-area : location
- { $$.ty = AREA_LOCATION;
- $$.a.a_loc = $1;
- }
- | location '@' '+' '(' expr ',' expr ')'
- { $$.ty = AREA_RECT;
- $$.a.a_rect.loc = $1;
- $$.a.a_rect.width = $5;
- $$.a.a_rect.height = $7;
- }
- | location TOWARDS expr ':' '(' expr ',' expr ')'
- { $$.ty = AREA_BAR;
- $$.a.a_bar.loc = $1;
- $$.a.a_bar.width = $6;
- $$.a.a_bar.depth = $8;
- $$.a.a_bar.dir = $3;
- }
- ;
-
-
-spelldef : spellbody_list
- { $$ = new_spell($1); }
- | LET defs IN spellbody_list
- { $$ = new_spell($4);
- $$->letdefs_nr = $2.letdefs_nr;
- $$->letdefs = $2.letdefs;
- $$->spellguard = $4;
- }
- ;
-
-
-defs : semicolons
- { $$.letdefs_nr = 0;
- CREATE($$.letdefs, letdef_t, 1);
- }
- | defs def semicolons
- { $$ = $1;
- $$.letdefs_nr++;
- RECREATE ($$.letdefs, letdef_t, $$.letdefs_nr);
- $$.letdefs[$1.letdefs_nr] = $2;
- }
- ;
-
-
-def : ID '=' expr
- {
- if (find_constant($1)) {
- fail(@1.first_line, @1.first_column, "Attempt to re-define constant `%s' as LET-bound variable.\n", $1);
- free($1);
- } else {
- $$.id = intern_id($1);
- $$.expr = $3;
- }
- }
- ;
-
-
-spellbody_list : spellbody
- { $$ = $1; }
- | spellbody '|' spellbody_list
- { spellguard_t *sg = new_spellguard(SPELLGUARD_CHOICE);
- sg->next = $1;
- sg->s.s_alt = $3;
- $$ = sg;
- }
- ;
-
-
-spellbody : spellguard DARROW spellbody
- { $$ = spellguard_implication($1, $3); }
- | '(' spellbody_list ')'
- { $$ = $2; }
- | EFFECT effect_list maybe_trigger maybe_end
- { 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;
- $$ = sg;
- }
- ;
-
-
-maybe_trigger : /* empty */
- { $$ = NULL; }
- | ATTRIGGER effect_list
- { $$ = $2; }
- ;
-
-
-maybe_end : /* empty */
- { $$ = NULL; }
- | ATEND effect_list
- { $$ = $2; }
- ;
-
-
-spellguard : prereq
- { $$ = $1; }
- | spellguard OR spellguard
- { spellguard_t *sg = new_spellguard(SPELLGUARD_CHOICE);
- sg->next = $1;
- sg->s.s_alt = $3;
- $$ = sg;
- }
- | '(' spellguard_list ')'
- { $$ = $2; }
- ;
-
-
-spellguard_list : spellguard
- { $$ = $1; }
- | spellguard ',' spellguard_list
- { $$ = spellguard_implication ($1, $3); }
- ;
-
-
-prereq : REQUIRE expr
- { $$ = new_spellguard(SPELLGUARD_CONDITION);
- $$->s.s_condition = $2;
- }
- | CATALYSTS items
- { $$ = new_spellguard(SPELLGUARD_CATALYSTS);
- $$->s.s_catalysts = $2;
- }
- | COMPONENTS items
- { $$ = new_spellguard(SPELLGUARD_COMPONENTS);
- $$->s.s_components = $2;
- }
- | MANA expr
- { $$ = new_spellguard(SPELLGUARD_MANA);
- $$->s.s_mana = $2;
- }
- | CASTTIME expr
- { $$ = new_spellguard(SPELLGUARD_CASTTIME);
- $$->s.s_casttime = $2;
- }
- ;
-
-
-items : '[' item_list ']'
- { $$ = $2; }
- ;
-
-
-item_list : item
- { $$ = NULL;
- magic_add_component(&$$, $1.id, $1.count);
- }
- | item_list ',' item
- { $$ = $1;
- magic_add_component(&$$, $3.id, $3.count);
- }
- ;
-
-
-item : INT '*' item_name
- { $$.id = $3; $$.count = $1; }
- | item_name
- { $$.id = $1; $$.count = 1; }
- ;
-
-
-item_name : STRING
- { struct item_data *item = itemdb_searchname($1);
- if (!item) {
- fail (@1.first_line, @1.first_column, "Unknown item `%s'\n", $1);
- $$ = 0;
- } else
- $$ = item->nameid;
- free ($1);
- }
- | INT
- { $$ = $1; }
- ;
-
-
-selection : PC_F
- { $$ = FOREACH_FILTER_PC; }
- | MOB_F
- { $$ = FOREACH_FILTER_MOB; }
- | ENTITY_F
- { $$ = FOREACH_FILTER_ENTITY; }
- | SPELL
- { $$ = FOREACH_FILTER_SPELL; }
- | TARGET_F
- { $$ = FOREACH_FILTER_TARGET; }
- | NPC_F
- { $$ = FOREACH_FILTER_NPC; }
- ;
-
-
-effect : '(' effect_list ')'
- { $$ = $2; }
- | SKIP ';'
- { $$ = new_effect(EFFECT_SKIP); }
- | ABORT ';'
- { $$ = new_effect(EFFECT_ABORT); }
- | END ';'
- { $$ = new_effect(EFFECT_END); }
- | BREAK ';'
- { $$ = new_effect(EFFECT_BREAK); }
- | ID '=' expr ';'
- {
- if (find_constant($1)) {
- fail(@1.first_line, @1.first_column, "Attempt to re-define constant `%s' in assignment.", $1);
- free($1);
- } else {
- $$ = new_effect(EFFECT_ASSIGN);
- $$->e.e_assign.id = intern_id($1);
- $$->e.e_assign.expr = $3;
- }
- }
- | FOREACH selection ID IN expr DO effect
- { $$ = new_effect(EFFECT_FOREACH);
- $$->e.e_foreach.id = intern_id($3);
- $$->e.e_foreach.area = $5;
- $$->e.e_foreach.body = $7;
- $$->e.e_foreach.filter = $2;
- }
- | FOR ID '=' expr TO expr DO effect
- { $$ = new_effect(EFFECT_FOR);
- $$->e.e_for.id = intern_id($2);
- $$->e.e_for.start = $4;
- $$->e.e_for.stop = $6;
- $$->e.e_for.body = $8;
- }
- | IF expr THEN effect ELSE effect
- { $$ = new_effect(EFFECT_IF);
- $$->e.e_if.cond = $2;
- $$->e.e_if.true_branch = $4;
- $$->e.e_if.false_branch = $6;
- }
- | IF expr THEN effect
- { $$ = new_effect(EFFECT_IF);
- $$->e.e_if.cond = $2;
- $$->e.e_if.true_branch = $4;
- $$->e.e_if.false_branch = new_effect(EFFECT_SKIP);
- }
- | SLEEP expr ';'
- { $$ = new_effect(EFFECT_SLEEP);
- $$->e.e_sleep = $2;
- }
- | ID '(' arg_list ')' ';'
- { $$ = op_effect($1, $3.args_nr, $3.args, @1.first_line, @1.first_column);
- free($1);
- }
- | SCRIPT_DATA
- { $$ = new_effect(EFFECT_SCRIPT);
- $$->e.e_script = parse_script((unsigned char *) $1, @1.first_line);
- free($1);
- 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);
- }
- ;
-
-effect_list : /* empty */
- { $$ = new_effect(EFFECT_SKIP); }
- | effect semicolons effect_list
- { $$ = set_effect_continuation($1, $3); }
- ;
-
-
-%%
-
-/* 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)
-{
- int i;
-
- for (i = 0; i < magic_conf.vars_nr; i++)
- if (!strcmp(id_name, magic_conf.var_name[i])) {
- free((char*)id_name);
- return i;
- }
-
- /* 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 = TY_UNDEF;
-
- return i;
-}
-
-static void
-add_spell(spell_t *spell, int line_nr)
-{
- int index = magic_conf.spells_nr;
- int i;
-
- for (i = 0; i < index; i++) {
- 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;
- }
- }
- magic_conf.spells_nr++;
-
- RECREATE(magic_conf.spells, spell_t *, magic_conf.spells_nr);
- magic_conf.spells[index] = spell;
-
-
-}
-
-static void
-add_teleport_anchor(teleport_anchor_t *anchor, int line_nr)
-{
- int index = magic_conf.anchors_nr;
- int i;
-
- for (i = 0; i < index; i++) {
- 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;
- }
- }
- magic_conf.anchors_nr++;
-
- RECREATE(magic_conf.anchors, teleport_anchor_t *, magic_conf.anchors_nr);
- magic_conf.anchors[index] = anchor;
-}
-
-
-static void
-fail(int line, int column, const char *fmt, ...)
-{
- va_list ap;
- fprintf(stderr, "[magic-init] L%d:%d: ", line, column);
- va_start(ap, fmt);
- vfprintf(stderr, fmt, ap);
- failed_flag = 1;
-}
-
-static expr_t *
-dot_expr(expr_t *expr, int id)
-{
- 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)
-{
- int id;
- 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, "Incorrect number of arguments to function `%s': Expected %d, found %d\n", name, strlen(fun->signature), args_nr);
- 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];
- } else { /* failure */
- expr = magic_new_expr(EXPR_VAL);
- expr->e.e_val.ty = TY_FAIL;
- }
-
- return expr;
-}
-
-static spell_t *
-new_spell(spellguard_t *guard)
-{
- static int spell_counter = 0;
-
- spell_t *retval = (spell_t*)calloc(1, sizeof(spell_t));
- retval->index = ++spell_counter;
- retval->spellguard = guard;
- return retval;
-}
-
-static spellguard_t *
-new_spellguard(int ty)
-{
- spellguard_t *retval = (spellguard_t *)calloc(1, sizeof(spellguard_t));
- retval->ty = ty;
- return retval;
-}
-
-static spellguard_t *
-spellguard_implication(spellguard_t *a, spellguard_t *b)
-{
- spellguard_t *retval = a;
-
- if (a == b) /* This can happen due to reference sharing:
- * e.g.,
- * (R0 -> (R1 | R2)) => (R3)
- * yields
- * (R0 -> (R1 -> R3 | R2 -> R3))
- *
- * So if we now add => R4 to that, we want
- * (R0 -> (R1 -> R3 -> R4 | R2 -> R3 -> R4))
- *
- * but we only need to add it once, because the R3 reference is shared.
- */
- return retval;
-
- /* If the premise is a disjunction, b is the continuation of _all_ branches */
- if (a->ty == SPELLGUARD_CHOICE)
- spellguard_implication(a->s.s_alt, b);
- if (a->next)
- spellguard_implication(a->next, b);
- else
- a->next = b;
-
-
- return retval;
-}
-
-static effect_t *
-new_effect(int ty)
-{
- effect_t *effect = (effect_t *) calloc(1, sizeof(effect_t));
- effect->ty = ty;
- return effect;
-}
-
-static effect_t *
-set_effect_continuation(effect_t *src, effect_t *continuation)
-{
- 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)
- return retval;
-
- /* For FOR and FOREACH, we use special stack handlers and thus don't have to set
- * the continuation. It's only IF that we need to handle in this fashion. */
- if (src->ty == EFFECT_IF) {
- set_effect_continuation(src->e.e_if.true_branch, continuation);
- set_effect_continuation(src->e.e_if.false_branch, continuation);
- }
- if (src->next)
- set_effect_continuation(src->next, continuation);
- else
- src->next = continuation;
-
- return retval;
-}
-
-static effect_t *
-op_effect(char *name, int args_nr, expr_t **args, int line, int column)
-{
- int id;
- 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, "Incorrect number of arguments to operation `%s': Expected %d, found %d\n", name, strlen(op->signature), args_nr);
- 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;
-
- for (i = 0; i < args_nr; i++)
- effect->e.e_op.args[i] = args[i];
- } else /* failure */
- effect = new_effect(EFFECT_SKIP);
-
- return effect;
-}
-
-
-proc_t *procs = NULL;
-int procs_nr = 0;
-
-// I think this is a memory leak, or undefined behavior
-static void
-install_proc(proc_t *proc)
-{
- if (!procs) {
- procs = proc;
- procs_nr = 1;
- } else {
- RECREATE (procs, proc_t, 1 + procs_nr);
- procs[procs_nr++] = *proc;
- }
-}
-
-static effect_t *
-call_proc(char *name, int args_nr, expr_t **args, 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) {
- fail(line_nr, column, "Unknown procedure `%s'\n", name);
- return new_effect(EFFECT_SKIP);
- }
-
- if (p->args_nr != args_nr) {
- fail(line_nr, column, "Procedure %s/%d invoked with %d parameters\n", name, p->args_nr, args_nr);
- return new_effect(EFFECT_SKIP);
- }
-
- 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;
- return retval;
-}
-
-struct const_def_rec {
- char *name;
- val_t val;
-} *const_defs = NULL;
-
-int const_defs_nr = 0;
-
-static void
-bind_constant(char *name, val_t *val, int line_nr)
-{
- if (find_constant(name)) {
- fail(line_nr, 0, "Redefinition of constant `%s'\n", name);
- return;
- }
-
- 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)
-{
- int i;
- for (i = 0; i < const_defs_nr; i++) {
- if (!strcmp(const_defs[i].name, name)) {
- free(name);
- return &const_defs[i].val;
- }
- }
-
- return NULL;
-}
-
-
-
-
-#define INTERN_ASSERT(name, id) { int zid = intern_id(name); if (zid != id) fprintf(stderr, "[magic-conf] INTERNAL ERROR: Builtin special var %s interned to %d, not %d as it should be!\n", name, zid, id); error_flag = 1; }
-
-extern FILE *magic_frontend_in;
-
-int
-magic_init(char *conffile) // must be called after itemdb initialisation
-{
- int error_flag = 0;
-
- magic_conf.vars_nr = 0;
- magic_conf.var_name = (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);
- INTERN_ASSERT("spellpower", VAR_SPELLPOWER);
- INTERN_ASSERT("self_spell", VAR_SPELL);
- INTERN_ASSERT("self_invocation", VAR_INVOCATION);
- INTERN_ASSERT("target", VAR_TARGET);
- INTERN_ASSERT("script_target", VAR_SCRIPTTARGET);
- INTERN_ASSERT("location", VAR_LOCATION);
-
- magic_frontend_in = fopen(conffile, "r");
- if (!magic_frontend_in) {
- fprintf(stderr, "[magic-conf] Magic configuration file `%s' not found -> no magic.\n", conffile);
- return 0;
- }
- magic_frontend_parse();
-
- if (magic_conf.vars[VAR_MIN_CASTTIME].ty == TY_INT)
- magic_conf.min_casttime = magic_conf.vars[VAR_MIN_CASTTIME].v.v_int;
-
- if (magic_conf.vars[VAR_OBSCURE_CHANCE].ty == TY_INT)
- magic_conf.obscure_chance = magic_conf.vars[VAR_OBSCURE_CHANCE].v.v_int;
-
- 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);
- failed_flag = 1;
-}