X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=chiark-tcl.git;a=blobdiff_plain;f=base%2Fhook.c;h=6e4b3a102e4abe26cf48cdb26faad2066dd2d439;hp=d6d96d9ce1a406ff4b34b4199415abc0b3fa1040;hb=382dc154ad04e75c16d062af9e4ab49a82330ba0;hpb=bc4e7d2673e44826dd768ad7f91c393349da24de diff --git a/base/hook.c b/base/hook.c index d6d96d9..6e4b3a1 100644 --- a/base/hook.c +++ b/base/hook.c @@ -1,140 +1,123 @@ /* + * base code for various Tcl extensions + * Copyright 2006-2012 Ian Jackson + * + * 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 library; if not, see . */ -#include "hbytes.h" -#include "tables.h" +#include "chiark-tcl-base.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; } -void 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, - HBytes_Value v, Tcl_Obj **result) { - const char *tn; - int nums[3], i; - Tcl_Obj *objl[4]; - - memset(nums,0,sizeof(nums)); - nums[1]= hbytes_len(&v); +int cht_posixerr(Tcl_Interp *ip, int errnoval, const char *m) { + const char *em; - 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; - } - - objl[0]= Tcl_NewStringObj((char*)tn,-1); - for (i=0; i<3; i++) objl[i+1]= Tcl_NewIntObj(nums[i]); - *result= Tcl_NewListObj(4,objl); - return TCL_OK; + Tcl_ResetResult(ip); + errno= errnoval; + em= Tcl_PosixError(ip); + Tcl_AppendResult(ip, m, ": ", em, (char*)0); + return TCL_ERROR; } -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))); +int cht_newfdposixerr(Tcl_Interp *ip, int fd, const char *m) { + int e; + e= errno; + close(fd); + return cht_posixerr(ip,e,m); } -static void hbytes_t_free(Tcl_Obj *o) { - hbytes_free(OBJ_HBYTES(o)); -} +void cht_objfreeir(Tcl_Obj *o) { + if (o->typePtr && o->typePtr->freeIntRepProc) + o->typePtr->freeIntRepProc(o); + o->typePtr= 0; +} -static void hbytes_t_ustr(Tcl_Obj *o) { +void cht_obj_updatestr_vstringls(Tcl_Obj *o, ...) { + va_list al; + char *p; + const char *part; int l; - char *str; - const Byte *byte; - - byte= hbytes_data(OBJ_HBYTES(o)); - l= hbytes_len(OBJ_HBYTES(o)); - str= o->bytes= TALLOC(l*2+1); - o->length= l*2; - while (l>0) { - sprintf(str,"%02x",*byte); - str+=2; byte++; l--; + size_t pl; + + va_start(al,o); + for (l=0; (part= va_arg(al, const char*)); ) { + pl= va_arg(al, size_t); + assert(pl <= INT_MAX/2 - l); + l += pl; } - *str= 0; -} + va_end(al); + + o->length= l; + o->bytes= TALLOC(l+1); -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; + va_start(al,o); + for (p= o->bytes; (part= va_arg(al, const char*)); p += pl) { + pl= va_arg(al, size_t); + memcpy(p, part, pl); } + va_end(al); - o->typePtr = &hbytes_type; - return TCL_OK; + *p= 0; } -Tcl_ObjType hbytes_type = { - "hbytes", - hbytes_t_free, hbytes_t_dup, hbytes_t_ustr, hbytes_t_sfa -}; +void cht_obj_updatestr_string(Tcl_Obj *o, const char *str) { + cht_obj_updatestr_vstringls(o, str, strlen(str), (char*)0); +} -int do_hbytes_raw2h(ClientData cd, Tcl_Interp *ip, - Tcl_Obj *binary, HBytes_Value *result) { - const char *str; - int l; +#define URANDOM "/dev/urandom" - str= Tcl_GetStringFromObj(binary,&l); - hbytes_array(result, str, l); - return TCL_OK; -} +int cht_get_urandom(Tcl_Interp *ip, Byte *buffer, int l) { + static FILE *urandom; -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 r; -int do_hbytes_length(ClientData cd, Tcl_Interp *ip, - HBytes_Value v, int *result) { - *result= hbytes_len(&v); - return TCL_OK; + if (!urandom) { + urandom= fopen(URANDOM,"rb"); + if (!urandom) return cht_posixerr(ip,errno,"open " URANDOM); + } + r= fread(buffer,1,l,urandom); + if (r==l) return 0; + + if (ferror(urandom)) { + r = cht_posixerr(ip,errno,"read " URANDOM); + } else { + assert(feof(urandom)); + r = cht_staticerr(ip, URANDOM " gave eof!", 0); + } + fclose(urandom); urandom=0; + return r; } -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_prepare__basic(Tcl_Interp *ip) { + static int prepared; + + if (prepared) return; + Tcl_RegisterObjType(&cht_tabledataid_nearlytype); + Tcl_RegisterObjType(&cht_enum_nearlytype); + Tcl_RegisterObjType(&cht_enum1_nearlytype); + prepared= 1; } -int Hbytes_Init(Tcl_Interp *ip) { - Tcl_RegisterObjType(&hbytes_type); - Tcl_RegisterObjType(&enum_nearlytype); - Tcl_RegisterObjType(&enum1_nearlytype); - Tcl_CreateObjCommand(ip,"hbytes", pa__hbytes,0,0); - return TCL_OK; +void cht_setup__commands(Tcl_Interp *ip, const TopLevel_Command *cmds) { + const TopLevel_Command *cmd; + + for (cmd= cmds; + cmd->name; + cmd++) + Tcl_CreateObjCommand(ip, (char*)cmd->name, cmd->func, 0,0); }