00001 #include <string.h>
00002 #include <stdlib.h>
00003 #include <assert.h>
00004 #include <neuro/stringtable.h>
00005 #include <neuro/cmdhandler.h>
00006 #include "nsutil.h"
00007 #include "nsnet.h"
00008 #include "nsd.h"
00009
00010 #define MAXTOKENS 256
00011
00012 struct CommandHandler {
00013 struct StringTable *cmds, *clients;
00014 struct ClientState *curClient;
00015 };
00016
00017 struct CommandEntry {
00018 void (*func)(struct CommandHandler *ch, int cliInd);
00019 };
00020
00021 struct ClientState {
00022 char *curline;
00023 int tokenCount;
00024 char *tokens[MAXTOKENS];
00025 };
00026
00027 struct CommandHandler *newCommandHandler(void)
00028 {
00029 struct CommandHandler *ch;
00030 ch = calloc(sizeof(struct CommandHandler), 1);
00031 ch->cmds = newStringTable();
00032 ch->clients = newStringTable();
00033 return ch;
00034 }
00035
00036 void freeValues(struct StringTable *st, const char *key, void *val, void *udata)
00037 {
00038 free(val);
00039 }
00040
00041 void freeCS(struct StringTable *st, const char *key, void *val, void *udata)
00042 {
00043 struct ClientState *cs = (struct ClientState *) val;
00044 if (cs->curline != NULL) {
00045 free(cs->curline);
00046 cs->curline = NULL;
00047 }
00048 }
00049
00050 void freeCommandHandler(struct CommandHandler *ch)
00051 {
00052 allStrings(ch->cmds, freeValues, NULL);
00053 allStrings(ch->clients, freeCS, NULL);
00054 allStrings(ch->clients, freeValues, NULL);
00055 freeStringTable(ch->cmds);
00056 freeStringTable(ch->clients);
00057 ch->cmds = ch->clients = NULL;
00058 free(ch);
00059 }
00060
00061 static const char *indexToStr(int cliIndex)
00062 {
00063 static char buf[80];
00064 sprintf(buf, "%d", cliIndex);
00065 return buf;
00066 }
00067
00068
00069 void newClientStarted(struct CommandHandler *ch, int cliIndex)
00070 {
00071 struct ClientState *cs;
00072 cs = calloc(sizeof(struct ClientState), 1);
00073 putString(ch->clients, indexToStr(cliIndex), cs);
00074 }
00075
00076
00077 void enregisterCommand(struct CommandHandler *ch, const char *cmd, void (*func)(struct CommandHandler *ch, int))
00078 {
00079 struct CommandEntry *ce;
00080 ce = calloc(sizeof(struct CommandEntry), 1);
00081 ce->func = func;
00082 putString(ch->cmds, cmd, ce);
00083 }
00084
00085 static void replaceCurline(struct ClientState *cs, const char *line)
00086 {
00087 int linelen = strlen(line);
00088 if (cs->curline)
00089 free(cs->curline);
00090 cs->curline = calloc(strlen(line)+2, 1);
00091 memcpy(cs->curline, line, linelen);
00092 cs->curline[linelen] = ' ';
00093 cs->curline[linelen+1] = 0;
00094 }
00095
00096 static void addToken(struct ClientState *cs, char *tok)
00097 {
00098 int i, j=0;
00099 assert(cs->tokenCount < MAXTOKENS);
00100 for (i = 0; tok[i]; i += 1) {
00101 if (tok[i] == '\\' && tok[i+1])
00102 i += 1;
00103 tok[j] = tok[i];
00104 j += 1;
00105 }
00106 tok[j] = 0;
00107 cs->tokens[cs->tokenCount] = tok;
00108 cs->tokenCount += 1;
00109 }
00110
00111 static void tokenizeLine(struct ClientState *cs)
00112 {
00113 int i;
00114 int inQuote=0;
00115 int inBackslash=0;
00116 int inSpace=1;
00117 int startPos = 0;
00118 memset(cs->tokens, 0, sizeof(cs->tokens));
00119 cs->tokenCount = 0;
00120 for (i = 0; cs->curline[i]; i += 1) {
00121 char c = cs->curline[i];
00122 if (inBackslash) {
00123 inBackslash = 0;
00124 continue;
00125 }
00126 if (c == '\\') {
00127 if (inSpace) {
00128 inSpace = 0;
00129 startPos = i;
00130 }
00131 inBackslash = 1;
00132 continue;
00133 }
00134 if (c == '"') {
00135 if (inQuote) {
00136 inQuote = 0;
00137 inSpace = 1;
00138 cs->curline[i] = 0;
00139 addToken(cs, cs->curline+startPos);
00140 continue;
00141 } else {
00142 if (cs->curline[i+1]) {
00143 startPos = i+1;
00144 inSpace = 0;
00145 inQuote = 1;
00146 }
00147 continue;
00148 }
00149 }
00150 if (c == '\r' || c == '\n' || c == '\t' || c == ' '
00151 || cs->curline[i+1] == 0) {
00152 if (inQuote) continue;
00153 if (inSpace) continue;
00154 if (c == '\r' || c == '\n' || c == '\t' || c == ' ')
00155 cs->curline[i] = 0;
00156 addToken(cs, cs->curline+startPos);
00157 inSpace = 1;
00158 continue;
00159 }
00160 if (inSpace) {
00161 startPos = i;
00162 inSpace = 0;
00163 continue;
00164 }
00165 }
00166 }
00167
00168 void handleLine(struct CommandHandler *ch, const char *line, int cliIndex)
00169 {
00170 struct ClientState *cs;
00171 struct CommandEntry *ce;
00172 cs = findString(ch->clients, indexToStr(cliIndex));
00173 assert(cs != NULL);
00174 replaceCurline(cs, line);
00175 tokenizeLine(cs);
00176 if (0)
00177 { int i;
00178 for (i = 0; i < cs->tokenCount; ++i)
00179 printf("%d: <%s>\n", i, cs->tokens[i]);
00180 }
00181 ce = findString(ch->cmds, cs->tokens[0]);
00182 if (ce == NULL)
00183 ce = findString(ch->cmds, "unknown");
00184 if (ce) {
00185 ch->curClient = cs;
00186 ce->func(ch, cliIndex);
00187 ch->curClient = NULL;
00188 }
00189 }
00190
00191
00192 int fetchIntParameters(struct CommandHandler *ch, int *vals, int num)
00193 {
00194 int i;
00195 for (i = 0; i < num; ++i)
00196 vals[i] = atoi(ch->curClient->tokens[i+1]);
00197 return 0;
00198 }
00199
00200 const char *fetchCommandName(struct CommandHandler *ch)
00201 {
00202 return ch->curClient->tokens[0];
00203 }
00204
00205 const char *fetchStringParameter(struct CommandHandler *ch, int which)
00206 {
00207 return ch->curClient->tokens[which+1];
00208 }
00209