X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?a=blobdiff_plain;f=base%2Fhook.c;h=9243724ecc91b3deaf08976949f6a6fa86a3be11;hb=4622d557f2b46f6a6538cf7e1f17b54f81ef93a1;hp=68df783561431b14b411c22fa274111b5e16fa99;hpb=aa983421528c717a29c402c0cb4c8438b96fd860;p=chiark-tcl.git diff --git a/base/hook.c b/base/hook.c index 68df783..9243724 100644 --- a/base/hook.c +++ b/base/hook.c @@ -1,17 +1,15 @@ /* */ -#include +#include "chiark-tcl-base.h" -#include "hbytes.h" -#include "tables.h" - -int staticerr(Tcl_Interp *ip, const char *m) { +int cht_staticerr(Tcl_Interp *ip, const char *m, const char *ec) { Tcl_SetResult(ip, (char*)m, TCL_STATIC); + if (ec) Tcl_SetObjErrorCode(ip, Tcl_NewStringObj(ec,-1)); return TCL_ERROR; } -int posixerr(Tcl_Interp *ip, int errnoval, const char *m) { +int cht_posixerr(Tcl_Interp *ip, int errnoval, const char *m) { const char *em; Tcl_ResetResult(ip); @@ -21,148 +19,57 @@ int posixerr(Tcl_Interp *ip, int errnoval, const char *m) { return TCL_ERROR; } -void objfreeir(Tcl_Obj *o) { +int cht_newfdposixerr(Tcl_Interp *ip, int fd, const char *m) { + int e; + e= errno; + close(fd); + return cht_posixerr(ip,e,m); +} + +void cht_objfreeir(Tcl_Obj *o) { if (o->typePtr && o->typePtr->freeIntRepProc) o->typePtr->freeIntRepProc(o); o->typePtr= 0; } -int do_hbytes_rep_info(ClientData cd, Tcl_Interp *ip, - Tcl_Obj *obj, Tcl_Obj **result) { - const char *tn; - int nums[3], i, lnl; - Tcl_Obj *objl[4]; +void cht_obj_updatestr_vstringls(Tcl_Obj *o, ...) { + va_list al; + char *p; + const char *part; + int l, pl; - if (obj->typePtr == &hbytes_type) { - HBytes_Value *v= OBJ_HBYTES(obj); - memset(nums,0,sizeof(nums)); - nums[1]= hbytes_len(v); + va_start(al,o); + for (l=0; (part= va_arg(al, const char*)); ) + l+= va_arg(al, int); + va_end(al); - if (HBYTES_ISEMPTY(v)) tn= "empty"; - else if (HBYTES_ISSENTINEL(v)) tn= "sentinel!"; - else if (HBYTES_ISSIMPLE(v)) tn= "simple"; - else { - HBytes_ComplexValue *cx= v->begin_complex; - tn= "complex"; - nums[0]= cx->prespace; - nums[2]= cx->avail - cx->len; - } - lnl= 3; - } else { - tn= "other"; - lnl= 0; - } - - objl[0]= Tcl_NewStringObj((char*)tn,-1); - for (i=0; ilength= l; + o->bytes= TALLOC(l+1); -static void hbytes_t_dup(Tcl_Obj *src, Tcl_Obj *dup) { - objfreeir(dup); - hbytes_array(OBJ_HBYTES(dup), - hbytes_data(OBJ_HBYTES(src)), - hbytes_len(OBJ_HBYTES(src))); -} - -static void hbytes_t_free(Tcl_Obj *o) { - hbytes_free(OBJ_HBYTES(o)); -} - -void obj_updatestr_array(Tcl_Obj *o, const Byte *byte, int l) { - char *str; - - str= o->bytes= TALLOC(l*2+1); - o->length= l*2; - while (l>0) { - sprintf(str,"%02x",*byte); - str+=2; byte++; l--; + va_start(al,o); + for (p= o->bytes; (part= va_arg(al, const char*)); p += pl) { + pl= va_arg(al, int); + memcpy(p, part, pl); } - *str= 0; -} + va_end(al); -static void hbytes_t_ustr(Tcl_Obj *o) { - obj_updatestr_array(o, - hbytes_data(OBJ_HBYTES(o)), - hbytes_len(OBJ_HBYTES(o))); + *p= 0; } -static int hbytes_t_sfa(Tcl_Interp *ip, Tcl_Obj *o) { - char *str, *ep, *os; - Byte *startbytes, *bytes; - int l; - char cbuf[3]; - - os= str= Tcl_GetStringFromObj(o,&l); assert(str); - objfreeir(o); - - if (l & 1) return staticerr(ip, "hbytes: conversion from hex:" - " odd length in hex"); - - startbytes= bytes= hbytes_arrayspace(OBJ_HBYTES(o), l/2); - - cbuf[2]= 0; - while (l>0) { - cbuf[0]= *str++; - cbuf[1]= *str++; - *bytes++= strtoul(cbuf,&ep,16); - if (ep != cbuf+2) { - hbytes_free(OBJ_HBYTES(o)); - return staticerr(ip, "hbytes: conversion from hex:" - " bad hex digit"); - } - l -= 2; - } - - o->typePtr = &hbytes_type; - return TCL_OK; -} - -Tcl_ObjType hbytes_type = { - "hbytes", - hbytes_t_free, hbytes_t_dup, hbytes_t_ustr, hbytes_t_sfa -}; - -int do_hbytes_raw2h(ClientData cd, Tcl_Interp *ip, - Tcl_Obj *binary, HBytes_Value *result) { - const char *str; - int l; - - str= Tcl_GetStringFromObj(binary,&l); - hbytes_array(result, str, l); - return TCL_OK; -} - -int do_hbytes_h2raw(ClientData cd, Tcl_Interp *ip, - HBytes_Value hex, Tcl_Obj **result) { - *result= Tcl_NewStringObj(hbytes_data(&hex), hbytes_len(&hex)); - return TCL_OK; -} - -int do_hbytes_length(ClientData cd, Tcl_Interp *ip, - HBytes_Value v, int *result) { - *result= hbytes_len(&v); - return TCL_OK; -} - -int do__hbytes(ClientData cd, Tcl_Interp *ip, - const HBytes_SubCommand *subcmd, - int objc, Tcl_Obj *const *objv) { - return subcmd->func(0,ip,objc,objv); +void cht_obj_updatestr_string(Tcl_Obj *o, const char *str) { + cht_obj_updatestr_vstringls(o, str, strlen(str), (char*)0); } #define URANDOM "/dev/urandom" -int get_urandom(Tcl_Interp *ip, Byte *buffer, int l) { +int cht_get_urandom(Tcl_Interp *ip, Byte *buffer, int l) { static FILE *urandom; int r, esave; if (!urandom) { urandom= fopen(URANDOM,"rb"); - if (!urandom) return posixerr(ip,errno,"open " URANDOM); + if (!urandom) return cht_posixerr(ip,errno,"open " URANDOM); } r= fread(buffer,1,l,urandom); if (r==l) return 0; @@ -171,18 +78,41 @@ int get_urandom(Tcl_Interp *ip, Byte *buffer, int l) { fclose(urandom); urandom=0; if (ferror(urandom)) { - return posixerr(ip,errno,"read " URANDOM); + return cht_posixerr(ip,errno,"read " URANDOM); } else { assert(feof(urandom)); - return staticerr(ip, URANDOM " gave eof!"); + return cht_staticerr(ip, URANDOM " gave eof!", 0); } } -int Hbytes_Init(Tcl_Interp *ip) { - Tcl_RegisterObjType(&hbytes_type); - Tcl_RegisterObjType(&blockcipherkey_type); - Tcl_RegisterObjType(&enum_nearlytype); - Tcl_RegisterObjType(&enum1_nearlytype); - Tcl_CreateObjCommand(ip,"hbytes", pa__hbytes,0,0); +int cht_initextension(Tcl_Interp *ip, const TopLevel_Command *cmds, + int *donep /* or 0, meaning no types follow */, + ... /* types, terminated by 0 */) { + static int cht_initd; + + const TopLevel_Command *cmd; + Tcl_ObjType *ot; + + va_list al; + + if (!cht_initd) { + cht_initd= 1; + Tcl_RegisterObjType(&cht_tabledataid_nearlytype); + Tcl_RegisterObjType(&cht_enum_nearlytype); + Tcl_RegisterObjType(&cht_enum1_nearlytype); + } + + if (donep && !*donep) { + *donep= 1; + va_start(al, donep); + while ((ot= va_arg(al, Tcl_ObjType*))) + Tcl_RegisterObjType(ot); + } + + for (cmd= cmds; + cmd->name; + cmd++) + Tcl_CreateObjCommand(ip, (char*)cmd->name, cmd->func, 0,0); + return TCL_OK; }