X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?a=blobdiff_plain;ds=sidebyside;f=maskmap%2Fmaskmap.c;h=f51dba4b19cf587690b170174a9c933dd36b6150;hb=07bc9fb02444968d4e8b1f0c6e00a15a8ada8d9e;hp=9c92810f0197c4a5d8aea6356ba72ba36e5bb2f5;hpb=0bcca45f296b613b1f1449d232f43eb0ada0014b;p=chiark-tcl.git diff --git a/maskmap/maskmap.c b/maskmap/maskmap.c index 9c92810..f51dba4 100644 --- a/maskmap/maskmap.c +++ b/maskmap/maskmap.c @@ -171,11 +171,45 @@ int do_maskmap_amend(ClientData cd, Tcl_Interp *ip, } int do_maskmap_lookup(ClientData cd, Tcl_Interp *ip, - Tcl_Obj *mapo, HBytes_Value addr, Tcl_Obj *def, + Tcl_Obj *mapo, HBytes_Value addrhb, Tcl_Obj *def, Tcl_Obj **result) { - /*MaskMap_Var *map= (void*)&mapo->internalRep;*/ - *result= Tcl_NewIntObj(42); - return TCL_OK; /*fixme*/ + MaskMap_Value *mm= (void*)&mapo->internalRep; + MaskMap_Entry *search; + const Byte *addr= hbytes_data(&addrhb); + int addrbytes= hbytes_len(&addrhb); + int i, directbytes, leftoverbits; + + search= mm->entries; + if (!search || search->prefixlen==-1) goto not_found; + + /* longest masks are first, so we can test this once */ + if (addrbytes < prefix_bytes(search->prefixlen)) + return staticerr(ip, "address shorter than mask(s) in map", + "HBYTES MASKMAP UNDERRUN"); + + for (i=0; + i < mm->allocd && search->prefixlen != -1; + i++, search++) { + directbytes= search->prefixlen / 8; + if (memcmp(search->prefix, addr, directbytes)) continue; + + leftoverbits= search->prefixlen % 8; + if (leftoverbits) + if ((addr[directbytes] & (0xffu << leftoverbits)) + != search->prefix[directbytes]) + continue; + + /*found*/ + *result= search->data; + return TCL_OK; + } + + not_found: + if (!def) + return staticerr(ip, "address not found in mask-map", + "HBYTES MASKMAP NOMATCH"); + *result= def; + return TCL_OK; } /*---------- Tcl type and arg parsing functions ----------*/