<snip>
> ----- Start script -----
> if (<some statement>) # First IF
> if (<another statement>) # Second IF
> <DO SOMETHING>
> else # Belonging to Second IF
> <DO SOMETHING ELSE>
> else # Really belonging to the First IF, but missing an END
> <DO SOMETHING ELSE>
> ----- End Script -----
<end snip>
I tried a similarly structured trigger and it crashed too. Investigating led
me to find
that there are no checks to see if an else/elseif/end is ever found. This is
what causes
the crash. I've modified the code to take care of that (please feel free to
report if there
is a more correct way of doing it). Below is what I've done. Hope it helps
All changes are in dg_scripts.c
1. Top of file, include olc.h for access to the LVL_BUILDER define
2. find_end()
struct cmdlist_element *find_end(struct cmdlist_element *cl)
{
struct cmdlist_element *c;
char *p;
if ((!cl) || (!(cl->next)))
return NULL;
for (c = cl->next; c->next; c = c->next)
{
for (p = c->cmd; *p && isspace(*p); p++);
if (!strn_cmp("if ", p, 3))
{
c = find_end(c);
/* MANWE_IF: If we've gotten to the end without finding one */
if (!c)
return NULL;
}
else if (!strn_cmp("end", p, 3))
return c;
}
return NULL;
}
3. find_else_end() - Here, there is something I cannot understand. I stepped
through the code, and
somehow, the loop exits one too early. I made a quick and dirty check
for it now, but hope I, or
someone will find the problem.
struct cmdlist_element *find_else_end(trig_data *trig,
struct cmdlist_element *cl, void *go,
struct script_data *sc, int type)
{
struct cmdlist_element *c;
char *p;
if ((!cl) || (!(cl->next)))
return NULL;
for (c = cl->next; c->next; c = c->next)
{
for (p = c->cmd; *p && isspace(*p); p++);
if (!strn_cmp("if ", p, 3))
{
c = find_end(c);
/* MANWE_IF: IF we've gotten to the end without finding one */
if (!c)
return NULL;
}
else if (!strn_cmp("elseif ", p, 7))
{
if (process_if(p + 7, go, sc, trig, type))
{
GET_TRIG_DEPTH(trig)++;
return c;
}
}
else if (!strn_cmp("else", p, 4))
{
GET_TRIG_DEPTH(trig)++;
return c;
}
else if (!strn_cmp("end", p, 3))
return c;
}
/* MANWE_IF: Can't figure out why, but the case where an 'end' is found on
the very last line
* of a trigger is not handled well, this is a work around until I figure
it out, if ever.
*/
if ((c) && (!strn_cmp("end", c->cmd, 3)))
return c;
else
return NULL;
}
4. Modifications to script_driver()
else if (!strn_cmp(p, "if ", 3))
{
if (process_if(p + 3, go, sc, trig, type))
{
GET_TRIG_DEPTH(trig)++;
}
else
{
cl = find_else_end(trig, cl, go, sc, type);
/* MANWE_IF: Added to get rid of missing end crashes */
if (!cl)
{
sprintf(cmd, "IF without END in trigger \"%s\"", trig->name);
mudlog(cmd, CMP, LVL_BUILDER, TRUE);
release_buffer(cmd);
return 0;
}
}
}
else if (!strn_cmp("elseif ", p, 7) || !strn_cmp("else", p, 4))
{
cl = find_end(cl);
/* MANWE_IF: Added to get rid of missing end crashes */
if (!cl)
{
sprintf(cmd, "ELSE without END in trigger \"%s\"", trig->name);
mudlog(cmd, CMP, LVL_BUILDER, TRUE);
release_buffer(cmd);
return 0;
}
else
{
GET_TRIG_DEPTH(trig)++;
}
}
That's about it. Checked different cases (for when if is true, when false,
with else, with elseif, without end, etc) and it seems
to works pretty good. I don't post often to this list as I find the level of
knowledge is way above mine and I like to putz along
and find things myself, but since I'm here :) does anyone see the need to
increment the depth level on an else? It is in the code
and I would think an else is on the same level as the corresponding if. The
way it is now, it looks to me as an if/else pair counts
for two levels of nesting. Any thoughts?
Claude Belisle aka PhoenixMUD's very own Manwe :)
+------------------------------------------------------------+
| Ensure that you have read the CircleMUD Mailing List FAQ: |
| http://qsilver.queensu.ca/~fletchra/Circle/list-faq.html |
+------------------------------------------------------------+
This archive was generated by hypermail 2b30 : 04/10/01 PDT