<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