+/*
+ * Dolda Connect - Modular multiuser Direct Connect-style client
+ * Copyright (C) 2007 Fredrik Tolf <fredrik@dolda2000.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
#include <stdlib.h>
#include <stdio.h>
#include <sys/poll.h>
};
static int fd = -1;
-static scm_bits_t resptype;
+static scm_t_bits resptype;
static SCM scm_dc_connect(SCM host)
{
if(fd >= 0)
dc_disconnect();
- if(host == SCM_UNDEFINED)
+ if((host == SCM_UNDEFINED) || (host == SCM_BOOL_F))
{
chost = NULL;
} else {
- SCM_ASSERT(SCM_STRINGP(host), host, SCM_ARG1, "dc-connect");
- chost = SCM_STRING_CHARS(host);
+ SCM_ASSERT(scm_is_string(host), host, SCM_ARG1, "dc-connect");
+ chost = scm_to_locale_string(host);
}
- if((fd = dc_connect(chost)) < 0)
+ fd = dc_connect(chost);
+ if(chost != NULL)
+ free(chost);
+ if(fd < 0)
scm_syserror("dc-connect");
- return(SCM_MAKINUM(fd));
+ return(scm_from_int(fd));
}
static SCM scm_dc_disconnect(void)
{
dc_disconnect();
- return(SCM_MAKINUM(0));
+ return(scm_from_int(0));
}
static SCM scm_dc_connected(void)
{
cto = -1;
} else {
- SCM_ASSERT(SCM_INUMP(timeout), timeout, SCM_ARG1, "dc-select");
- cto = SCM_INUM(timeout);
+ SCM_ASSERT(scm_is_integer(timeout), timeout, SCM_ARG1, "dc-select");
+ cto = scm_to_int(timeout);
}
if(fd < 0)
scm_syserror_msg("dc-select", "Not connected", SCM_EOL, ENOTCONN);
{
struct respsmob *data;
- data = scm_must_malloc(sizeof(*data), "respsmob");
+ data = scm_gc_malloc(sizeof(*data), "respsmob");
data->resp = resp;
SCM_RETURN_NEWSMOB(resptype, data);
}
if((resp = dc_getresp()) == NULL)
return(SCM_BOOL_F);
} else {
- SCM_ASSERT(SCM_INUMP(tag), tag, SCM_ARG1, "dc-getresp");
- if((resp = dc_gettaggedresp(SCM_INUM(tag))) == NULL)
+ SCM_ASSERT(scm_is_integer(tag), tag, SCM_ARG1, "dc-getresp");
+ if((resp = dc_gettaggedresp(scm_to_int(tag))) == NULL)
return(SCM_BOOL_F);
}
ret = makerespsmob(resp);
resp = ((struct respsmob *)SCM_SMOB_DATA(scm_resp))->resp;
ret = SCM_EOL;
ret = scm_cons(scm_cons(scm_str2symbol("cmd"), scm_makfrom0str(icswcstombs(resp->cmdname, "UTF-8", NULL))), ret);
- ret = scm_cons(scm_cons(scm_str2symbol("code"), SCM_MAKINUM(resp->code)), ret);
- ret = scm_cons(scm_cons(scm_str2symbol("tag"), SCM_MAKINUM(resp->tag)), ret);
+ ret = scm_cons(scm_cons(scm_str2symbol("code"), scm_from_int(resp->code)), ret);
+ ret = scm_cons(scm_cons(scm_str2symbol("tag"), scm_from_int(resp->tag)), ret);
l = SCM_EOL;
for(i = resp->numlines - 1; i >= 0; i--)
{
ret = scm_cons(scm_makfrom0str(icswcstombs(ires->argv[i].val.str, "UTF-8", NULL)), ret);
break;
case 2:
- ret = scm_cons(scm_int2num(ires->argv[i].val.num), ret);
+ ret = scm_cons(scm_from_int(ires->argv[i].val.num), ret);
break;
case 3:
- ret = scm_cons(scm_double2num(ires->argv[i].val.flnum), ret);
+ ret = scm_cons(scm_from_double(ires->argv[i].val.flnum), ret);
+ break;
+ case 4:
+ ret = scm_cons(scm_from_int64(ires->argv[i].val.num), ret);
break;
}
}
return(2);
}
+static wchar_t *scm_string_to_wcs(SCM str)
+{
+ char *buf;
+ wchar_t *ret;
+
+ buf = scm_to_locale_string(str);
+ ret = icmbstowcs(buf, NULL);
+ free(buf);
+ return(ret);
+}
+
static SCM scm_dc_qcmd(SCM argv, SCM callback)
{
int tag, enob;
{
port = scm_open_output_string();
scm_display(SCM_CAR(argv), port);
- if((tok = icmbstowcs(SCM_STRING_CHARS(scm_get_output_string(port)), "UTF-8")) == NULL)
+ if((tok = scm_string_to_wcs(scm_get_output_string(port))) == NULL)
{
enob = errno;
addtobuf(toks, NULL);
addtobuf(toks, NULL);
if(callback == SCM_UNDEFINED)
{
- tag = dc_queuecmd(NULL, NULL, cmd, L"%%a", toks, NULL);
+ tag = dc_queuecmd(NULL, NULL, cmd, L"%a", toks, NULL);
} else {
- scmcb = scm_must_malloc(sizeof(*scmcb), "scmcb");
+ scmcb = scm_malloc(sizeof(*scmcb));
scm_gc_protect_object(scmcb->subr = callback);
- tag = dc_queuecmd(qcmd_scmcb, scmcb, cmd, L"%%a", toks, NULL);
+ tag = dc_queuecmd(qcmd_scmcb, scmcb, cmd, L"%a", toks, NULL);
}
dc_freewcsarr(toks);
if(cmd != NULL)
free(cmd);
- return(SCM_MAKINUM(tag));
+ if(tag == -1) {
+ if(errno == ENOSYS) {
+ scm_error(scm_str2symbol("no-such-cmd"), "dc-qcmd", "Invalid command name", SCM_EOL, SCM_BOOL_F);
+ } else if(errno == EINVAL) {
+ scm_error(scm_str2symbol("illegal-escape"), "dc-qcmd", "Invalid escape sequence", SCM_EOL, SCM_BOOL_F);
+ } else {
+ scm_syserror("dc-qcmd");
+ }
+ } else {
+ return(scm_from_int(tag));
+ }
}
static void login_scmcb(int err, wchar_t *reason, struct scmcb *scmcb)
static SCM scm_dc_loginasync(SCM callback, SCM useauthless, SCM username)
{
struct scmcb *scmcb;
+ char *un;
SCM_ASSERT(SCM_CLOSUREP(callback), callback, SCM_ARG1, "dc-loginasync");
- scmcb = scm_must_malloc(sizeof(*scmcb), "scmcb");
+ scmcb = scm_malloc(sizeof(*scmcb));
scm_gc_protect_object(scmcb->subr = callback);
- dc_loginasync(SCM_STRINGP(username)?SCM_STRING_CHARS(username):NULL, SCM_NFALSEP(useauthless), NULL, (void (*)(int, wchar_t *, void *))login_scmcb, scmcb);
+ if(scm_is_string(username))
+ un = scm_to_locale_string(username);
+ else
+ un = NULL;
+ dc_loginasync(un, SCM_NFALSEP(useauthless), NULL, (void (*)(int, wchar_t *, void *))login_scmcb, scmcb);
+ if(un != NULL)
+ free(un);
return(SCM_BOOL_T);
}
SCM ret;
wchar_t **arr, **ap, *buf;
- SCM_ASSERT(SCM_STRINGP(sexpr), sexpr, SCM_ARG1, "dc-lexsexpr");
- if((buf = icmbstowcs(SCM_STRING_CHARS(sexpr), NULL)) == NULL)
+ SCM_ASSERT(scm_is_string(sexpr), sexpr, SCM_ARG1, "dc-lexsexpr");
+ if((buf = scm_string_to_wcs(sexpr)) == NULL)
scm_syserror("dc-lexsexpr");
arr = dc_lexsexpr(buf);
free(buf);
return(scm_reverse(ret));
}
+static SCM scm_dc_checkproto(SCM resp, SCM version)
+{
+ int ver;
+
+ SCM_ASSERT(SCM_SMOB_PREDICATE(resptype, resp), resp, SCM_ARG1, "dc-checkproto");
+ if(version == SCM_UNDEFINED)
+ {
+ ver = DC_LATEST;
+ } else {
+ SCM_ASSERT(scm_is_integer(version), version, SCM_ARG2, "dc-checkproto");
+ ver = scm_to_int(version);
+ }
+ if(dc_checkprotocol(((struct respsmob *)SCM_SMOB_DATA(resp))->resp, ver))
+ return(SCM_BOOL_F);
+ else
+ return(SCM_BOOL_T);
+}
+
static size_t resp_free(SCM respsmob)
{
struct respsmob *data;
data = (struct respsmob *)SCM_SMOB_DATA(respsmob);
dc_freeresp(data->resp);
- free(data);
- return(sizeof(*data));
+ scm_gc_free(data, sizeof(*data), "respsmob");
+ return(0);
}
static int resp_print(SCM respsmob, SCM port, scm_print_state *pstate)
data = (struct respsmob *)SCM_SMOB_DATA(respsmob);
scm_puts("#<dc-response ", port);
- scm_display(SCM_MAKINUM(data->resp->tag), port);
+ scm_display(scm_from_int(data->resp->tag), port);
scm_puts(" ", port);
scm_puts(icswcstombs(data->resp->cmdname, "UTF-8", NULL), port);
scm_puts(" ", port);
- scm_display(SCM_MAKINUM(data->resp->code), port);
+ scm_display(scm_from_int(data->resp->code), port);
scm_puts(">", port);
return(1);
}
scm_c_define_gsubr("dc-qcmd", 1, 1, 0, scm_dc_qcmd);
scm_c_define_gsubr("dc-loginasync", 2, 1, 0, scm_dc_loginasync);
scm_c_define_gsubr("dc-lexsexpr", 1, 0, 0, scm_dc_lexsexpr);
+ scm_c_define_gsubr("dc-checkproto", 1, 1, 0, scm_dc_checkproto);
+ scm_c_define("dc-latest", scm_from_int(DC_LATEST));
resptype = scm_make_smob_type("dc-resp", sizeof(struct respsmob));
scm_set_smob_free(resptype, resp_free);
scm_set_smob_print(resptype, resp_print);