Replace shift with a great variadic function
I am disappointed in the lack of compiler attributes for type-checking variadic functions.master
parent
05fe4ece20
commit
fc113c8ef9
218
handle.c
218
handle.c
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
|
||||
#include <err.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -32,15 +33,8 @@ static int color(const char *s) {
|
|||
return (x == 1) ? 0 : x;
|
||||
}
|
||||
|
||||
typedef void (*Handler)(char *prefix, char *params);
|
||||
|
||||
static char *prift(char **prefix) {
|
||||
return strsep(prefix, "!@");
|
||||
}
|
||||
|
||||
static char *shift(char **params) {
|
||||
static char *paramField(char **params) {
|
||||
char *rest = *params;
|
||||
if (!rest) errx(EX_PROTOCOL, "unexpected eol");
|
||||
if (rest[0] == ':') {
|
||||
*params = NULL;
|
||||
return &rest[1];
|
||||
|
@ -48,24 +42,59 @@ static char *shift(char **params) {
|
|||
return strsep(params, " ");
|
||||
}
|
||||
|
||||
static void shift(
|
||||
char *prefix, char **nick, char **user, char **host,
|
||||
char *params, size_t req, size_t opt, /* (char **) */ ...
|
||||
) {
|
||||
char *field;
|
||||
if (prefix) {
|
||||
field = strsep(&prefix, "!");
|
||||
if (nick) *nick = field;
|
||||
field = strsep(&prefix, "@");
|
||||
if (user) *user = field;
|
||||
if (host) *host = prefix;
|
||||
}
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, opt);
|
||||
for (size_t i = 0; i < req; ++i) {
|
||||
if (!params) {
|
||||
va_end(ap);
|
||||
errx(EX_PROTOCOL, "%zu params required, found %zu", req, i);
|
||||
}
|
||||
field = paramField(¶ms);
|
||||
char **param = va_arg(ap, char **);
|
||||
if (param) *param = field;
|
||||
}
|
||||
for (size_t i = 0; i < opt; ++i) {
|
||||
char **param = va_arg(ap, char **);
|
||||
if (params) {
|
||||
*param = paramField(¶ms);
|
||||
} else {
|
||||
*param = NULL;
|
||||
}
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
typedef void (*Handler)(char *prefix, char *params);
|
||||
|
||||
static void handlePing(char *prefix, char *params) {
|
||||
(void)prefix;
|
||||
ircFmt("PONG %s\r\n", params);
|
||||
}
|
||||
|
||||
static void handle432(char *prefix, char *params) {
|
||||
(void)prefix;
|
||||
shift(¶ms);
|
||||
shift(¶ms);
|
||||
char *mesg = shift(¶ms);
|
||||
char *mesg;
|
||||
shift(prefix, NULL, NULL, NULL, params, 1, 0, &mesg);
|
||||
uiLog(L"You can't use that name here");
|
||||
uiFmt("Sheriff says, \"%s\"", mesg);
|
||||
uiLog(L"Type /nick <name> to choose a new one");
|
||||
}
|
||||
|
||||
static void handle001(char *prefix, char *params) {
|
||||
(void)prefix;
|
||||
char *nick = shift(¶ms);
|
||||
char *nick;
|
||||
shift(prefix, NULL, NULL, NULL, params, 1, 0, &nick);
|
||||
if (strcmp(nick, chat.nick)) {
|
||||
free(chat.nick);
|
||||
chat.nick = strdup(nick);
|
||||
|
@ -74,27 +103,23 @@ static void handle001(char *prefix, char *params) {
|
|||
}
|
||||
|
||||
static void handleJoin(char *prefix, char *params) {
|
||||
char *nick = prift(&prefix);
|
||||
char *user = prift(&prefix);
|
||||
char *chan = shift(¶ms);
|
||||
char *nick, *user, *chan;
|
||||
shift(prefix, &nick, &user, NULL, params, 1, 0, &chan);
|
||||
uiFmt(
|
||||
"\3%d%s\3 arrives in \3%d%s\3",
|
||||
color(user), nick, color(chan), chan
|
||||
);
|
||||
if (!strcmp(nick, chat.nick) && strcmp(user, chat.user)) {
|
||||
free(chat.user);
|
||||
chat.user = strdup(user);
|
||||
}
|
||||
tabTouch(nick);
|
||||
uiFmt(
|
||||
"\3%d%s\3 arrives in \3%d%s\3",
|
||||
color(user), nick, color(chan), chan
|
||||
);
|
||||
}
|
||||
|
||||
static void handlePart(char *prefix, char *params) {
|
||||
char *nick = prift(&prefix);
|
||||
char *user = prift(&prefix);
|
||||
char *chan = shift(¶ms);
|
||||
tabRemove(nick);
|
||||
if (params) {
|
||||
char *mesg = shift(¶ms);
|
||||
char *nick, *user, *chan, *mesg;
|
||||
shift(prefix, &nick, &user, NULL, params, 1, 1, &chan, &mesg);
|
||||
if (mesg) {
|
||||
uiFmt(
|
||||
"\3%d%s\3 leaves \3%d%s\3, \"%s\"",
|
||||
color(user), nick, color(chan), chan, mesg
|
||||
|
@ -105,14 +130,13 @@ static void handlePart(char *prefix, char *params) {
|
|||
color(user), nick, color(chan), chan
|
||||
);
|
||||
}
|
||||
tabRemove(nick);
|
||||
}
|
||||
|
||||
static void handleQuit(char *prefix, char *params) {
|
||||
char *nick = prift(&prefix);
|
||||
char *user = prift(&prefix);
|
||||
tabRemove(nick);
|
||||
if (params) {
|
||||
char *mesg = shift(¶ms);
|
||||
char *nick, *user, *mesg;
|
||||
shift(prefix, &nick, &user, NULL, params, 0, 1, &mesg);
|
||||
if (mesg) {
|
||||
char *quot = (mesg[0] == '"') ? "" : "\"";
|
||||
uiFmt(
|
||||
"\3%d%s\3 leaves, %s%s%s",
|
||||
|
@ -121,51 +145,51 @@ static void handleQuit(char *prefix, char *params) {
|
|||
} else {
|
||||
uiFmt("\3%d%s\3 leaves", color(user), nick);
|
||||
}
|
||||
tabRemove(nick);
|
||||
}
|
||||
|
||||
static void handleKick(char *prefix, char *params) {
|
||||
char *nick = prift(&prefix);
|
||||
char *user = prift(&prefix);
|
||||
char *chan = shift(¶ms);
|
||||
char *kick = shift(¶ms);
|
||||
char *mesg = shift(¶ms);
|
||||
char *nick, *user, *chan, *kick, *mesg;
|
||||
shift(prefix, &nick, &user, NULL, params, 2, 1, &chan, &kick, &mesg);
|
||||
if (mesg) {
|
||||
uiFmt(
|
||||
"\3%d%s\3 kicks \3%d%s\3 out of \3%d%s\3, \"%s\"",
|
||||
color(user), nick, color(kick), kick, color(chan), chan, mesg
|
||||
);
|
||||
} else {
|
||||
uiFmt(
|
||||
"\3%d%s\3 kicks \3%d%s\3 out of \3%d%s\3",
|
||||
color(user), nick, color(kick), kick, color(chan), chan
|
||||
);
|
||||
}
|
||||
tabRemove(nick);
|
||||
uiFmt(
|
||||
"\3%d%s\3 kicks \3%d%s\3 out of \3%d%s\3, \"%s\"",
|
||||
color(user), nick, color(kick), kick, color(chan), chan, mesg
|
||||
);
|
||||
}
|
||||
|
||||
static void handle332(char *prefix, char *params) {
|
||||
(void)prefix;
|
||||
shift(¶ms);
|
||||
char *chan = shift(¶ms);
|
||||
char *topic = shift(¶ms);
|
||||
urlScan(topic);
|
||||
uiTopicStr(topic);
|
||||
char *chan, *topic;
|
||||
shift(prefix, NULL, NULL, NULL, params, 3, 0, NULL, &chan, &topic);
|
||||
uiFmt(
|
||||
"The sign in \3%d%s\3 reads, \"%s\"",
|
||||
color(chan), chan, topic
|
||||
);
|
||||
urlScan(topic);
|
||||
uiTopicStr(topic);
|
||||
}
|
||||
|
||||
static void handleTopic(char *prefix, char *params) {
|
||||
char *nick = prift(&prefix);
|
||||
char *user = prift(&prefix);
|
||||
char *chan = shift(¶ms);
|
||||
char *topic = shift(¶ms);
|
||||
urlScan(topic);
|
||||
uiTopicStr(topic);
|
||||
char *nick, *user, *chan, *topic;
|
||||
shift(prefix, &nick, &user, NULL, params, 2, 0, &chan, &topic);
|
||||
uiFmt(
|
||||
"\3%d%s\3 places a new sign in \3%d%s\3, \"%s\"",
|
||||
color(user), nick, color(chan), chan, topic
|
||||
);
|
||||
urlScan(topic);
|
||||
uiTopicStr(topic);
|
||||
}
|
||||
|
||||
static void handle366(char *prefix, char *params) {
|
||||
(void)prefix;
|
||||
shift(¶ms);
|
||||
char *chan = shift(¶ms);
|
||||
char *chan;
|
||||
shift(prefix, NULL, NULL, NULL, params, 2, 0, NULL, &chan);
|
||||
ircFmt("WHO %s\r\n", chan);
|
||||
}
|
||||
|
||||
|
@ -175,14 +199,11 @@ static struct {
|
|||
} who;
|
||||
|
||||
static void handle352(char *prefix, char *params) {
|
||||
(void)prefix;
|
||||
shift(¶ms);
|
||||
shift(¶ms);
|
||||
char *user = shift(¶ms);
|
||||
shift(¶ms);
|
||||
shift(¶ms);
|
||||
char *nick = shift(¶ms);
|
||||
tabTouch(nick);
|
||||
char *user, *nick;
|
||||
shift(
|
||||
prefix, NULL, NULL, NULL,
|
||||
params, 6, 0, NULL, NULL, &user, NULL, NULL, &nick
|
||||
);
|
||||
size_t cap = sizeof(who.buf) - who.len;
|
||||
int len = snprintf(
|
||||
&who.buf[who.len], cap,
|
||||
|
@ -190,65 +211,74 @@ static void handle352(char *prefix, char *params) {
|
|||
(who.len ? ", " : ""), color(user), nick
|
||||
);
|
||||
if ((size_t)len < cap) who.len += len;
|
||||
tabTouch(nick);
|
||||
}
|
||||
|
||||
static void handle315(char *prefix, char *params) {
|
||||
(void)prefix;
|
||||
shift(¶ms);
|
||||
char *chan = shift(¶ms);
|
||||
who.len = 0;
|
||||
char *chan;
|
||||
shift(prefix, NULL, NULL, NULL, params, 2, 0, NULL, &chan);
|
||||
uiFmt(
|
||||
"In \3%d%s\3 are %s",
|
||||
color(chan), chan, who.buf
|
||||
);
|
||||
who.len = 0;
|
||||
}
|
||||
|
||||
static void handleNick(char *prefix, char *params) {
|
||||
char *prev = prift(&prefix);
|
||||
char *user = prift(&prefix);
|
||||
char *next = shift(¶ms);
|
||||
char *prev, *user, *next;
|
||||
shift(prefix, &prev, &user, NULL, params, 1, 0, &next);
|
||||
uiFmt(
|
||||
"\3%d%s\3 is now known as \3%d%s\3",
|
||||
color(user), prev, color(user), next
|
||||
);
|
||||
if (!strcmp(user, chat.user)) {
|
||||
free(chat.nick);
|
||||
chat.nick = strdup(next);
|
||||
}
|
||||
tabReplace(prev, next);
|
||||
}
|
||||
|
||||
static void handleCTCP(char *nick, char *user, char *mesg) {
|
||||
mesg = &mesg[1];
|
||||
char *ctcp = strsep(&mesg, " ");
|
||||
char *params = strsep(&mesg, "\1");
|
||||
if (strcmp(ctcp, "ACTION")) return;
|
||||
uiFmt(
|
||||
"\3%d%s\3 is now known as \3%d%s\3",
|
||||
color(user), prev, color(user), next
|
||||
"* \3%d%s\3 %s",
|
||||
color(user), nick, params
|
||||
);
|
||||
if (strcmp(user, chat.user)) tabTouch(nick);
|
||||
urlScan(params);
|
||||
}
|
||||
|
||||
static void handlePrivmsg(char *prefix, char *params) {
|
||||
char *nick = prift(&prefix);
|
||||
char *user = prift(&prefix);
|
||||
shift(¶ms);
|
||||
char *mesg = shift(¶ms);
|
||||
char *nick, *user, *mesg;
|
||||
shift(prefix, &nick, &user, NULL, params, 2, 0, NULL, &mesg);
|
||||
if (mesg[0] == '\1') {
|
||||
handleCTCP(nick, user, mesg);
|
||||
return;
|
||||
}
|
||||
bool self = !strcmp(user, chat.user);
|
||||
bool ping = !strncasecmp(mesg, chat.nick, strlen(chat.nick));
|
||||
uiFmt(
|
||||
"%c%c\3%d%s\17%c %s",
|
||||
self["<["], ping["\17\26"], color(user), nick, self[">]"], mesg
|
||||
);
|
||||
if (!self) tabTouch(nick);
|
||||
urlScan(mesg);
|
||||
if (ping) uiBeep();
|
||||
if (mesg[0] == '\1') {
|
||||
strsep(&mesg, " ");
|
||||
char *action = strsep(&mesg, "\1");
|
||||
uiFmt("* \3%d%s\3 %s", color(user), nick, action);
|
||||
} else {
|
||||
uiFmt(
|
||||
"%c%c\3%d%s\17%c %s",
|
||||
self["<["], ping["\17\26"], color(user), nick, self[">]"], mesg
|
||||
);
|
||||
}
|
||||
urlScan(mesg);
|
||||
}
|
||||
|
||||
static void handleNotice(char *prefix, char *params) {
|
||||
char *nick = prift(&prefix);
|
||||
char *user = prift(&prefix);
|
||||
char *chan = shift(¶ms);
|
||||
char *mesg = shift(¶ms);
|
||||
if (strcmp(chat.chan, chan)) return;
|
||||
char *nick, *user, *chan, *mesg;
|
||||
shift(prefix, &nick, &user, NULL, params, 2, 0, &chan, &mesg);
|
||||
if (strcmp(chan, chat.chan)) return;
|
||||
uiFmt(
|
||||
"-\3%d%s\3- %s",
|
||||
color(user), nick, mesg
|
||||
);
|
||||
tabTouch(nick);
|
||||
urlScan(mesg);
|
||||
uiFmt("-\3%d%s\3- %s", color(user), nick, mesg);
|
||||
}
|
||||
|
||||
static const struct {
|
||||
|
|
Loading…
Reference in New Issue