+ rc= mme_parsekey(ip,&new,prefix,preflen,0); if (rc) return rc;
+
+ sr= mm_search(mm, &new, &searched);
+
+ replacements= &new;
+ nreplacements= 1;
+ replace_start= searched;
+ replace_end= searched;
+
+ switch (sr) {
+
+ case sr_notfound:
+ break;
+
+ case sr_exact:
+ replace_end= searched+1;
+ break;
+
+ case sr_aroundsmall:
+ u.mme= new;
+ u.sign= -1;
+ replace_start= mm_binarychop(mm, 0, searched, &u,
+ mm_amend_aroundsmall_binchoptest, &dummy);
+ u.sign= +1;
+ replace_end= mm_binarychop(mm, searched+1, mm.used, &u,
+ mm_amend_aroundsmall_binchoptest, &dummy);
+ break;
+
+ case sr_inbig:
+ /* Urgh, we need to break it up. This produces
+ * - innermost prefix (the new one) as specified
+ * - one for each bitlength
+ * <= innermost
+ * > outermost (the existing one)
+ * each one specifying the outermost prefix plus zero, one,
+ * two, etc. bits of the innermost followed by one bit
+ * opposite to the innermost, with the outermost's data
+ * Eg, if we have ff/8=>A and want to amend so that ffff/16=>B
+ * then we replace ff/8 with ff0/9=>A ff8/10=>A ffc/11=>A ...
+ * ... fff8/14=>A fffc/15=>A fffe/16=>A ffff/16=>B.
+ */
+
+ breaking= &mm.entries[searched];
+ nreplacements= new.prefix - breaking->prefixlen + 1;
+ replacements= TALLOC(sizeof(*replacements) * nreplacements);
+
+ for (fragmentlen= breaking->prefixlen + 1,
+ left_insert= 0, right_insert= nreplacements;
+ fragmentlen <= new.prefix;
+ fragmentlen++) {
+ int fragmentbytes;
+
+ fragmentbytes= prefix_bytes(fragmentlen)
+ fragment->prefixlen= fragmentlen;
+ fragment->prefix= TALLOC(fragmentbytes);
+ memcpy(fragment->prefix, new.prefix, fragmentbytes);
+ mme_clear_unwanted(fragment, fragmentbytes);
+
+ fragment->prefix[fragmentbytes] ^=
+ 0x80u >> ((fragmentlen+7) & 7);
+
+ switch (mme_compare(&fragment, &new)) {
+ case -2: replacements[left_insert++]= fragment; break;
+ case +2: replacements[--right_insert]= fragment; break;
+ default: abort();
+ }
+ }
+ assert(left_insert == right_insert-1);
+ replacements[left_insert]= new;
+ mme_init(&new);
+
+ replace_end= searched+1;
+ break;
+
+ }
+
+ new_used= mm.used - (replace_end - replace_start) + nreplacements;
+
+ if (new_used > mm.space)
+ mm_reallocentries(mm, new_used * 2);
+
+ for (scan=replacements, i=0;
+ i < nreplacements;
+ scan++, i++) {
+ scan->data= data;
+ Tcl_IncrRefCount(scan->data);
+ }
+
+ for (i= replace_start, scan= mm.entries+i;
+ i < replace_end;
+ i++, scan++) {
+ mme_free(scan);
+ }
+
+ memmove(mm.entries + replace_start + nreplacements,
+ mm.entries + replace_end,
+ sizeof(*mm.entries) * (mm.used - replace_end));
+
+ memcpy(mm.entries + replace_start,
+ replacements,
+ sizeof(*mm.entries) * nreplacements);
+
+ mm.used= new_used;
+ if (replacements != &new)
+ /* we don't bother freeing the actual array elements because
+ * if replacements!=&new the array is only full if we're
+ * committed and have already copied the values into the actual
+ * MaskMap_Value. */
+ TFREE(replacements);
+
+ return TCL_OK;
+}
+
+/*---------- other substantial operations on mask maps ----------*/
+
+int do_maskmap_lookup(ClientData cd, Tcl_Interp *ip,
+ Tcl_Obj *mapo, HBytes_Value addrhb, Tcl_Obj *def,
+ Tcl_Obj **result) {
+ MaskMap_Value *mm= (void*)&mapo->internalRep;
+ const Byte *addr= hbytes_data(&addrhb);
+ int addrbytes= hbytes_len(&addrhb);
+ int i, addrbits, place;
+ Search_Result sr;
+
+ addrbits= addrbytes * 8;
+ sr= mm_search(mm, addr, addrbits, &place);
+
+ switch (sr) {
+
+ case sr_notfound:
+ if (!def) return staticerr(ip, "address not found in mask-map",
+ "HBYTES MASKMAP NOMATCH");
+ *result= def;
+ break;
+
+ case sr_aroundsmall:
+ return staticerr(ip, "address shorter than mask in map",
+ "HBYTES MASKMAP UNDERRUN");
+
+ case sr_exact:
+ case sr_inbig:
+ *result= mm.entres[place].data;
+ break;
+
+ }
+
+ return TCL_OK;
+}
+
+/*---------- Tcl type and arg parsing functions ----------*/
+
+int pat_maskmapv(Tcl_Interp *ip, Tcl_Obj *var, MaskMap_Var *agg) {
+ int rc;
+ rc= pat_somethingv(ip,var,&agg->sth,&maskmap_type); if (rc) return rc;
+ agg->mm= (void*)&agg->sth.obj->internalRep;
+ return TCL_OK;
+}
+