⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 interpreter.cc

📁 Unix下的MUD客户端程序
💻 CC
📖 第 1 页 / 共 2 页
字号:
// a class to keep a list of commands and execute them one at a time#include "mcl.h"#include "cui.h"#include "Option.h"#include "MessageWindow.h"#include "Interpreter.h"#include "Shell.h"#include "Action.h"#include "Alias.h"#include "Chat.h"#include "Session.h"Interpreter interpreter;extern MUD *lastMud;bool actions_disabled, aliases_disabled, macros_disabled;// Pick off one argument, optionally smashing case and place it in buf// Eat whitespace, respect "" and ''const char *one_argument (const char *argument, char *buf, bool smash_case) {    char end;        while(isspace(*argument))        argument++;    if (*argument == '\'' || *argument == '\"')        end = *argument++;    else        end = NUL;    while(*argument && (end ? *argument != end : !isspace(*argument)))  {        *buf++ = smash_case ? tolower(*argument) : *argument;        argument++;    }    *buf++ = NUL;    if (*argument && end)        argument++;    while(isspace(*argument))        argument++;    return argument;}void Interpreter::execute() {    int count = 0;        while(commands.count())    {        String line = *commands[0];        commands.remove(commands[0]);                if (++count > 100)        {            output->printf ("Recursing alias? Next command would be \"%s\".\n", (const char*)line);            while(commands.count())                commands.remove(commands[0]);            break;        }        char out_buf[MAX_INPUT_BUF];        const char *t = out_buf;        if (!(embed_interp->run_quietly("sys/send", line, out_buf)))            t = line;                if (t[0] == commandCharacter)            mclCommand (t+ 1);        else if (currentSession) {            currentSession->writeMUD(t);        }        else            status->setf ("You are not connected. Use Alt-O to connect to a MUD.");    }}// Legal speedwalk stringsconst char legal_standard_speedwalk[] = "nsewud";const char legal_extended_speedwalk[] = "nsewudhjkl";#define MAX_SPEEDWALK_REPEAT 99 // just in case someone typos '244n'#define ADD2(s) *pc2++ = s[0]; *pc2++ = s[1];// Expand possible speedwalk stringvoid Interpreter::expandSpeedwalk(const char *s, int flags){    const char *pc;    bool try_speedwalk = config->getOption(opt_speedwalk);    const char *legal_speedwalk;        if (s[0] == config->getOption(opt_speedwalk_character)) {        try_speedwalk = true;        legal_speedwalk = legal_extended_speedwalk;        s++;    } else        legal_speedwalk = legal_standard_speedwalk;        if (try_speedwalk)    {        for (pc = s; *pc; pc++)            if (!isdigit(*pc) && !strchr (legal_speedwalk, *pc))                break;                // the harcoded "News" will probably be a config option	        if (!*pc && strcasecmp(s,"news") && (strchr(legal_speedwalk, *(pc-1)))) // it IS a speedwalk string        {            int repeat = 0;                        for (pc = s; *pc; pc++)                if (isdigit(*pc))                    repeat = 10 * repeat + *pc - '0';                else                {                    repeat = max(1,min(MAX_SPEEDWALK_REPEAT,repeat));                    char *walk = (char*)alloca(repeat*3+1);                                        char *pc2 = walk;                                        while(repeat--)                    {                        switch (*pc) {                        case 'h':                            ADD2("nw"); break;                        case 'j':                            ADD2("ne"); break;                        case 'k':                            ADD2("sw"); break;                        case 'l':                            ADD2("se"); break;                                                    default:                            *pc2++ = *pc;                        }						*pc2++ = NUL;						add (walk, EXPAND_NONE);					}                                        repeat = 0;                }                        return;        }    }    add(s,flags & ~EXPAND_SPEEDWALK);}const char* Interpreter::expandVariables(const char *s) {    if (!strchr(s, '%'))        return s;    else {                StaticBuffer buf(MAX_MUD_BUF);        char *out;                for (out = buf; *s; s++)  {            struct tm *t = NULL;                        if (*s == '%' && *(s+1))            {                switch(*++s)                {                    // @@ change this to snprintf                case 'h': // remote hostname                    out += sprintf(out, "%s", currentSession ? currentSession->mud.getHostname() : "");                    break;                                    case 'p': // remote portname                    out += sprintf(out, "%d", currentSession ? currentSession->mud.getPort() : 0);                    break;                                    case 'n':                    out += sprintf(out, "%s", currentSession ?~ currentSession->mud.name : "");                    break;                                    case 'P':                    out += sprintf(out, "%d", currentSession ? currentSession->getLocalPort(): 0);                    break;                                    case 'f': // mudFTP port                    out += sprintf(out, "%d", currentSession ? currentSession->mud.getPort() + 6 : 0);                    break;                                        // strftime uses some slightly different characters                    #define TIME(my_char,their_char) case my_char: \    { \    char fmt[3] = { '%', their_char, NUL }; \    if (!t) t= localtime(&current_time); \    out += strftime(out, (buf+MAX_MUD_BUF)-out, fmt, t); \    break; \    }                                        TIME('H', 'H'); // Hour                    TIME('m', 'M'); // Minute                    TIME('M', 'b'); // Abbreviated month name                    TIME('w', 'a'); // Abbreviated weekday name                    TIME('t', 'c'); // Preferred date and time representation                    TIME('d', 'd'); // Day of the month                    TIME('y', 'y'); // Year (last two digits)                    TIME('Y', 'Y'); // Full year                    TIME('o', 'm'); // month number, 01-11                                                        case '%': // Just one %                    out += sprintf(out, "%%");                    break;                                        // Need something like username/password here                                    default:                    *out++ = *s;                }            }            else                *out++ = *s;                    }                *out = NUL;        return buf;    }}// %variables// speedwalk (can not recurse)// aliases (can recurse)// ;// Results from aliases: 2,3// Command// Expand stuff in this line before it gets sent to the MUDvoid Interpreter::add(const char *s, int flags, bool back) {    if (s[0] == config->getOption(opt_escape_character)) { // short circuit        if (back)            commands.insert(new String(s+1));        else            commands.append(new String(s+1));        return;    }    if (flags & EXPAND_VARIABLES) {        s = expandVariables(s);        flags = flags & ~EXPAND_VARIABLES;    }    if (flags & EXPAND_ALIASES)        expandAliases(s, flags);    else if (flags & EXPAND_SPEEDWALK)        expandSpeedwalk(s, flags);    else if (flags & EXPAND_SEMICOLON)        expandSemicolon(s, flags);    else if (s[0] == commandCharacter && isdigit(s[1])) {        char count[MAX_MUD_BUF];        s = one_argument(s+1, count, false);        int n = atoi(count);        if (n > 0 && n < 100) {            while(n-- > 0)                add(s, EXPAND_ALL);        } else            status->setf("Repeat count must be between 0 and 100");        return;    } else {        if (back)            commands.insert(new String(s));        else            commands.append(new String(s));    }}void Interpreter::expandSemicolon(const char *s, int flags) {    if ((strchr(s, ';'))) {        char buf[strlen(s)+1];        char *out;        bool got_semicolon = false;        for (;*s;) {                        for (out = buf; *s; s++ ) {                if (*s == '\\' && s[1] == ';') { // escaped semicolon                    *out++ = ';';                    s++;                }  else if (*s == ';') {                    got_semicolon = true;                    break;                }                else                    *out++ = *s;            }            // Deleting spaces just before the ;            while (out > buf && isspace(out[-1]))                out--;            *out = NUL;            // Skip the semicolon, if there was one            if (*s == ';')                s++;                            // Deleting space just after the ; if appropriate            while(*s && isspace(*s))                s++;            if (got_semicolon)                add(buf, EXPAND_ALL); // unconditionally expand everything so aliases are expanded with their contents            else // escaped semicolons only                add(buf, flags & ~ EXPAND_SEMICOLON);        }    }    else        add(s, flags & ~EXPAND_SEMICOLON);}// ought to move some of this stuff to separate functions, this function is growing LARGEvoid Interpreter::expandAliases(const char* s, int flags) {        // Isolate alias name        if (!s[0]) // special case, unfortunately        add("", EXPAND_NONE);    else {        int count;        char name[MAX_ALIAS_BUFFER];        char buf[MAX_MUD_BUF];                if (embed_interp->run_quietly("sys/command", s, buf)) {            if (!buf[0]) // command cancelled                return;            s = buf;        }                // Allow e.g. @ or % to be valid alias names without requiring a space        // afterwards        if (!isalpha(s[0])) {            count = 1;            name[0] = s[0];            name[1] = NUL;            count = 1;        } else            sscanf(s, "%s %n", name, &count); // skip spaces.. will this break anything?                // Easy way to add a command        if (embed_interp->run_quietly(Sprintf("cmd_%s", name),s+count, buf, true))            return; // command executed, don't send this anywhere                Alias *a = NULL;                if (!aliases_disabled)            a = currentSession ? currentSession->mud.findAlias(name) : globalMUD.findAlias(name);        if (a) {            char out_buf[MAX_MUD_BUF];            a->expand(s+count, out_buf);            add(out_buf, EXPAND_ALL); // Expand everything again        }					        else // no expansion ocurred            add(s, flags & ~ EXPAND_ALIASES);    }}// Execute a mcl Commandvoid Interpreter::mclCommand (const char *s){    char cmd[256];        s = one_argument(s, cmd, true);        if (!strcmp(cmd, "quit"))        mclFinished = true;        else if (!strcmp(cmd, "echo"))    {        output->printf("%s\n", s);    }    else if (!strcmp(cmd, "status"))    {        status->setf("%s", s);    }    else if (!strcmp(cmd, "bell"))    {        screen->flash();    }    else if (!strcmp(cmd, "exec"))    {        int w = 80, h=10, x=0, y=3, t=10;        int c;        String res;                OptionParser o(s, "w:h:x:y:t:");                while((c = o.nextOption(res)))            switch (c)            {            case 'w':                w  = atoi(res);                break;                            case 'h':                h = atoi(res);                break;                            case 'x':                x = atoi(res);                break;                            case 'y':                y = atoi(res);                break;                            case 't':                t = atoi(res);                break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -