[Circle] LONG CODE - functions fixing mobprog if/else/endif associates

From: Eric L. Helvey (helver@newwave.net)
Date: 07/25/96


These things should work nicely...  I've taken a couple of the functions
out of my mobprog.c and supplied them here.  In the mprog_process_if
there might be one or two function calls that are undefined in your 
particular versions.  But it should work.

Helver

> char* find_endif (char* com_list, struct char_data* mob)
> {
> 
>    int   if_scope = 1; 
> 
>    char* cmnd     = '\0';
>    char* morebuf  = '\0';
> 
>    char  buf [MAX_INPUT_LENGTH];
> 
>    while (if_scope > 0)
>    {
>       cmnd = com_list;
> 
>       while (*com_list != '\n' && *com_list != '\r' && *com_list != '\0') com_list++; com_list++;
> 
>       while (isspace(*cmnd)) cmnd++;
> 
>       if (*cmnd == '\0')
>       {
>          bug ("Mob: %d missing else or endif in find_endif", mob_index[mob->nr].virtual);
>          return '\0';
>       }
> 
>       morebuf = one_argument (cmnd, buf);
> 
>       if (!str_cmp (buf, "if")) if_scope++; 
>       if (!str_cmp (buf, "endif")) if_scope--;
> 
>    } /* while */
> 
>    return com_list;
> 
> } /* find_endif */
> 
> /* Used in mprog_process_if to determine the proper 'else' of the if-block so that
>  * other subsequent commands are not skipped in the event of and error or
>  * breaks in nested if statements. This will inprove the logical flow of
>  * mob_prog processing to what it should be.
>  */
> 
> char* find_else (char* com_list, struct char_data *mob)
> {
>    int   if_scope = 1; 
> 
>    char* cmnd     = '\0';
>    char* morebuf  = '\0';
> 
>    char  buf [MAX_INPUT_LENGTH];
> 
>    while (if_scope > 0)
>    {
>       cmnd = com_list;
> 
>       while (*com_list != '\n' && *com_list != '\r' && *com_list != '\0') com_list++; com_list++;
> 
>       while (isspace(*cmnd)) cmnd++;
> 
>       if (*cmnd == '\0')
>       {
>          bug ("Mob: %d missing else or endif in find_else", mob_index[mob->nr].virtual);
>          return '\0';
>       }
> 
>       morebuf = one_argument (cmnd, buf);
> 
>       if (!str_cmp (buf, "if")) if_scope++; 
>       if (!str_cmp (buf, "endif")) if_scope--;
>       if ((!str_cmp (buf, "else")) && (if_scope == 1))
>       {
>          return cmnd;
>       }
> 
>    } /* while */
> 
>    return cmnd;
>  
> } /* find_else */
> 
> 
> /* Used to get sequential lines of a multi line string (separated by "\n\r")
>  * Thus its like one_argument(), but a trifle different. It is destructive
>  * to the multi line string argument, and thus clist must not be shared.
>  */
> 
> char *mprog_next_command(char *clist)
> {
> 
>   char *pointer = clist;
> 
> /* a little error checking here, if we are sent a null pointer
>  * dereferencing it would cause a seg fault and crash the mud
>  * this is defined as 'bad'. for a complete description of 'bad'
>  * check your local dictionary :)
>  */
>   if (!clist) return NULL;
> 
>   if (*pointer == '\r')
>     pointer++;  
>   if (*pointer == '\n')
>     pointer++;
> 
>   while (*pointer != '\n' && *pointer != '\0' && *pointer != '\r')
>     pointer++;
>   if (*pointer == '\n') {
>     *pointer = '\0';
>     pointer++; }
>   if (*pointer == '\r') {
>     *pointer = '\0';
>     pointer++; }
>     
>   return (pointer);
> 
> }
> 
> /* Quite a long and arduous function, this guy handles the control
>  * flow part of MOBprograms.  Basicially once the driver sees an
>  * 'if' attention shifts to here.  While many syntax errors are
>  * caught, some will still get through due to the handling of break
>  * and errors in the same fashion.  The desire to break out of the
>  * recursion without catastrophe in the event of a mis-parse was
>  * believed to be high. Thus, if an error is found, it is bugged and
>  * the parser acts as though a break were issued and just bails out
>  * at that point. I havent tested all the possibilites, so I'm speaking
>  * in theory, but it is 'guaranteed' to work on syntactically correct
>  * MOBprograms, so if the mud crashes here, check the mob carefully!
>  */
> 
> char null[1];
> 
> char *mprog_process_if(char *ifchck, char *com_list, struct char_data *mob,
> 		       struct char_data *actor, struct obj_data *obj, void *vo,
> 		       struct char_data *rndm)
> {
> 
>  char buf[ MAX_INPUT_LENGTH ];
>  char buf2[ MAX_INPUT_LENGTH ];
>  char *morebuf = '\0';
>  char    *cmnd = '\0';
>  int loopdone = FALSE;
>  int     flag = FALSE;
>  int  legal;
> 
>  char *end_list  = '\0';
>  char *else_list = '\0';
> 
>  *null = '\0';
> 
>  /* find the end of the list if-block for returning instead of 
>   * completely dropping out the mob-prog
>   */
> 
>  end_list  = find_endif (com_list, mob);
> 
>  /* skip all of the if-block to the proper 'else' segment
>   * if there is no 'else' segment, this function will skip
>   * to the proper 'endif' -- it's amazingly cool :) brr
>   */
> 
>  else_list = find_else  (com_list, mob);
> 
> 
>  /* check for trueness of the ifcheck */
>  if ((legal = mprog_do_ifchck(ifchck, mob, actor, obj, vo, rndm))) flag = TRUE;
> 
>  while(loopdone == FALSE) /*scan over any existing or statements */
>  {
>      cmnd     = com_list;
>      com_list = mprog_next_command(com_list);
>      while (*cmnd == ' ')
>        cmnd++;
>      if (*cmnd == '\0')
>      {
> 	 bug ("Mob: %d no commands after IF/OR", mob_index[mob->nr].virtual); 
> 	 return null;
>      }
>      morebuf = one_argument(cmnd,buf);
>      if (!str_cmp(buf, "or"))
>      {
> 	 if ((legal = mprog_do_ifchck(morebuf,mob,actor,obj,vo,rndm))) flag = TRUE;
>      }
>      else
>        loopdone = TRUE;
>  }
>  
>  if (flag)
>    for (; ;) /*ifcheck was true, do commands but ignore else to endif*/ 
>    {
>        if (!str_cmp(buf, "if"))
>        { 
> 	   com_list = mprog_process_if(morebuf,com_list,mob,actor,obj,vo,rndm);
> 	   while (*cmnd==' ')
> 	     cmnd++;
> 	   if (*com_list == '\0')
> 	     return null;
> 	   cmnd     = com_list;
> 	   com_list = mprog_next_command(com_list);
> 	   morebuf  = one_argument(cmnd,buf);
> 	   continue;
>        }
>        if (   (!str_cmp(buf, "break"))
>            || (!str_cmp(buf, "endif")) 
>            || (!str_cmp(buf, "else"))
>           )
>           return end_list;
> 
>        strcpy (buf2, cmnd);
>        strcat (buf2, com_list);
>        mprog_process_cmnd(buf2, mob, actor, obj, vo, rndm);
>        if (!(*buf2)) com_list[0] = '\0';
>        cmnd     = com_list;
>        com_list = mprog_next_command(com_list);
>        while (*cmnd == ' ')
> 	 cmnd++;
>        if (*cmnd == '\0')
>        {
>            bug ("Mob: %d missing else or endif", mob_index[mob->nr].virtual); 
>            return null;
>        }
>        morebuf = one_argument(cmnd, buf);
>    }
>  else /*false ifcheck, find else and do existing commands or quit at endif*/
>    {
>      com_list = else_list;
>      cmnd     = com_list;
>      com_list = mprog_next_command(com_list);
> 
>      morebuf = one_argument(cmnd, buf);
> 
>      /* found either an else or an endif.. act accordingly */
>      if (!str_cmp(buf, "endif")) {
>        return com_list;
> 	}
>      cmnd     = com_list;
>      com_list = mprog_next_command(com_list);
>      if (cmnd == NULL) {
>         bug ("Mob: %d null command list", mob_index[mob->nr].virtual);
>         return null;
>      }
>      while (*cmnd == ' ')
>        cmnd++;
>      if (*cmnd == '\0')
>        { 
> 	 bug ("Mob: %d missing endif", mob_index[mob->nr].virtual); 
> 	 return null;
>        }
>      morebuf = one_argument(cmnd, buf);
>      
>      for (; ;) /*process the post-else commands until an endif is found.*/
>        {
> 	 if (!str_cmp(buf, "if"))
> 	   { 
> 	     com_list = mprog_process_if(morebuf, com_list, mob, actor,
> 					 obj, vo, rndm);
> 	     while (*cmnd == ' ')
> 	       cmnd++;
> 	     if (*com_list == '\0')
> 	       return null;
> 	     cmnd     = com_list;
> 	     com_list = mprog_next_command(com_list);
> 	     morebuf  = one_argument(cmnd,buf);
> 	     continue;
> 	   }
> 	 if (!str_cmp(buf, "else")) 
> 	   {
> 	     bug ("Mob: %d found else in an else section",
> 		  mob_index[mob->nr].virtual); 
> 	     return end_list;
> 	   }
> 	 if (   (!str_cmp(buf, "break"))
> 	     || (!str_cmp(buf, "endif"))
>             )
> 	    return end_list; 
> 
>          strcpy (buf2, cmnd);
>          strcat (buf2, com_list);
> 	 mprog_process_cmnd(buf2, mob, actor, obj, vo, rndm);
>          if (!(*buf2)) com_list[0] = '\0';
> 	 cmnd     = com_list;
> 	 com_list = mprog_next_command(com_list);
> 	 while (*cmnd == ' ')
> 	   cmnd++;
> 	 if (*cmnd == '\0')
> 	   {
> 	     bug ("Mob:%d missing endif in else section",
> 		  mob_index[mob->nr].virtual); 
> 	     return null;
> 	   }
> 	 morebuf = one_argument(cmnd, buf);
>        }
>    }
> }
> 
+-----------------------------------------------------------+
| Ensure that you have read the CircleMUD Mailing List FAQ: |
|   http://cspo.queensu.ca/~fletcher/Circle/list_faq.html   |
+-----------------------------------------------------------+



This archive was generated by hypermail 2b30 : 12/07/00 PST