Re: erh, something about DG.. :)

From: Claude Belisle (cbeli@pop.agri.ch)
Date: 02/12/00


<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