circlemud_squared_0.5.153/cnf/
circlemud_squared_0.5.153/etc/
circlemud_squared_0.5.153/etc/etc/
circlemud_squared_0.5.153/etc/house/
circlemud_squared_0.5.153/etc/misc/
circlemud_squared_0.5.153/etc/plralias/A-E/
circlemud_squared_0.5.153/etc/plralias/F-J/
circlemud_squared_0.5.153/etc/plralias/K-O/
circlemud_squared_0.5.153/etc/plralias/P-T/
circlemud_squared_0.5.153/etc/plralias/U-Z/
circlemud_squared_0.5.153/etc/plralias/ZZZ/
circlemud_squared_0.5.153/etc/plrobjs/
circlemud_squared_0.5.153/etc/plrobjs/A-E/
circlemud_squared_0.5.153/etc/plrobjs/F-J/
circlemud_squared_0.5.153/etc/plrobjs/K-O/
circlemud_squared_0.5.153/etc/plrobjs/P-T/
circlemud_squared_0.5.153/etc/plrobjs/U-Z/
circlemud_squared_0.5.153/etc/plrobjs/ZZZ/
circlemud_squared_0.5.153/etc/text/
circlemud_squared_0.5.153/etc/text/help/
circlemud_squared_0.5.153/src/util/
circlemud_squared_0.5.153/src/util/worldconv/
/* ************************************************************************
*   File: interpreter.c                                 Part of CircleMUD *
*  Usage: parse user commands, search for specials, call ACMD functions   *
*                                                                         *
*  All rights reserved.  See license.doc for complete information.        *
*                                                                         *
*  Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University *
*  CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991.               *
************************************************************************ */
/*
 * This file contains the functions to load the world files into memory
 * into the stock CircleMUD arrays.
 *
 * You should update this code to match the code in your MUD if it's been
 * changed from stock in any way.
 */

#include "sysdep.h"
#include "utils.h"
#include "structs.h"
#include "interpreter.h"
#include "main.h"



const char *fill[] =
{
  "in",
  "from",
  "with",
  "the",
  "on",
  "at",
  "to",
  "\n"
};


/*
 * Function to skip over the leading spaces of a string.
 */
void skip_spaces(char **string)
{
  for (; **string && isspace(**string); (*string)++);
}

int fill_word(char *argument)
{
  return (search_block(argument, fill, TRUE) >= 0);
}


/*
 * one_word is like one_argument, except that words in quotes ("") are
 * considered one word.
 */
char *one_word(char *argument, char *first_arg)
{
  char *begin = first_arg;

  do {
    skip_spaces(&argument);

    first_arg = begin;

    if (*argument == '\"') {
      argument++;
      while (*argument && *argument != '\"') {
        *(first_arg++) = LOWER(*argument);
        argument++;
      }
      argument++;
    } else {
      while (*argument && !isspace(*argument)) {
        *(first_arg++) = LOWER(*argument);
        argument++;
      }
    }

    *first_arg = '\0';
  } while (fill_word(begin));

  return (argument);
}


/**
 * Returns whether a string a valid integer.
 * @param str the string to be tested
 * @param allowSign whether an initial + or - sign is permitted
 * @return TRUE if the string is a valid integer;
 *         FALSE otherwise
 */
bool isInteger(const char *str, bool allowSign) {
  if (str != NULL && *str != '\0') {
    /* Skip any leading whitespace. */
    while (*str != '\0' && isspace(*str)) {
      str++;
    }
    /* Skip the sign character if its permitted. */
    if (allowSign && strchr("+-", *str) != NULL) {
      str++;
    }
    if (isdigit(*str)) {
      /* Skip any digit characters. */
      while (isdigit(*str)) {
        str++;
      }
      /* Skip any trailing whitespace. */
      while (*str != '\0' && isspace(*str)) {
        str++;
      }
      if (*str == '\0') {
        return (TRUE);
      }
    }
  }
  return (FALSE);
}

/*
 * searches an array of strings for a target string.  "exact" can be
 * 0 or non-0, depending on whether or not the match must be exact for
 * it to be returned.  Returns -1 if not found; 0..n otherwise.  Array
 * must be terminated with a '\n' so it knows to stop searching.
 */
ssize_t search_block(const char *arg, const char **list, bool exact)
{
  int i, l;

  /*  We used to have \r as the first character on certain array items to
   *  prevent the explicit choice of that point.  It seems a bit silly to
   *  dump control characters into arrays to prevent that, so we'll just
   *  check in here to see if the first character of the argument is '!',
   *  and if so, just blindly return a '-1' for not found. - ae.
   */
  if (*arg == '!')
    return (-1);

  /* Record the length of the argument. */
  l = strlen(arg);

  if (exact) {
    for (i = 0; **(list + i) != '\n'; i++)
      if (!strcasecmp(arg, *(list + i)))
        return (i);
  } else {
    if (!l)
      l = 1;                    /* Avoid "" to match the first available
                                 * string */
    for (i = 0; **(list + i) != '\n'; i++)
      if (!strncasecmp(arg, *(list + i), l))
        return (i);
  }

  return (-1);
}

/**
 * Reads one token from a source string.
 * @param buf the buffer into which the token is to be written
 * @param buflen the length of the specified buffer
 * @param delims the list of characters delimiting the next token
 * @param src the source string from which the token is to be read
 * @return a pointer to the character in the source string that bounds the
 *   token written into the specified buffer, or NULL if some error occurs
 */
const char *onetoken(char *buf, size_t buflen, const char *delims,
  const char *src) {
  register const char *p = NULL;
  if (buf == NULL) {
    log("onetoken(): invalid 'buf' string.");
  } else if (buflen == 0) {
    log("onetoken(): invalid 'buflen' value 0.");
  } else if (delims == NULL || *delims == '\0') {
    log("onetoken(): invalid 'delims' string.");
  } else if (src == NULL) {
    log("onetoken(): invalid 'src' string.");
  } else {
    /* Declare a variable to contain the buffer position. */
    register size_t bufpos = 0;

    /* Iterate over the source string. */
    for (p = src; *p != '\0' && strchr(delims, *p) == NULL; p++) {
      /* Accumulate the character. */
      if (bufpos < buflen - 1 && *p != '\r') {
        buf[bufpos++] = *p;
      }
    }
    /* Terminate the buffer with a NUL character. */
    buf[bufpos] = '\0';
  }
  return (p);
}

/**
 * Gets whether a string represents a numeric value.
 * @param string the string to be tested
 * @return <code>true</code> if the specified string represents an integer or
 *   floating point numeric value; <code>false</code> otherwise
 */
bool isNumber(const char *string) {
  if (string && *string != '\0') {
    /* Skip a leading + or - sign. */
    if (*string == '+' || *string == '-') {
      string++;
    }
    if (isdigit(*string)) {
      /* Declare a variable to point to the end of the source string. */
      char *endPointer = NULL;

      /* Parse a floating point value from the source string. */
      double dummy = strtod(string, &endPointer);

      /* Skip any trailing whitespace. */
      while (endPointer && *endPointer != '\0' && isspace(*endPointer)) {
        endPointer++;
      }
      /* Test whether we parsed a valid number. */
      if (dummy != 0.0 ||
         (endPointer != string && *endPointer == '\0')) {
        return (TRUE);
      }
    }
  }
  return (FALSE);
}