Crossfire Mailing List Archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: CF: BUG: Morks Tower



On Sun, May 07, 2000 at 08:44:29PM -0700, Mark Wedel wrote:
>  Since monsters themselves can not trigger special actions (like gates moving or
> the like), this often instead is done by putting magic ears on the map which are
> triggered when the time is right.

The attached patch modifies parse_message() to recognize '@connected'
lines immediately after '@match' lines.  It also fixes several memory
leaks and null pointer dereferences for incorrectly formatted messages
(maybe you want to rewrite it completely as it's still very ugly).  But
note that the patch is completely untested (I'm still working on the
apply() rewrite, my local tree is in the middle of nowhere and can't be
compiled any time soon) and incomplete.  A push_connected_objects()
function is missing that is similar to push_button() but takes the
'connected' number as an argument, not an object pointer.  I won't have
time to finish this patch, but somebody else may take it as a start.

-- 
Jan
*** monster.c-orig	Mon May  8 12:28:17 2000
--- monster.c	Mon May  8 13:18:38 2000
***************
*** 41,48 ****
--- 41,51 ----
   */
  
  typedef struct _msglang {
+   size_t nummsgs;       /* Number of messages */
    char **messages;	/* An array of messages */
+   size_t *numkeywords;  /* For each message, number of keywords */
    char ***keywords;	/* For each message, an array of strings to match */
+   int *connected;       /* For each message, connected objects */
  } msglang;
  
  
***************
*** 1189,1202 ****
      return 1;
  }
  
