예제 #1
0
파일: handler.c 프로젝트: KaSt/nereamud
void room_exist(ROOM_DATA *room) {
  propertyTablePut(room_table, room);

  // add contents
  if(listSize(roomGetContents(room)) > 0) {
    LIST_ITERATOR *cont_i = newListIterator(roomGetContents(room));
    OBJ_DATA        *cont = NULL;
    ITERATE_LIST(cont, cont_i)
      obj_exist(cont);
    deleteListIterator(cont_i);
  }

  // add its people
  if(listSize(roomGetCharacters(room)) > 0) {
    LIST_ITERATOR *ch_i = newListIterator(roomGetCharacters(room));
    CHAR_DATA       *ch = NULL;
    ITERATE_LIST(ch, ch_i)
      char_exist(ch);
    deleteListIterator(ch_i);
  }

  // add its exits
  LIST       *ex_list = roomGetExitNames(room);
  LIST_ITERATOR *ex_i = newListIterator(ex_list);
  char           *dir = NULL;
  ITERATE_LIST(dir, ex_i) {
    exit_exist(roomGetExit(room, dir));
  } deleteListIterator(ex_i);
예제 #2
0
파일: parse.c 프로젝트: KaSt/nereamud
//
// Takes a list of tokens, and builds the proper syntax for the command and
// then sends it to the character.
void show_parse_syntax_error(CHAR_DATA *ch, const char *cmd, LIST *tokens) {
  BUFFER            *buf = newBuffer(1);
  LIST_ITERATOR   *tok_i = newListIterator(tokens);
  PARSE_TOKEN       *tok = NULL;
  bool    optional_found = FALSE;
  int              count = 0;

  // go through all of our tokens, and append their syntax to the buf
  ITERATE_LIST(tok, tok_i) {
    // make sure we add a space before anything else...
    if(count > 0)
      bprintf(buf, " ");
    count++;

    // have we encountered the "optional" marker? if so, switch our open/close
    if(tok->type == PARSE_TOKEN_OPTIONAL) {
      bprintf(buf, "[");
      optional_found = TRUE;
      // we don't want to put a space right after this [
      count = 0;
      continue;
    }

    // append our message
    switch(tok->type) {
    case PARSE_TOKEN_MULTI: {
      bprintf(buf, "<");
      LIST_ITERATOR *multi_i = newListIterator(tok->token_list);
      PARSE_TOKEN      *mtok = NULL;
      int            m_count = 0;
      ITERATE_LIST(mtok, multi_i) {
	if(m_count > 0)
	  bprintf(buf, ", ");
	m_count++;
	bprintf(buf, "%s", get_datatype_format_error_mssg(mtok));
      } deleteListIterator(multi_i);
      bprintf(buf, ">");
      break;
    }

    case PARSE_TOKEN_FLAVOR:
      bprintf(buf, "%s%s%s", (tok->flavor_optional ? "[" : ""), tok->flavor,
	      (tok->flavor_optional ? "]" : ""));
      break;

    default:
      bprintf(buf, "<%s>", get_datatype_format_error_mssg(tok));
      break;
    }
  } deleteListIterator(tok_i);

  // send the message
  send_to_char(ch, "Proper syntax is: %s %s%s\r\n", cmd, bufferString(buf),
	       (optional_found ? "]" : ""));
  deleteBuffer(buf);
}
예제 #3
0
파일: socket.c 프로젝트: KaSt/nereamud
/* reset all of the sockets' control values */
void reconnect_copyover_sockets() {
  LIST_ITERATOR *sock_i = newListIterator(socket_list);
  SOCKET_DATA     *sock = NULL; 
  ITERATE_LIST(sock, sock_i)
    FD_SET(sock->control, &fSet);
  deleteListIterator(sock_i);
}
예제 #4
0
/// Function name  : findDocumentIndexByValue
// Description     : Determines the index of the specified document
// 
// DOCUMENTS_DATA*  pDocumentsData  : [in]  Window data
// CONST DOCUMENT*  pTargetDocument : [in]  Document to retrieve the index for
// INT&             iOutput         : [out] Zero-based index if found, otherwise -1
// 
// Return Value   : TRUE if found, otherwise FALSE
// 
BOOL   findDocumentIndexByValue(DOCUMENTS_DATA*  pWindowData, CONST DOCUMENT*  pTargetDocument, INT&  iOutput)
{
   LIST_ITERATOR*  pIterator;             // List iterator
   DOCUMENT*       pCurrentDocument;      // List iterator

   
   // Prepare
   iOutput = -1;

   /// Iterate through document list
   for (pIterator = createListIterator(pWindowData->pDocumentList); getCurrentItem(pIterator, (LPARAM&)pCurrentDocument); moveNextItem(pIterator))
   {
      // [CHECK] Compare current item
      if (pCurrentDocument == pTargetDocument)
      {
         /// [FOUND] Set result and abort
         iOutput = pIterator->iIndex;
         break;
      }
   }

   // Cleanup and return TRUE if found
   deleteListIterator(pIterator);
   return (iOutput != -1);
}
예제 #5
0
파일: persistent.c 프로젝트: KaSt/nereamud
//
// unload a persistent room from memory. Will not work if PCs are present.
PyObject *PyRoom_unloadPersistence(PyObject *pyroom) {
  ROOM_DATA *room = PyRoom_AsRoom(pyroom);
  if(room == NULL) {
    PyErr_Format(PyExc_TypeError, "tried to save nonexistent room.");
    return NULL;
  }

  // it's not pesistent
  if(!roomIsPersistent(room))
    return Py_BuildValue("i", 0);

  // does it contain a PC?
  LIST_ITERATOR *ch_i = newListIterator(roomGetCharacters(room));
  CHAR_DATA       *ch = NULL;
  bool       pc_found = FALSE;
  ITERATE_LIST(ch, ch_i) {
    if(!charIsNPC(ch)) {
      pc_found = TRUE;
      break;
    }
  } deleteListIterator(ch_i);

  if(pc_found)
    return Py_BuildValue("i", 0);
  worldStorePersistentRoom(gameworld, roomGetClass(room), room);
  extract_room(room);
  return Py_BuildValue("");
}
예제 #6
0
/// Function name  : findDocumentIndexByPath
// Description     : Determines the index of the specified document
// 
// HWND          hTabCtrl     : [in]  Documents control
// CONST TCHAR*  szFullPath   : [in]  Full path of the desired document
// INT&          iOutput      : [out] Zero-based index if found, otherwise -1
// 
// Return Value   : TRUE if found, otherwise FALSE
// 
BOOL   findDocumentIndexByPath(HWND  hTabCtrl, CONST TCHAR*  szFullPath, INT&  iOutput)
{
   DOCUMENTS_DATA* pWindowData;    // Window data
   LIST_ITERATOR*  pIterator;      // List iterator
   DOCUMENT*       pDocument;      // List iterator

   
   // Prepare
   pWindowData = getDocumentsControlData(hTabCtrl);
   iOutput     = -1;
   
   /// Iterate through document list
   for (pIterator = createListIterator(pWindowData->pDocumentList); getCurrentItem(pIterator, (LPARAM&)pDocument); moveNextItem(pIterator))
   {
      // [CHECK] Compare paths
      if (utilCompareStringVariables(getDocumentPath(pDocument), szFullPath))
      {
         /// [FOUND] Set result and abort
         iOutput = pIterator->iIndex;
         break;
      }
   }

   // Cleanup and return TRUE if found
   deleteListIterator(pIterator);
   return (iOutput != -1);
}
예제 #7
0
파일: room_reset.c 프로젝트: KaSt/nereamud
//
// Perform resetRun on all the reset commands in the list, using
// initiator and initiator_type
void resetRunOn(LIST *list, void *initiator, int initiator_type, 
		const char *locale) {
  if(listSize(list) > 0) {
    LIST_ITERATOR *list_i = newListIterator(list);
    RESET_DATA     *reset = NULL;
    ITERATE_LIST(reset, list_i)
      resetRun(reset, initiator, initiator_type, locale);
    deleteListIterator(list_i);
  }
}
예제 #8
0
파일: handler.c 프로젝트: KaSt/nereamud
void obj_unexist(OBJ_DATA *obj) {
  // also unexist all contents
  if(listSize(objGetContents(obj)) > 0) {
    LIST_ITERATOR *cont_i = newListIterator(objGetContents(obj));
    OBJ_DATA *cont = NULL;
    ITERATE_LIST(cont, cont_i)
      obj_unexist(cont);
    deleteListIterator(cont_i);
  }

  propertyTableRemove(obj_table, objGetUID(obj));
}
예제 #9
0
파일: handler.c 프로젝트: KaSt/nereamud
void obj_exist(OBJ_DATA *obj) {
  propertyTablePut(obj_table, obj);

  // also add all contents
  if(listSize(objGetContents(obj)) > 0) {
    LIST_ITERATOR *cont_i = newListIterator(objGetContents(obj));
    OBJ_DATA *cont = NULL;
    ITERATE_LIST(cont, cont_i)
      obj_exist(cont);
    deleteListIterator(cont_i);
  }
}
예제 #10
0
파일: socket.c 프로젝트: KaSt/nereamud
void output_handler() {
  LIST_ITERATOR *sock_i = newListIterator(socket_list);
  SOCKET_DATA     *sock = NULL; 

  ITERATE_LIST(sock, sock_i) {
    /* if the player quits or get's disconnected */
    if(sock->closed)
      continue;
    
    /* Send all new data to the socket and close it if any errors occour */
    if (!flush_output(sock))
      close_socket(sock, FALSE);
  } deleteListIterator(sock_i);
}
예제 #11
0
파일: room_reset.c 프로젝트: KaSt/nereamud
//
// run all of the resets for a specified room
void do_resets(ROOM_DATA *room) {
  // first apply all of our prototype resets
  LIST            *protos = parse_keywords(roomGetPrototypes(room));
  LIST_ITERATOR  *proto_i = newListIterator(protos);
  char             *proto = NULL;
  RESET_LIST        *list = NULL;

  // try to run each parent reset, and finally our own
  ITERATE_LIST(proto, proto_i) {
    if((list = worldGetType(gameworld, "reset", proto)) != NULL)
      resetRunOn(resetListGetResets(list), room, INITIATOR_ROOM, get_key_locale(proto));
  } deleteListIterator(proto_i);
  deleteListWith(protos, free);
}
예제 #12
0
파일: pyroom2.c 프로젝트: avidal/nakedmud
static PyObject *
PyRoom_getobjs(PyRoom *self, PyObject *args) {
  ROOM_DATA *room = worldGetRoom(gameworld, self->vnum);
  if(room == NULL)
    return NULL;
  else {
    LIST_ITERATOR *obj_i = newListIterator(roomGetContents(room));
    PyObject *list = PyList_New(0);
    OBJ_DATA *obj;

    // for each obj in the room list, add him to a Python list
    ITERATE_LIST(obj, obj_i)
      PyList_Append(list, newPyObj(obj));
    deleteListIterator(obj_i);
    return Py_BuildValue("O", list);
  }
}
예제 #13
0
파일: pyroom2.c 프로젝트: avidal/nakedmud
static PyObject *
PyRoom_getchars(PyRoom *self, PyObject *args) {
  ROOM_DATA *room = worldGetRoom(gameworld, self->vnum);
  if(room == NULL)
    return NULL;
  else {
    LIST_ITERATOR *char_i = newListIterator(roomGetCharacters(room));
    PyObject *list = PyList_New(0);
    CHAR_DATA *ch;

    // for each char in the room list, add him to a Python list
    ITERATE_LIST(ch, char_i)
      PyList_Append(list, newPyChar(ch));
    deleteListIterator(char_i);
    return Py_BuildValue("O", list);
  }
}
예제 #14
0
파일: room_reset.c 프로젝트: KaSt/nereamud
//
// zone reset hook. Whenever a zone is reset, apply all of its reset rules for
// each room in the zone.
void zone_reset_hook(const char *info) {
  char  *zone_key = NULL;
  hookParseInfo(info, &zone_key);
  ZONE_DATA *zone = worldGetZone(gameworld, zone_key);

  LIST_ITERATOR *res_i = newListIterator(zoneGetResettable(zone));
  char           *name = NULL;
  const char   *locale = zone_key;
  ROOM_DATA      *room = NULL;
  ITERATE_LIST(name, res_i) {
    if((room = worldGetRoom(gameworld, get_fullkey(name, locale))) != NULL) {
      do_resets(room);
    }
  } deleteListIterator(res_i);

  // garbage collection
  free(zone_key);
}
예제 #15
0
파일: socket.c 프로젝트: KaSt/nereamud
void recycle_sockets()
{
  SOCKET_DATA *dsock;
  LIST_ITERATOR *sock_i = newListIterator(socket_list);

  ITERATE_LIST(dsock, sock_i) {
    if (dsock->lookup_status != TSTATE_CLOSED) 
      continue;

    /* remove the socket from the main list */
    listRemove(socket_list, dsock);
    propertyTableRemove(sock_table, dsock->uid);

    /* close the socket */
    close(dsock->control);

    /* stop compression */
    compressEnd(dsock, dsock->compressing, TRUE);

    /* delete the socket from memory */
    deleteSocket(dsock);
  } deleteListIterator(sock_i);
}
예제 #16
0
파일: handler.c 프로젝트: KaSt/nereamud
void obj_to_game(OBJ_DATA *obj) {
  if(setIn(object_set, obj))
    return;

  // property table, for lookup by python
  if(!obj_exists(obj))
    obj_exist(obj);

  // set and list storage, for objects physically 'in' the game
  listPut(object_list, obj);
  setPut(object_set, obj);

  // execute all of our to_game hooks
  hookRun("obj_to_game", hookBuildInfo("obj", obj));

  // also add all contents
  if(listSize(objGetContents(obj)) > 0) {
    LIST_ITERATOR *cont_i = newListIterator(objGetContents(obj));
    OBJ_DATA *cont = NULL;
    ITERATE_LIST(cont, cont_i)
      obj_to_game(cont);
    deleteListIterator(cont_i);
  }
}
예제 #17
0
파일: trighooks.c 프로젝트: KaSt/nereamud
//
// generalized function for setting up a dictionary and running a trigger. The
// common types of variables can be supplied in the function. Additional ones
// can be added in the optional list, which must be deleted after use
void gen_do_trig(TRIGGER_DATA *trig, 
		 void *me, int me_type, CHAR_DATA *ch, OBJ_DATA *obj,
		 ROOM_DATA *room, EXIT_DATA *exit, const char *command,
		 const char *arg, LIST *optional) {
  // make our basic dictionary, and fill it up with these new variables
  PyObject *dict = restricted_script_dict();
  LIST *varnames = newList(); 
  // now, import all of our variables
  if(command) {
    PyObject *pycmd = PyString_FromString(command);
    PyDict_SetItemString(dict, "cmd", pycmd);
    listPut(varnames, strdup("cmd"));
    Py_DECREF(pycmd);
  }
  if(arg) {
    PyObject *pyarg = PyString_FromString(arg);
    PyDict_SetItemString(dict, "arg", pyarg);
    listPut(varnames, strdup("arg"));
    Py_DECREF(pyarg);
  }
  if(ch) {
    PyObject *pych = charGetPyForm(ch);
    PyDict_SetItemString(dict, "ch", pych);
    listPut(varnames, strdup("ch"));
    Py_DECREF(pych);
  }
  if(room) {
    PyObject *pyroom = roomGetPyForm(room);
    PyDict_SetItemString(dict, "room", pyroom);
    listPut(varnames, strdup("room"));
    Py_DECREF(pyroom);
  }    
  if(obj) {
    PyObject *pyobj = objGetPyForm(obj);
    PyDict_SetItemString(dict, "obj", pyobj);
    listPut(varnames, strdup("obj"));
    Py_DECREF(pyobj);
  }
  if(exit) {
    PyObject *pyexit = newPyExit(exit);
    PyDict_SetItemString(dict, "ex", pyexit);
    listPut(varnames, strdup("ex"));
    Py_DECREF(pyexit);
  }

  // add the thing the trigger is attached to
  if(me) {
    PyObject *pyme = NULL;
    switch(me_type) {
    case TRIGVAR_CHAR:  pyme = charGetPyForm(me); break;
    case TRIGVAR_OBJ:   pyme = objGetPyForm(me);  break;
    case TRIGVAR_ROOM:  pyme = roomGetPyForm(me); break;
    }
    PyDict_SetItemString(dict, "me", pyme);
    listPut(varnames, strdup("me"));
    Py_DECREF(pyme);
  }

  // now, add any optional variables
  if(optional) {
    LIST_ITERATOR *opt_i = newListIterator(optional);
    OPT_VAR         *opt = NULL;
    PyObject      *pyopt = NULL;
    ITERATE_LIST(opt, opt_i) {
      pyopt = NULL;
      switch(opt->type) {
      case TRIGVAR_CHAR:  pyopt = charGetPyForm(opt->data); break;
      case TRIGVAR_OBJ:   pyopt = objGetPyForm(opt->data);  break;
      case TRIGVAR_ROOM:  pyopt = roomGetPyForm(opt->data); break;
      }
      PyDict_SetItemString(dict, opt->name, pyopt);
      listPut(varnames, strdup(opt->name));
      Py_XDECREF(pyopt);
    } deleteListIterator(opt_i);
  }
예제 #18
0
파일: socket.c 프로젝트: KaSt/nereamud
void input_handler() {
  LIST_ITERATOR *sock_i = newListIterator(socket_list);
  SOCKET_DATA     *sock = NULL; 

  ITERATE_LIST(sock, sock_i) {
    // Close sockects we are unable to read from, or if we have no handler
    // to take in input
    if ((FD_ISSET(sock->control, &rFd) && !read_from_socket(sock)) ||
	listSize(sock->input_handlers) == 0) {
      close_socket(sock, FALSE);
      continue;
    }

    /* Ok, check for a new command */
    next_cmd_from_buffer(sock);
    
    // are we idling?
    if(!sock->cmd_read)
      sock->idle +=  1.0 / PULSES_PER_SECOND;
    /* Is there a new command pending ? */
    else if (sock->cmd_read) {
      sock->idle = 0.0;
      IH_PAIR *pair = listGet(sock->input_handlers, 0);
      if(pair->python == FALSE) {
	void (* handler)(SOCKET_DATA *, char *) = pair->handler;
	char *cmddup = strdup(bufferString(sock->next_command));
	handler(sock, cmddup);
	free(cmddup);
      }
      else {
	PyObject *arglist = Py_BuildValue("Os", socketGetPyFormBorrowed(sock),
					  bufferString(sock->next_command));
	PyObject *retval  = PyEval_CallObject(pair->handler, arglist);

	// check for an error:
	if(retval == NULL)
	  log_pyerr("Error with a Python input handler");
	
	// garbage collection
	Py_XDECREF(retval);
	Py_XDECREF(arglist);
      }

      // append our last command to the command history. History buffer is
      // 100 commands, so pop off the earliest command if we're going over
      listPut(sock->command_hist, strdup(bufferString(sock->next_command)));
      if(listSize(sock->command_hist) > 100)
	free(listRemoveNum(sock->command_hist, 100));
      bufferClear(sock->next_command);

      // we save whether or not we read a command until our next call to
      // input_handler(), at which time it is reset to FALSE if we didn't read
      // sock->cmd_read = FALSE;
    }

#ifdef MODULE_ALIAS
    // ACK!! this is so yucky, but I can't think of a better way to do it...
    // if this command was put in place by an alias, decrement the alias_queue
    // counter by one. This counter is in place mainly so aliases do not end
    // up calling eachother and making us get stuck in an infinite loop.
    if(sock->player) {
      int alias_queue = charGetAliasesQueued(sock->player);
      if(alias_queue > 0)
	charSetAliasesQueued(sock->player, --alias_queue);
    }
#endif
  } deleteListIterator(sock_i);
}
예제 #19
0
파일: parse.c 프로젝트: KaSt/nereamud
//
// Tries to apply a token to args, to parse something out. Returns a PARSE_VAR
// if the token's usage resulted in the creation of a variable. If an error was
// encountered, make this apparent by setting the value of the variable at error
PARSE_VAR *use_one_parse_token(CHAR_DATA *looker, PARSE_TOKEN *tok, 
			       char **args, bool *error, char *err_buf) {
  char buf[SMALL_BUFFER];
  PARSE_VAR  *var = NULL;
  char       *arg = *args;

  // skip over any leading spaces we might have
  while(isspace(*arg))
    arg++;

  switch(tok->type) {
  case PARSE_TOKEN_MULTI: {
    // make a proxy error value and error buf so we don't accidentally fill
    // these up when it turns out we find something on a var past the first
    bool multi_err = FALSE;
    char multi_err_buf[SMALL_BUFFER] = "";

    // go through all of our possible types until we find something
    LIST_ITERATOR *multi_i = newListIterator(tok->token_list);
    PARSE_TOKEN      *mtok = NULL;
    bool multiple_possible = FALSE;
    ITERATE_LIST(mtok, multi_i) {
      if(mtok->all_ok)
	multiple_possible = TRUE;
      var = use_one_parse_token(looker, mtok, &arg, &multi_err, multi_err_buf);
      // reset our error value for the next pass at it...
      if(var == NULL)
	multi_err = FALSE;
      // found something! Disambiguate the type
      else {
	switch(mtok->type) {
	case PARSE_TOKEN_CHAR:    var->disambiguated_type = PARSE_CHAR;   break;
	case PARSE_TOKEN_ROOM:    var->disambiguated_type = PARSE_ROOM;   break;
	case PARSE_TOKEN_EXIT:    var->disambiguated_type = PARSE_EXIT;   break;
	case PARSE_TOKEN_OBJ:     var->disambiguated_type = PARSE_OBJ;    break;
	case PARSE_TOKEN_WORD:    var->disambiguated_type = PARSE_STRING; break;
	case PARSE_TOKEN_STRING:  var->disambiguated_type = PARSE_STRING; break;
	case PARSE_TOKEN_INT:     var->disambiguated_type = PARSE_INT;    break;
	case PARSE_TOKEN_DOUBLE:  var->disambiguated_type = PARSE_DOUBLE; break;
	case PARSE_TOKEN_BOOL:    var->disambiguated_type = PARSE_BOOL;   break;
	}
	// break out of the loop... we found something
	break;
      }
    } deleteListIterator(multi_i);

    // did we manage not to find something?
    if(var != NULL)
      var->multiple_possible = multiple_possible;
    else {
      one_arg(arg, buf); // get the first arg, for reporting...
      sprintf(err_buf, "Your argument '%s' was invalid or could not be found.",
	      buf);
      *error = TRUE;
    }
    break;
  }

  case PARSE_TOKEN_FLAVOR: {
    int len = strlen(tok->flavor);
    // have we found the flavor text?
    if(strncasecmp(tok->flavor, arg, len) == 0 &&
	 (arg[len] == '\0' || isspace(arg[len])))
      arg = arg + len;
    // do we need to do something about it?
    else if(!tok->flavor_optional)
      *error = TRUE;
    break;
  }

    // parse out a char value
  case PARSE_TOKEN_CHAR:
    arg = one_arg(arg, buf);
    var = use_one_parse_token_char(looker, tok, buf);
    if(var == NULL) {
      sprintf(err_buf, "The person, %s, could not be found.", buf);
      *error = TRUE;
    }
    break;

    // parse out an obj value
  case PARSE_TOKEN_OBJ:
    arg = one_arg(arg, buf);
    var = use_one_parse_token_obj(looker, tok, buf);
    if(var == NULL) {
      sprintf(err_buf, "The object, %s, could not be found.", buf);
      *error = TRUE;
    }
    break;

    // parse out a room value
  case PARSE_TOKEN_ROOM:
    arg = one_arg(arg, buf);
    var = use_one_parse_token_room(looker, tok, buf);
    if(var == NULL) {
      sprintf(err_buf, "The room, %s, could not be found.", buf);
      *error = TRUE;
    }
    break;

    // parse out an exit value
  case PARSE_TOKEN_EXIT:
    arg = one_arg(arg, buf);
    var = use_one_parse_token_exit(looker, tok, buf);
    if(var == NULL) {
      sprintf(err_buf, "The direction, %s, could not be found.", buf);
      *error = TRUE;
    }
    break;

    // try to parse out a double value
  case PARSE_TOKEN_DOUBLE:
    arg = one_arg(arg, buf);
    var = use_one_parse_token_double(buf);
    if(var == NULL) {
      sprintf(err_buf, "'%s' is not a decimal value.", buf);
      *error = TRUE;
    }
    break;

    // try to parse out an integer value
  case PARSE_TOKEN_INT:
    arg = one_arg(arg, buf);
    var = use_one_parse_token_int(buf);
    if(var == NULL) {
      sprintf(err_buf, "'%s' is not a%s number.", buf,
	      (string_is_double(buf) ? "n acceptable" : ""));
      *error = TRUE;
    }
    break;

    // try to parse out a boolean value
  case PARSE_TOKEN_BOOL:
    arg = one_arg(arg, buf);
    var = use_one_parse_token_bool(buf);
    if(var == NULL) {
      sprintf(err_buf, "'%s' is not a yes/no value.", buf);
      *error = TRUE;
    }
    break;

    // parse out a single word
  case PARSE_TOKEN_WORD: {
    var = newParseVar(PARSE_VAR_STRING);
    var->ptr_val    = arg;
    bool multi_word = FALSE;
    char multi_mark = '"';

    // are we using quotation marks to specify multiple words?
    if(*arg == '"' || *arg == '\'') {
      multi_word = TRUE;
      multi_mark = *arg;
      arg++;
      var->ptr_val = arg;
    }

    // go through arg to the next space, and delimit the word
    for(; *arg != '\0'; arg++) {
      if((multi_word && *arg == multi_mark) || (!multi_word && isspace(*arg))) {
	*arg = '\0';
	arg++;
	break;
      }
    }
    break;
  }

    // copies whatever is left
  case PARSE_TOKEN_STRING:
    var = newParseVar(PARSE_VAR_STRING);
    var->ptr_val = arg;
    // skip up the place of the arg...
    while(*arg != '\0')
      arg++;
    break;

    // since this doesn't really parse a value...
  case PARSE_TOKEN_OPTIONAL:
    break;
  }

  // up the placement of our arg if we didn't encounter an error
  if(!*error)
    *args = arg;

  return var;
}