/* Copyright (c) 1992 by David Moore. All rights reserved. */ /* builtins.c,v 2.6 1995/06/13 00:22:33 dmoore Exp */ #include "config.h" #include <stdlib.h> #include <string.h> #include <ctype.h> #include "db.h" #include "params.h" #include "buffer.h" #include "externs.h" #include "builtins.h" /* Generated by mkbuiltin.sh */ /* Call everyone with the first arg, the second arg, and the whole line. */ typedef void (*comm_func)(const dbref, const char*, const char *, const char*); struct command { const char *name; int min_match; comm_func func; }; static struct command builtins[] = { #include "builtintab.h" /* Generated by mkcommandtab.sh */ }; static int commandcmp(const void *k, const void *d) { const char *key = k; const struct command *data = d; /* Make uncase sensitive. */ return muck_strnicmp(key, data->name, data->min_match); } static comm_func lookup_command(const char *key) { struct command *result; result = bsearch(key, builtins, sizeof(builtins)/sizeof(struct command), sizeof(struct command), commandcmp); if (result && muck_strprefix(result->name, key)) { return result->func; } else { return 0; } } /* This routine expands a leading /"/ or /:/ into /say / and /pose /. Always returns a pointer into a static buffer. */ static char *fix_cookies(const char *str) { static Buffer buf; switch (*str) { #include "cookies.h" /* Generated from builtins/cookies. */ default: Bufcpy(&buf, str); break; } return Buftext(&buf); } /* Returns a pointer to a static buffer which contains a copy of the everything after the first word of the command. */ static char *get_full_args(const char *command) { static Buffer buf; const char *p = command; while (*p && !isspace(*p)) p++; if (*p) p++; Bufcpy(&buf, p); return Buftext(&buf); } /* Splits a string into three parts. The command (first word), and two arguments (seperated by '='). Sets arg1 and arg2 to point to the appropriate places. Works entirely within the string passed via command. */ static void split_args(char *command, char **arg1, char **arg2) { char *p = command; char *q; *arg1 = ""; *arg2 = ""; if (!p || !*p) return; /* Skip to first space, and truncate off as command. */ while (*p && !isspace(*p)) p++; if (!*p) return; *p++ = '\0'; while (*p && isspace(*p)) p++; /* Eat some spaces. */ *arg1 = p; /* Mark arg1 start. */ /* Skip to '=' and truncate off arg1. */ while (*p && (*p != ARG_DELIMITER)) p++; q = p; if (*p) { /* There is an arg2. */ *p++ = '\0'; while (*p && isspace(*p)) p++; /* eat some spaces. */ *arg2 = p; /* Mark arg2 start. */ } /* Strip trailing spaces from arg1. */ for (q--; isspace(*q); q--) *q = '\0'; } void process_command(const dbref player, const char *comm, int comm_len) { char *command, *arg1, *arg2, *full_args; comm_func func; if (!comm) { /* Should never happen. */ log_status("FATAL: process_command was called with a null string."); panic("null string sent to process_command"); } #ifdef LOG_WIZARD_COMMANDS if (Wizard(player) && !HasFlag(player, IN_EDITOR)) { dbref loc = GetLoc(player); log_command("%u in %u:%s %s", player, player, loc, loc, HasFlag(player, IN_PROGRAM) ? " [interactive]" : "", comm); } #endif /* LOG_WIZARD_COMMANDS */ #ifdef LOG_COMMANDS if (!HasFlag(player, IN_EDITOR)) { dbref loc = GetLoc(player); log_command("%u in %u:%s %s", player, player, loc, loc, HasFlag(player, IN_PROGRAM) ? " [interactive]" : "", comm); } #endif /* LOG_COMMANDS */ #ifdef LOG_LAST_COMMAND if (!HasFlag(player, IN_EDITOR)) { dbref loc = GetLoc(player); log_last_command("%u in %u:%s %s", player, player, GetOwner(loc), loc, HasFlag(player, IN_PROGRAM) ? " [interactive]" : "", comm); } #endif /* LOG_LAST_COMMAND */ if (HasFlag(player, IN_EDITOR)) { editor(player, comm, comm_len); return; } if (HasFlag(player, IN_PROGRAM)) { interactive(player, comm); return; } /* Eat any leading white space. */ while (*comm && isspace(*comm)) comm++; command = fix_cookies(comm); if (try_move(player, command)) { /* Exact exit match. */ return; } full_args = get_full_args(command); split_args(command, &arg1, &arg2); func = lookup_command(command); if (func) { /* Command is a known builtin. */ func(player, arg1, arg2, full_args); return; } /* Only get here if we couldn't match an exit, and it's not builtin. */ notify(player, "Huh? (Type \"help\" for help.)"); #ifdef LOG_FAILED_COMMANDS if (!controls(player, GetLoc(player), 0)) { dbref loc = GetLoc(player); dbref owner = GetOwner(loc); log_status("HUH: from %u in %u[%u]: %s", player, player, loc, loc, owner, owner, comm); } #endif /* LOG_FAILED_COMMANDS */ }