! static void free_messages(msglang *msgs) {
    int messages, keywords;
  
    if (!msgs)
      return;
!   for(messages = 0; msgs->messages[messages]; messages++) {
      if(msgs->keywords[messages]) {
!       for(keywords = 0; msgs->keywords[messages][keywords]; keywords++)
          free(msgs->keywords[messages][keywords]);
        free(msgs->keywords[messages]);
      }
--- 1192,1206 ----
      return 1;
  }
  
! static void free_messages (msglang *msgs)
! {
    int messages, keywords;
  
    if (!msgs)
      return;
!   for(messages = 0; messages < msgs->nummsgs; messages++) {
      if(msgs->keywords[messages]) {
!       for(keywords = 0; keywords < msgs->numkeywords[messages]; keywords++)
          free(msgs->keywords[messages][keywords]);
        free(msgs->keywords[messages]);
      }
***************
*** 1204,1243 ****
    }
    free(msgs->messages);
    free(msgs->keywords);
    free(msgs);
  }
  
! static msglang *parse_message(char *msg) {
!   msglang *msgs;
    int nrofmsgs, msgnr, i;
    char *cp, *line, *last;
-   char *buf = strdup_local(msg);
  
!   /* First find out how many messages there are.  A @ for each. */
!   for (nrofmsgs = 0, cp = buf; *cp; cp++)
!     if (*cp == '@')
!       nrofmsgs++;
    if (!nrofmsgs)
!     return NULL;
  
    msgs = (msglang *) malloc(sizeof(msglang));
    msgs->messages = (char **) malloc(sizeof(char *) * (nrofmsgs + 1));
    msgs->keywords = (char ***) malloc(sizeof(char **) * (nrofmsgs + 1));
    for(i=0; i<=nrofmsgs; i++) {
      msgs->messages[i] = NULL;
      msgs->keywords[i] = NULL;
    }
  
    for (last = NULL, cp = buf, msgnr = 0;*cp; cp++)
      if (*cp == '@') {
!       int nrofkeywords, keywordnr;
        *cp = '\0'; cp++;
        if(last != NULL)
          msgs->messages[msgnr++] = strdup_local(last);
!       if(strncmp(cp,"match",5)) {
          LOG(llevError,"Unsupported command in message.\n");
!         free(buf);
!         return NULL;
        }
        for(line = cp + 6, nrofkeywords = 0; *line != '\n' && *line; line++)
          if(*line == '|')
--- 1208,1261 ----
    }
    free(msgs->messages);
    free(msgs->keywords);
+   free(msgs->numkeywords);
    free(msgs);
  }
  
! static msglang *parse_message (char *msg)
! {
!   static const char msgstart[] = "@match";
!   msglang *msgs = NULL;
!   char *buf = strdup_local(msg);
! 
    int nrofmsgs, msgnr, i;
    char *cp, *line, *last;
  
! 
!   /* First find out how many messages there are. */
!   nrofmsgs = 0;
!   cp = buf;
!   while (1) {
!     cp = strstr (cp, msgstart);
!     if (cp == NULL)
!       goto error;
!     nrofmsgs++;
!     cp += (sizeof msgstart) - 1;   /* strlen (msgstart) */
!   }
    if (!nrofmsgs)
!     goto error;
  
    msgs = (msglang *) malloc(sizeof(msglang));
+   msgs->nummsgs = nrofmsgs + 1;
    msgs->messages = (char **) malloc(sizeof(char *) * (nrofmsgs + 1));
+   msgs->numkeywords = malloc (sizeof (size_t) * (nrofmsgs + 1));
    msgs->keywords = (char ***) malloc(sizeof(char **) * (nrofmsgs + 1));
+   msgs->connected = malloc (sizeof (int) * (nrofmsgs + 1));
    for(i=0; i<=nrofmsgs; i++) {
      msgs->messages[i] = NULL;
      msgs->keywords[i] = NULL;
+     msgs->connected[i] = 0;
    }
  
    for (last = NULL, cp = buf, msgnr = 0;*cp; cp++)
      if (*cp == '@') {
!       int nrofkeywords, keywordnr, connected;
        *cp = '\0'; cp++;
        if(last != NULL)
          msgs->messages[msgnr++] = strdup_local(last);
!       if(strncmp(cp,msgstart, (sizeof msgstart) - 1)) {
          LOG(llevError,"Unsupported command in message.\n");
!         goto error;
        }
        for(line = cp + 6, nrofkeywords = 0; *line != '\n' && *line; line++)
          if(*line == '|')
***************
*** 1246,1261 ****
          nrofkeywords++;
        if(nrofkeywords < 1) {
          LOG(llevError,"Too few keywords in message.\n");
!         free(buf);
!         free_messages(msgs);
!         return NULL; 
        }
        msgs->keywords[msgnr] = (char **) malloc(sizeof(char **) * (nrofkeywords +1));
        msgs->keywords[msgnr][nrofkeywords] = NULL;
        last = cp + 6;
        cp = strchr(cp,'\n');
!       if(cp != NULL)
!         cp++;
        for(line = last, keywordnr = 0;line<cp && *line;line++)
          if(*line == '\n' || *line == '|') {
            *line = '\0';
--- 1264,1280 ----
          nrofkeywords++;
        if(nrofkeywords < 1) {
          LOG(llevError,"Too few keywords in message.\n");
!         goto error;
        }
+       msgs->numkeywords[msgnr] = nrofkeywords + 1;
        msgs->keywords[msgnr] = (char **) malloc(sizeof(char **) * (nrofkeywords +1));
        msgs->keywords[msgnr][nrofkeywords] = NULL;
        last = cp + 6;
        cp = strchr(cp,'\n');
!       if(cp == NULL) {
!         LOG (llevError, "Incomplete @match line.\n");
!         goto error;
!       }
        for(line = last, keywordnr = 0;line<cp && *line;line++)
          if(*line == '\n' || *line == '|') {
            *line = '\0';
***************
*** 1263,1274 ****
--- 1282,1308 ----
              msgs->keywords[msgnr][keywordnr++] = strdup_local(last);
            last = line + 1;
          }
+       if (sscanf (cp, "@connected %d", &connected) == 1) {
+         msgs->connected[msgnr] = connected;
+         cp = strchr (cp, '\n');
+         if (cp == NULL) {
+           llevError, "Incomplete @connected line.\n");
+           goto error;
+         }
+         cp++;
+       }
        last = cp;
      }
    if(last != NULL)
      msgs->messages[msgnr++] = strdup_local(last);
    free(buf);
    return msgs;
+ 
+ 
+  error:
+   free (buf);
+   free_messages (msgs);
+   return NULL;
  }
  
  static void dump_messages(msglang *msgs) {
***************
*** 1315,1320 ****
--- 1349,1355 ----
          sprintf(buf,"The %s says:",query_name(npc));
  	new_info_map(NDI_NAVY|NDI_UNIQUE, npc->map,buf);
  	new_info_map(NDI_NAVY | NDI_UNIQUE, npc->map, msgs->messages[i]);
+         push_connected_objects (msgs->connected[i]);
          free_messages(msgs);
          return 1;
        }