1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <stdio.h> 30*7c478bd9Sstevel@tonic-gate #include <malloc.h> 31*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 32*7c478bd9Sstevel@tonic-gate #include <errno.h> 33*7c478bd9Sstevel@tonic-gate #include <string.h> 34*7c478bd9Sstevel@tonic-gate #include "xlator.h" 35*7c478bd9Sstevel@tonic-gate #include "util.h" 36*7c478bd9Sstevel@tonic-gate #include "bucket.h" 37*7c478bd9Sstevel@tonic-gate #include "errlog.h" 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gate /* Statics: */ 40*7c478bd9Sstevel@tonic-gate #define TRUE 1 41*7c478bd9Sstevel@tonic-gate #define FALSE 0 42*7c478bd9Sstevel@tonic-gate #define NLISTS 50 43*7c478bd9Sstevel@tonic-gate #define NPAR 25 44*7c478bd9Sstevel@tonic-gate 45*7c478bd9Sstevel@tonic-gate static bucket_t **Buckethead; 46*7c478bd9Sstevel@tonic-gate static int N_lists; 47*7c478bd9Sstevel@tonic-gate 48*7c478bd9Sstevel@tonic-gate static int Bc = -1; /* For iterators. */ 49*7c478bd9Sstevel@tonic-gate static bucket_t *Bp; 50*7c478bd9Sstevel@tonic-gate 51*7c478bd9Sstevel@tonic-gate static void start_new_list(const bucket_t *); 52*7c478bd9Sstevel@tonic-gate static void grow_lists(void); 53*7c478bd9Sstevel@tonic-gate static bucket_t *new_bucket(const char *, int); 54*7c478bd9Sstevel@tonic-gate static void print_iface(const Interface *); 55*7c478bd9Sstevel@tonic-gate static void new_hashmap(void); 56*7c478bd9Sstevel@tonic-gate static int add_to_hashmap(const char *, const bucket_t *); 57*7c478bd9Sstevel@tonic-gate static bucket_t *find_in_hashmap(const char *); 58*7c478bd9Sstevel@tonic-gate /* 59*7c478bd9Sstevel@tonic-gate * initialization interfaces. 60*7c478bd9Sstevel@tonic-gate */ 61*7c478bd9Sstevel@tonic-gate 62*7c478bd9Sstevel@tonic-gate /* 63*7c478bd9Sstevel@tonic-gate * create_lists -- initialize the bucket list and hash map. 64*7c478bd9Sstevel@tonic-gate */ 65*7c478bd9Sstevel@tonic-gate void 66*7c478bd9Sstevel@tonic-gate create_lists(void) 67*7c478bd9Sstevel@tonic-gate { 68*7c478bd9Sstevel@tonic-gate 69*7c478bd9Sstevel@tonic-gate errlog(BEGIN, "create_lists() {"); 70*7c478bd9Sstevel@tonic-gate new_hashmap(); 71*7c478bd9Sstevel@tonic-gate if ((Buckethead = calloc(sizeof (bucket_t *), NLISTS)) == NULL) { 72*7c478bd9Sstevel@tonic-gate errlog(FATAL, "out of memory creating initial " 73*7c478bd9Sstevel@tonic-gate "list of versions"); 74*7c478bd9Sstevel@tonic-gate 75*7c478bd9Sstevel@tonic-gate } 76*7c478bd9Sstevel@tonic-gate N_lists = NLISTS; 77*7c478bd9Sstevel@tonic-gate errlog(END, "}"); 78*7c478bd9Sstevel@tonic-gate } 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate /* 82*7c478bd9Sstevel@tonic-gate * data-loading interfaces -- adding buckets to lists and 83*7c478bd9Sstevel@tonic-gate * interfaces to buckets. 84*7c478bd9Sstevel@tonic-gate */ 85*7c478bd9Sstevel@tonic-gate 86*7c478bd9Sstevel@tonic-gate /* 87*7c478bd9Sstevel@tonic-gate * add_parent -- add a parent node. Returns TRUE or FALSE. 88*7c478bd9Sstevel@tonic-gate * 89*7c478bd9Sstevel@tonic-gate * if *version == NULL, then 90*7c478bd9Sstevel@tonic-gate * the bucket version (eg, SUNW_1.1) hasn't 91*7c478bd9Sstevel@tonic-gate * been parsed correctly. Die. 92*7c478bd9Sstevel@tonic-gate * if *after == NULL, then this is the ``initial case'', 93*7c478bd9Sstevel@tonic-gate * where no predecessor (child) exists. We start a new 94*7c478bd9Sstevel@tonic-gate * tree of buckets. 95*7c478bd9Sstevel@tonic-gate * if *after != NULL, we have the normal case, and 96*7c478bd9Sstevel@tonic-gate * add to an existing tree. 97*7c478bd9Sstevel@tonic-gate * if *after is not a version name found among the buckets, 98*7c478bd9Sstevel@tonic-gate * then something got misparsed or the versions file is 99*7c478bd9Sstevel@tonic-gate * malformed. Function will print problem and 100*7c478bd9Sstevel@tonic-gate * return 0 so caller can report location of error. 101*7c478bd9Sstevel@tonic-gate * If either version or after is NULL, it's a programmer error. 102*7c478bd9Sstevel@tonic-gate */ 103*7c478bd9Sstevel@tonic-gate int 104*7c478bd9Sstevel@tonic-gate add_parent(const char *version, const char *after, int weak) 105*7c478bd9Sstevel@tonic-gate { 106*7c478bd9Sstevel@tonic-gate bucket_t *new, *child; 107*7c478bd9Sstevel@tonic-gate 108*7c478bd9Sstevel@tonic-gate /* Sanity-check parameters. */ 109*7c478bd9Sstevel@tonic-gate assert(version != NULL, "passed a null version to add_parent"); 110*7c478bd9Sstevel@tonic-gate assert(after != NULL, "passed a null after to add_parent"); 111*7c478bd9Sstevel@tonic-gate errlog(BEGIN, "add_parent(%s,%s,%d) {", version, after, weak); 112*7c478bd9Sstevel@tonic-gate if ((new = find_in_hashmap(version)) == NULL) { 113*7c478bd9Sstevel@tonic-gate /* We don't have one have one yet. */ 114*7c478bd9Sstevel@tonic-gate new = new_bucket(version, weak); 115*7c478bd9Sstevel@tonic-gate } 116*7c478bd9Sstevel@tonic-gate new->b_weak = weak; 117*7c478bd9Sstevel@tonic-gate if (*after == '\0') { 118*7c478bd9Sstevel@tonic-gate /* 119*7c478bd9Sstevel@tonic-gate * This is the ``initial case'', where no 120*7c478bd9Sstevel@tonic-gate * child exists. We start a new tree of buckets. 121*7c478bd9Sstevel@tonic-gate */ 122*7c478bd9Sstevel@tonic-gate (void) add_to_hashmap(version, new); 123*7c478bd9Sstevel@tonic-gate start_new_list(new); 124*7c478bd9Sstevel@tonic-gate } else { 125*7c478bd9Sstevel@tonic-gate if ((child = find_in_hashmap(after)) == NULL) { 126*7c478bd9Sstevel@tonic-gate /* 127*7c478bd9Sstevel@tonic-gate * The version in the spec doesn't appear in the 128*7c478bd9Sstevel@tonic-gate * versions file. One or the other is lying. 129*7c478bd9Sstevel@tonic-gate */ 130*7c478bd9Sstevel@tonic-gate errlog(WARNING, "set file: can't find version \"%s\"," 131*7c478bd9Sstevel@tonic-gate "therefor can't add it's parent, \"%s\"", 132*7c478bd9Sstevel@tonic-gate after, version); 133*7c478bd9Sstevel@tonic-gate errlog(END, "} /* add_parent */"); 134*7c478bd9Sstevel@tonic-gate return (FALSE); 135*7c478bd9Sstevel@tonic-gate } 136*7c478bd9Sstevel@tonic-gate (void) add_to_hashmap(version, new); 137*7c478bd9Sstevel@tonic-gate child->b_parent = new; 138*7c478bd9Sstevel@tonic-gate } 139*7c478bd9Sstevel@tonic-gate errlog(END, "} /* add_parent */"); 140*7c478bd9Sstevel@tonic-gate return (TRUE); 141*7c478bd9Sstevel@tonic-gate } 142*7c478bd9Sstevel@tonic-gate 143*7c478bd9Sstevel@tonic-gate /* 144*7c478bd9Sstevel@tonic-gate * add_uncle -- adds an uncle node 145*7c478bd9Sstevel@tonic-gate */ 146*7c478bd9Sstevel@tonic-gate int 147*7c478bd9Sstevel@tonic-gate add_uncle(const char *version, const char *after, int weak) 148*7c478bd9Sstevel@tonic-gate { 149*7c478bd9Sstevel@tonic-gate bucket_t *new, *child; 150*7c478bd9Sstevel@tonic-gate struct bucketlist *uncle; 151*7c478bd9Sstevel@tonic-gate 152*7c478bd9Sstevel@tonic-gate /* Sanity-check parameters. */ 153*7c478bd9Sstevel@tonic-gate assert(version != NULL, "passed a null version to add_uncle"); 154*7c478bd9Sstevel@tonic-gate assert(after != NULL, "passed a null after to add_uncle"); 155*7c478bd9Sstevel@tonic-gate errlog(BEGIN, "add_uncle(%s,%s,%d) {", version, after, weak); 156*7c478bd9Sstevel@tonic-gate if ((new = find_in_hashmap(version)) == NULL) { 157*7c478bd9Sstevel@tonic-gate /* We don't have one have one yet. */ 158*7c478bd9Sstevel@tonic-gate new = new_bucket(version, weak); 159*7c478bd9Sstevel@tonic-gate } 160*7c478bd9Sstevel@tonic-gate if (*after == '\0') { 161*7c478bd9Sstevel@tonic-gate /* 162*7c478bd9Sstevel@tonic-gate * This is the ``initial case'', where no 163*7c478bd9Sstevel@tonic-gate * child exists. We start a new tree of buckets. 164*7c478bd9Sstevel@tonic-gate */ 165*7c478bd9Sstevel@tonic-gate (void) add_to_hashmap(version, new); 166*7c478bd9Sstevel@tonic-gate start_new_list(new); 167*7c478bd9Sstevel@tonic-gate } else { 168*7c478bd9Sstevel@tonic-gate if ((child = find_in_hashmap(after)) == NULL) { 169*7c478bd9Sstevel@tonic-gate /* 170*7c478bd9Sstevel@tonic-gate * The version in the spec doesn't appear in the 171*7c478bd9Sstevel@tonic-gate * versions file. One or the other is lying. 172*7c478bd9Sstevel@tonic-gate */ 173*7c478bd9Sstevel@tonic-gate errlog(WARNING, "set file: can't find version \"%s\"," 174*7c478bd9Sstevel@tonic-gate "therefor can't add it's uncle, \"%s\"", 175*7c478bd9Sstevel@tonic-gate after, version); 176*7c478bd9Sstevel@tonic-gate errlog(END, "}"); 177*7c478bd9Sstevel@tonic-gate return (FALSE); 178*7c478bd9Sstevel@tonic-gate } 179*7c478bd9Sstevel@tonic-gate (void) add_to_hashmap(version, new); 180*7c478bd9Sstevel@tonic-gate uncle = malloc(sizeof (struct bucketlist)); 181*7c478bd9Sstevel@tonic-gate uncle->bl_next = child->b_uncles; 182*7c478bd9Sstevel@tonic-gate uncle->bl_bucket = new; 183*7c478bd9Sstevel@tonic-gate child->b_uncles = uncle; 184*7c478bd9Sstevel@tonic-gate } 185*7c478bd9Sstevel@tonic-gate errlog(END, "}"); 186*7c478bd9Sstevel@tonic-gate return (TRUE); 187*7c478bd9Sstevel@tonic-gate } 188*7c478bd9Sstevel@tonic-gate 189*7c478bd9Sstevel@tonic-gate /* 190*7c478bd9Sstevel@tonic-gate * set_weak -- set a version to be a weak version 191*7c478bd9Sstevel@tonic-gate */ 192*7c478bd9Sstevel@tonic-gate void 193*7c478bd9Sstevel@tonic-gate set_weak(const char *version, int weak) 194*7c478bd9Sstevel@tonic-gate { 195*7c478bd9Sstevel@tonic-gate bucket_t *v; 196*7c478bd9Sstevel@tonic-gate if ((v = find_in_hashmap(version)) == NULL) { 197*7c478bd9Sstevel@tonic-gate /* We don't have one have one yet. */ 198*7c478bd9Sstevel@tonic-gate errlog(ERROR|FATAL, "Unable to set weak. Version not found"); 199*7c478bd9Sstevel@tonic-gate } 200*7c478bd9Sstevel@tonic-gate v->b_weak = weak; 201*7c478bd9Sstevel@tonic-gate } 202*7c478bd9Sstevel@tonic-gate 203*7c478bd9Sstevel@tonic-gate /* 204*7c478bd9Sstevel@tonic-gate * add_by_name -- look up bucket and add an interface to it. 205*7c478bd9Sstevel@tonic-gate * Returns 0 for success or an errno.h value for failure. 206*7c478bd9Sstevel@tonic-gate * 207*7c478bd9Sstevel@tonic-gate * if *version is not among the buckets, then the 208*7c478bd9Sstevel@tonic-gate * version in the spec doesn't appear in the 209*7c478bd9Sstevel@tonic-gate * set file. One or the other is lying. Function will 210*7c478bd9Sstevel@tonic-gate * report the problem and return ENOENT 211*7c478bd9Sstevel@tonic-gate * so the front end can report and exit (or 212*7c478bd9Sstevel@tonic-gate * continue if it wants). 213*7c478bd9Sstevel@tonic-gate * if interface ore version is NULL, then 214*7c478bd9Sstevel@tonic-gate * the begin line code should 215*7c478bd9Sstevel@tonic-gate * have caught it long before, to avoid passing 216*7c478bd9Sstevel@tonic-gate * a null pointer around. Die. 217*7c478bd9Sstevel@tonic-gate * 218*7c478bd9Sstevel@tonic-gate */ 219*7c478bd9Sstevel@tonic-gate #define ADD_EQUALS(str) if (strchr(str, '=') == NULL) (void) strcat(str, " =") 220*7c478bd9Sstevel@tonic-gate 221*7c478bd9Sstevel@tonic-gate int 222*7c478bd9Sstevel@tonic-gate add_by_name(const char *version, const Interface *interface) 223*7c478bd9Sstevel@tonic-gate { 224*7c478bd9Sstevel@tonic-gate bucket_t *b; 225*7c478bd9Sstevel@tonic-gate char buffer[1024]; 226*7c478bd9Sstevel@tonic-gate 227*7c478bd9Sstevel@tonic-gate assert(version != NULL, "passed a null version to add_by_name"); 228*7c478bd9Sstevel@tonic-gate assert(interface != NULL, "passed a null interface to add_by_name"); 229*7c478bd9Sstevel@tonic-gate 230*7c478bd9Sstevel@tonic-gate errlog(BEGIN, "add_by_name(%s,", version); 231*7c478bd9Sstevel@tonic-gate print_iface(interface); 232*7c478bd9Sstevel@tonic-gate errlog(TRACING, ");"); 233*7c478bd9Sstevel@tonic-gate 234*7c478bd9Sstevel@tonic-gate /* Sanity-check the parameters. */ 235*7c478bd9Sstevel@tonic-gate if ((b = find_in_hashmap(version)) == NULL) { 236*7c478bd9Sstevel@tonic-gate /* 237*7c478bd9Sstevel@tonic-gate * The version in the spec doesn't appear in the 238*7c478bd9Sstevel@tonic-gate * versions file. Alas, this isn't an error. It can 239*7c478bd9Sstevel@tonic-gate * happen whenever doing just sparc, just i386 240*7c478bd9Sstevel@tonic-gate * or the like. 241*7c478bd9Sstevel@tonic-gate */ 242*7c478bd9Sstevel@tonic-gate errlog(END, "}"); 243*7c478bd9Sstevel@tonic-gate return (ENOENT); 244*7c478bd9Sstevel@tonic-gate } 245*7c478bd9Sstevel@tonic-gate /* 246*7c478bd9Sstevel@tonic-gate * Add to bucket. 247*7c478bd9Sstevel@tonic-gate */ 248*7c478bd9Sstevel@tonic-gate (void) snprintf(buffer, sizeof (buffer), "%s", interface->IF_name); 249*7c478bd9Sstevel@tonic-gate 250*7c478bd9Sstevel@tonic-gate if (interface->IF_filter && interface->IF_auxiliary) { 251*7c478bd9Sstevel@tonic-gate errlog(FATAL, "Error: cannot set both FILTER and AUXILIARY " 252*7c478bd9Sstevel@tonic-gate "for an interface: %s", interface->IF_name); 253*7c478bd9Sstevel@tonic-gate } 254*7c478bd9Sstevel@tonic-gate 255*7c478bd9Sstevel@tonic-gate if (interface->IF_filter) { 256*7c478bd9Sstevel@tonic-gate ADD_EQUALS(buffer); 257*7c478bd9Sstevel@tonic-gate if (interface->IF_type == FUNCTION) { 258*7c478bd9Sstevel@tonic-gate (void) strcat(buffer, " FUNCTION"); 259*7c478bd9Sstevel@tonic-gate } else if (interface->IF_type == DATA) { 260*7c478bd9Sstevel@tonic-gate (void) strcat(buffer, " DATA"); 261*7c478bd9Sstevel@tonic-gate } 262*7c478bd9Sstevel@tonic-gate (void) strcat(buffer, " FILTER "); 263*7c478bd9Sstevel@tonic-gate (void) strcat(buffer, interface->IF_filter); 264*7c478bd9Sstevel@tonic-gate } else if (interface->IF_auxiliary) { 265*7c478bd9Sstevel@tonic-gate ADD_EQUALS(buffer); 266*7c478bd9Sstevel@tonic-gate (void) strcat(buffer, " AUXILIARY "); 267*7c478bd9Sstevel@tonic-gate (void) strcat(buffer, interface->IF_auxiliary); 268*7c478bd9Sstevel@tonic-gate } else if (IsFilterLib) { 269*7c478bd9Sstevel@tonic-gate /* 270*7c478bd9Sstevel@tonic-gate * For DATA types it is currently assumed that they are 271*7c478bd9Sstevel@tonic-gate * handled via a minimal C file, e.g. 'data.c', in the 272*7c478bd9Sstevel@tonic-gate * library's build. Hence, we do not append '= DATA' here. 273*7c478bd9Sstevel@tonic-gate */ 274*7c478bd9Sstevel@tonic-gate if (interface->IF_type == FUNCTION) { 275*7c478bd9Sstevel@tonic-gate ADD_EQUALS(buffer); 276*7c478bd9Sstevel@tonic-gate (void) strcat(buffer, " FUNCTION"); 277*7c478bd9Sstevel@tonic-gate } 278*7c478bd9Sstevel@tonic-gate } 279*7c478bd9Sstevel@tonic-gate 280*7c478bd9Sstevel@tonic-gate switch (interface->IF_binding) { 281*7c478bd9Sstevel@tonic-gate case DIRECT: 282*7c478bd9Sstevel@tonic-gate ADD_EQUALS(buffer); 283*7c478bd9Sstevel@tonic-gate (void) strcat(buffer, " DIRECT"); 284*7c478bd9Sstevel@tonic-gate break; 285*7c478bd9Sstevel@tonic-gate case NODIRECT: 286*7c478bd9Sstevel@tonic-gate ADD_EQUALS(buffer); 287*7c478bd9Sstevel@tonic-gate (void) strcat(buffer, " NODIRECT"); 288*7c478bd9Sstevel@tonic-gate break; 289*7c478bd9Sstevel@tonic-gate } 290*7c478bd9Sstevel@tonic-gate 291*7c478bd9Sstevel@tonic-gate if (interface->IF_binding == PROTECTED) { 292*7c478bd9Sstevel@tonic-gate /* Assign in case of realloc. */ 293*7c478bd9Sstevel@tonic-gate b->b_protected_table = 294*7c478bd9Sstevel@tonic-gate add_to_stringtable(b->b_protected_table, buffer); 295*7c478bd9Sstevel@tonic-gate b->b_has_protecteds = 1; 296*7c478bd9Sstevel@tonic-gate errlog(VERBOSE, "set has_protecteds on bucket 0x%p", b); 297*7c478bd9Sstevel@tonic-gate } else { 298*7c478bd9Sstevel@tonic-gate /* Assign in case of realloc. */ 299*7c478bd9Sstevel@tonic-gate b->b_global_table = add_to_stringtable(b->b_global_table, 300*7c478bd9Sstevel@tonic-gate buffer); 301*7c478bd9Sstevel@tonic-gate } 302*7c478bd9Sstevel@tonic-gate errlog(END, "}"); 303*7c478bd9Sstevel@tonic-gate return (0); 304*7c478bd9Sstevel@tonic-gate } 305*7c478bd9Sstevel@tonic-gate 306*7c478bd9Sstevel@tonic-gate 307*7c478bd9Sstevel@tonic-gate /* 308*7c478bd9Sstevel@tonic-gate * Processing interfaces 309*7c478bd9Sstevel@tonic-gate */ 310*7c478bd9Sstevel@tonic-gate 311*7c478bd9Sstevel@tonic-gate /* 312*7c478bd9Sstevel@tonic-gate * sort_buckets -- sort the interfaces within the buckets into 313*7c478bd9Sstevel@tonic-gate * alphabetical order. 314*7c478bd9Sstevel@tonic-gate */ 315*7c478bd9Sstevel@tonic-gate void 316*7c478bd9Sstevel@tonic-gate sort_buckets(void) 317*7c478bd9Sstevel@tonic-gate { 318*7c478bd9Sstevel@tonic-gate bucket_t *l, *b; 319*7c478bd9Sstevel@tonic-gate 320*7c478bd9Sstevel@tonic-gate errlog(BEGIN, "sort_buckets() {"); 321*7c478bd9Sstevel@tonic-gate for (l = first_list(); l != NULL; l = next_list()) { 322*7c478bd9Sstevel@tonic-gate errlog(VERBOSE, "l-bucket: %s", l->b_name); 323*7c478bd9Sstevel@tonic-gate for (b = first_from_list(l); b != NULL; b = next_from_list()) { 324*7c478bd9Sstevel@tonic-gate errlog(VERBOSE, " b-bkt: %s", b->b_name); 325*7c478bd9Sstevel@tonic-gate sort_stringtable(b->b_global_table); 326*7c478bd9Sstevel@tonic-gate sort_stringtable(b->b_protected_table); 327*7c478bd9Sstevel@tonic-gate if (b->b_uncles) { 328*7c478bd9Sstevel@tonic-gate 329*7c478bd9Sstevel@tonic-gate if (b->b_uncles->bl_bucket) { 330*7c478bd9Sstevel@tonic-gate sort_stringtable(b->b_uncles->bl_bucket->b_global_table); 331*7c478bd9Sstevel@tonic-gate sort_stringtable(b->b_uncles->bl_bucket->b_protected_table); 332*7c478bd9Sstevel@tonic-gate } 333*7c478bd9Sstevel@tonic-gate } 334*7c478bd9Sstevel@tonic-gate } 335*7c478bd9Sstevel@tonic-gate } 336*7c478bd9Sstevel@tonic-gate errlog(END, "}"); 337*7c478bd9Sstevel@tonic-gate } 338*7c478bd9Sstevel@tonic-gate 339*7c478bd9Sstevel@tonic-gate 340*7c478bd9Sstevel@tonic-gate /* 341*7c478bd9Sstevel@tonic-gate * add_local -- set the local flag on the logically first bucket. 342*7c478bd9Sstevel@tonic-gate * This decision may belong in the caller, as it is about 343*7c478bd9Sstevel@tonic-gate * mapfiles, not inherent ordering or bucket contents... 344*7c478bd9Sstevel@tonic-gate */ 345*7c478bd9Sstevel@tonic-gate void 346*7c478bd9Sstevel@tonic-gate add_local(void) 347*7c478bd9Sstevel@tonic-gate { 348*7c478bd9Sstevel@tonic-gate bucket_t *b, *list; 349*7c478bd9Sstevel@tonic-gate int done = 0; 350*7c478bd9Sstevel@tonic-gate 351*7c478bd9Sstevel@tonic-gate errlog(BEGIN, "add_local() {"); 352*7c478bd9Sstevel@tonic-gate /* Iterate across lists of buckets */ 353*7c478bd9Sstevel@tonic-gate for (list = first_list(); list != NULL; list = next_list()) { 354*7c478bd9Sstevel@tonic-gate /* Traverse the list found. */ 355*7c478bd9Sstevel@tonic-gate for (b = list; b != NULL; b = b->b_parent) { 356*7c478bd9Sstevel@tonic-gate if (b->b_weak != 1) { 357*7c478bd9Sstevel@tonic-gate /* We've found the first non-weak. */ 358*7c478bd9Sstevel@tonic-gate b->b_has_locals = done = 1; 359*7c478bd9Sstevel@tonic-gate errlog(VERBOSE, 360*7c478bd9Sstevel@tonic-gate "set has_locals on bucket 0x%p", b); 361*7c478bd9Sstevel@tonic-gate break; 362*7c478bd9Sstevel@tonic-gate } 363*7c478bd9Sstevel@tonic-gate } 364*7c478bd9Sstevel@tonic-gate if (b != NULL && b->b_has_locals == 1) 365*7c478bd9Sstevel@tonic-gate break; 366*7c478bd9Sstevel@tonic-gate } 367*7c478bd9Sstevel@tonic-gate if (done == 0) { 368*7c478bd9Sstevel@tonic-gate errlog(WARNING, "has_locals never set"); 369*7c478bd9Sstevel@tonic-gate } 370*7c478bd9Sstevel@tonic-gate errlog(END, "}"); 371*7c478bd9Sstevel@tonic-gate } 372*7c478bd9Sstevel@tonic-gate 373*7c478bd9Sstevel@tonic-gate 374*7c478bd9Sstevel@tonic-gate /* 375*7c478bd9Sstevel@tonic-gate * Output interfaces, mostly iterators 376*7c478bd9Sstevel@tonic-gate */ 377*7c478bd9Sstevel@tonic-gate 378*7c478bd9Sstevel@tonic-gate 379*7c478bd9Sstevel@tonic-gate /* 380*7c478bd9Sstevel@tonic-gate * parents_of -- return a list of all parents. 381*7c478bd9Sstevel@tonic-gate */ 382*7c478bd9Sstevel@tonic-gate char ** 383*7c478bd9Sstevel@tonic-gate parents_of(const bucket_t *start) 384*7c478bd9Sstevel@tonic-gate { 385*7c478bd9Sstevel@tonic-gate static char *a[NPAR] = {NULL}; 386*7c478bd9Sstevel@tonic-gate const bucket_t *b = start; 387*7c478bd9Sstevel@tonic-gate char **p = &a[0]; 388*7c478bd9Sstevel@tonic-gate 389*7c478bd9Sstevel@tonic-gate assert(start != NULL, "passed a null start to parents_of"); 390*7c478bd9Sstevel@tonic-gate errlog(BEGIN, "parents_of() {"); 391*7c478bd9Sstevel@tonic-gate a[0] = '\0'; 392*7c478bd9Sstevel@tonic-gate 393*7c478bd9Sstevel@tonic-gate /* Go to parent, print it and all its uncle. */ 394*7c478bd9Sstevel@tonic-gate if (b->b_parent == NULL) { 395*7c478bd9Sstevel@tonic-gate errlog(TRACING, "returning empty string"); 396*7c478bd9Sstevel@tonic-gate errlog(END, "}"); 397*7c478bd9Sstevel@tonic-gate return (a); 398*7c478bd9Sstevel@tonic-gate } 399*7c478bd9Sstevel@tonic-gate b = b->b_parent; 400*7c478bd9Sstevel@tonic-gate *p++ = b->b_name; 401*7c478bd9Sstevel@tonic-gate *p = '\0'; 402*7c478bd9Sstevel@tonic-gate 403*7c478bd9Sstevel@tonic-gate assert(p < &a[NPAR], "p fell off the end of a in parents_of"); 404*7c478bd9Sstevel@tonic-gate errlog(END, "}"); 405*7c478bd9Sstevel@tonic-gate return (a); 406*7c478bd9Sstevel@tonic-gate } 407*7c478bd9Sstevel@tonic-gate 408*7c478bd9Sstevel@tonic-gate /* 409*7c478bd9Sstevel@tonic-gate * first, next_from_bucket --iterators for bucket contents. Serially 410*7c478bd9Sstevel@tonic-gate * reusable only. 411*7c478bd9Sstevel@tonic-gate */ 412*7c478bd9Sstevel@tonic-gate int Ic = -1; 413*7c478bd9Sstevel@tonic-gate 414*7c478bd9Sstevel@tonic-gate /* 415*7c478bd9Sstevel@tonic-gate * debugging interfaces 416*7c478bd9Sstevel@tonic-gate */ 417*7c478bd9Sstevel@tonic-gate void 418*7c478bd9Sstevel@tonic-gate print_bucket(const bucket_t *b) 419*7c478bd9Sstevel@tonic-gate { 420*7c478bd9Sstevel@tonic-gate 421*7c478bd9Sstevel@tonic-gate errlog(TRACING, "bucket_t at 0x%p {", (void *)b); 422*7c478bd9Sstevel@tonic-gate errlog(TRACING, " char *b_name = \"%s\";", b->b_name); 423*7c478bd9Sstevel@tonic-gate errlog(TRACING, " struct bucket_t *b_parent = 0x%p;", 424*7c478bd9Sstevel@tonic-gate (void *)b->b_parent); 425*7c478bd9Sstevel@tonic-gate errlog(TRACING, " struct bucketlist *b_uncles = 0x%p;", 426*7c478bd9Sstevel@tonic-gate (void *)b->b_uncles); 427*7c478bd9Sstevel@tonic-gate errlog(TRACING, " struct bucket_t *b_thread = 0x%p;", 428*7c478bd9Sstevel@tonic-gate (void *)b->b_thread); 429*7c478bd9Sstevel@tonic-gate errlog(TRACING, " int b_has_locals = %d;", 430*7c478bd9Sstevel@tonic-gate b->b_has_locals); 431*7c478bd9Sstevel@tonic-gate errlog(TRACING, " int b_has_protecteds = %d;", 432*7c478bd9Sstevel@tonic-gate b->b_has_protecteds); 433*7c478bd9Sstevel@tonic-gate errlog(TRACING, " int b_was_printed = %d;", 434*7c478bd9Sstevel@tonic-gate b->b_was_printed); 435*7c478bd9Sstevel@tonic-gate errlog(TRACING, " int b_weak = %d;", 436*7c478bd9Sstevel@tonic-gate b->b_weak); 437*7c478bd9Sstevel@tonic-gate errlog(TRACING, " table_t *b_global_table = 0x%p;", 438*7c478bd9Sstevel@tonic-gate (void *)b->b_global_table); 439*7c478bd9Sstevel@tonic-gate errlog(TRACING, " table_t *b_protected_table = 0x%p;", 440*7c478bd9Sstevel@tonic-gate (void *)b->b_protected_table); 441*7c478bd9Sstevel@tonic-gate errlog(TRACING, "}"); 442*7c478bd9Sstevel@tonic-gate } 443*7c478bd9Sstevel@tonic-gate 444*7c478bd9Sstevel@tonic-gate void 445*7c478bd9Sstevel@tonic-gate print_all_buckets(void) 446*7c478bd9Sstevel@tonic-gate { 447*7c478bd9Sstevel@tonic-gate bucket_t *l, *b; 448*7c478bd9Sstevel@tonic-gate int i = 0, j = 0; 449*7c478bd9Sstevel@tonic-gate char **p; 450*7c478bd9Sstevel@tonic-gate 451*7c478bd9Sstevel@tonic-gate for (i = 0, l = first_list(); l != NULL; l = next_list(), ++i) { 452*7c478bd9Sstevel@tonic-gate errlog(TRACING, "list %d", i); 453*7c478bd9Sstevel@tonic-gate for (j = 0, b = first_from_list(l); 454*7c478bd9Sstevel@tonic-gate b != NULL; b = next_from_list(), ++j) { 455*7c478bd9Sstevel@tonic-gate errlog(TRACING, "bucket %d", j); 456*7c478bd9Sstevel@tonic-gate print_bucket(b); 457*7c478bd9Sstevel@tonic-gate errlog(TRACING, "global interfaces = {"); 458*7c478bd9Sstevel@tonic-gate print_stringtable(b->b_global_table); 459*7c478bd9Sstevel@tonic-gate errlog(TRACING, "}"); 460*7c478bd9Sstevel@tonic-gate errlog(TRACING, "protected interfaces = {"); 461*7c478bd9Sstevel@tonic-gate print_stringtable(b->b_protected_table); 462*7c478bd9Sstevel@tonic-gate errlog(TRACING, "}"); 463*7c478bd9Sstevel@tonic-gate 464*7c478bd9Sstevel@tonic-gate for (p = parents_of(b); p != NULL && *p != NULL; ++p) { 465*7c478bd9Sstevel@tonic-gate errlog(TRACING, " %s", *p); 466*7c478bd9Sstevel@tonic-gate } 467*7c478bd9Sstevel@tonic-gate errlog(TRACING, ";"); 468*7c478bd9Sstevel@tonic-gate 469*7c478bd9Sstevel@tonic-gate if (b->b_uncles) { 470*7c478bd9Sstevel@tonic-gate errlog(TRACING, " uncle bucket %d.1", j); 471*7c478bd9Sstevel@tonic-gate print_bucket(b->b_uncles->bl_bucket); 472*7c478bd9Sstevel@tonic-gate errlog(TRACING, "global interfaces = {"); 473*7c478bd9Sstevel@tonic-gate print_stringtable( 474*7c478bd9Sstevel@tonic-gate b->b_uncles->bl_bucket->b_global_table); 475*7c478bd9Sstevel@tonic-gate errlog(TRACING, "}"); 476*7c478bd9Sstevel@tonic-gate errlog(TRACING, "protected interfaces = {"); 477*7c478bd9Sstevel@tonic-gate print_stringtable( 478*7c478bd9Sstevel@tonic-gate b->b_uncles->bl_bucket->b_protected_table); 479*7c478bd9Sstevel@tonic-gate errlog(TRACING, "}"); 480*7c478bd9Sstevel@tonic-gate } 481*7c478bd9Sstevel@tonic-gate } 482*7c478bd9Sstevel@tonic-gate } 483*7c478bd9Sstevel@tonic-gate } 484*7c478bd9Sstevel@tonic-gate 485*7c478bd9Sstevel@tonic-gate 486*7c478bd9Sstevel@tonic-gate /* 487*7c478bd9Sstevel@tonic-gate * lower-level functions, not visible outside the file. 488*7c478bd9Sstevel@tonic-gate */ 489*7c478bd9Sstevel@tonic-gate 490*7c478bd9Sstevel@tonic-gate /* 491*7c478bd9Sstevel@tonic-gate * new_bucket -- create a bucket for a given version. Must not fail. 492*7c478bd9Sstevel@tonic-gate */ 493*7c478bd9Sstevel@tonic-gate static bucket_t * 494*7c478bd9Sstevel@tonic-gate new_bucket(const char *name, int weak) 495*7c478bd9Sstevel@tonic-gate { 496*7c478bd9Sstevel@tonic-gate bucket_t *b; 497*7c478bd9Sstevel@tonic-gate 498*7c478bd9Sstevel@tonic-gate if ((b = (bucket_t *)calloc(1, sizeof (bucket_t))) == NULL) { 499*7c478bd9Sstevel@tonic-gate errlog(FATAL, "out of memory creating a bucket " 500*7c478bd9Sstevel@tonic-gate "to store interfaces in"); 501*7c478bd9Sstevel@tonic-gate } 502*7c478bd9Sstevel@tonic-gate if ((b->b_name = strdup(name)) == NULL) { 503*7c478bd9Sstevel@tonic-gate errlog(FATAL, "out of memory storing an interface " 504*7c478bd9Sstevel@tonic-gate "in a version bucket"); 505*7c478bd9Sstevel@tonic-gate } 506*7c478bd9Sstevel@tonic-gate b->b_uncles = NULL; 507*7c478bd9Sstevel@tonic-gate b->b_global_table = create_stringtable(TABLE_INITIAL); 508*7c478bd9Sstevel@tonic-gate b->b_protected_table = create_stringtable(TABLE_INITIAL); 509*7c478bd9Sstevel@tonic-gate b->b_weak = weak; 510*7c478bd9Sstevel@tonic-gate return (b); 511*7c478bd9Sstevel@tonic-gate } 512*7c478bd9Sstevel@tonic-gate 513*7c478bd9Sstevel@tonic-gate 514*7c478bd9Sstevel@tonic-gate /* 515*7c478bd9Sstevel@tonic-gate * start_new_list -- start a list of buckets. 516*7c478bd9Sstevel@tonic-gate */ 517*7c478bd9Sstevel@tonic-gate static void 518*7c478bd9Sstevel@tonic-gate start_new_list(const bucket_t *b) 519*7c478bd9Sstevel@tonic-gate { 520*7c478bd9Sstevel@tonic-gate int i; 521*7c478bd9Sstevel@tonic-gate 522*7c478bd9Sstevel@tonic-gate errlog(BEGIN, "start_new_list() {"); 523*7c478bd9Sstevel@tonic-gate assert(Buckethead != NULL, "Buckethead null in start_new_list"); 524*7c478bd9Sstevel@tonic-gate for (i = 0; Buckethead[i] != NULL && i < N_lists; ++i) 525*7c478bd9Sstevel@tonic-gate continue; 526*7c478bd9Sstevel@tonic-gate if (i >= N_lists) { 527*7c478bd9Sstevel@tonic-gate grow_lists(); 528*7c478bd9Sstevel@tonic-gate } 529*7c478bd9Sstevel@tonic-gate Buckethead[i] = (bucket_t *)b; 530*7c478bd9Sstevel@tonic-gate errlog(END, "}"); 531*7c478bd9Sstevel@tonic-gate } 532*7c478bd9Sstevel@tonic-gate 533*7c478bd9Sstevel@tonic-gate /* 534*7c478bd9Sstevel@tonic-gate * grow_list -- make more lists. This should never occur... 535*7c478bd9Sstevel@tonic-gate */ 536*7c478bd9Sstevel@tonic-gate static void 537*7c478bd9Sstevel@tonic-gate grow_lists(void) 538*7c478bd9Sstevel@tonic-gate { 539*7c478bd9Sstevel@tonic-gate int i = N_lists; 540*7c478bd9Sstevel@tonic-gate 541*7c478bd9Sstevel@tonic-gate errlog(BEGIN, "grow_lists() {"); 542*7c478bd9Sstevel@tonic-gate errlog(WARNING, "Warning: more than %d version lists " 543*7c478bd9Sstevel@tonic-gate "required (< %d is normal). Check sets file " 544*7c478bd9Sstevel@tonic-gate "to see why so many lines appear.", 545*7c478bd9Sstevel@tonic-gate N_lists, NLISTS); 546*7c478bd9Sstevel@tonic-gate 547*7c478bd9Sstevel@tonic-gate N_lists *= 2; 548*7c478bd9Sstevel@tonic-gate if ((Buckethead = realloc(Buckethead, sizeof (bucket_t *) * N_lists)) 549*7c478bd9Sstevel@tonic-gate == NULL) { 550*7c478bd9Sstevel@tonic-gate errlog(FATAL, "out of memory growing list of " 551*7c478bd9Sstevel@tonic-gate "version buckets"); 552*7c478bd9Sstevel@tonic-gate } 553*7c478bd9Sstevel@tonic-gate for (; i < N_lists; ++i) { 554*7c478bd9Sstevel@tonic-gate Buckethead[i] = NULL; 555*7c478bd9Sstevel@tonic-gate } 556*7c478bd9Sstevel@tonic-gate } 557*7c478bd9Sstevel@tonic-gate 558*7c478bd9Sstevel@tonic-gate /* 559*7c478bd9Sstevel@tonic-gate * delete_lists -- clean up afterwards. 560*7c478bd9Sstevel@tonic-gate */ 561*7c478bd9Sstevel@tonic-gate void 562*7c478bd9Sstevel@tonic-gate delete_lists(void) 563*7c478bd9Sstevel@tonic-gate { 564*7c478bd9Sstevel@tonic-gate N_lists = 0; 565*7c478bd9Sstevel@tonic-gate free(Buckethead); 566*7c478bd9Sstevel@tonic-gate Buckethead = 0; 567*7c478bd9Sstevel@tonic-gate } 568*7c478bd9Sstevel@tonic-gate 569*7c478bd9Sstevel@tonic-gate /* 570*7c478bd9Sstevel@tonic-gate * first_list, next_list -- an iterator for lists themselves. Serially 571*7c478bd9Sstevel@tonic-gate * reusable only. 572*7c478bd9Sstevel@tonic-gate */ 573*7c478bd9Sstevel@tonic-gate bucket_t * 574*7c478bd9Sstevel@tonic-gate first_list(void) 575*7c478bd9Sstevel@tonic-gate { 576*7c478bd9Sstevel@tonic-gate Bc = 0; 577*7c478bd9Sstevel@tonic-gate return (Buckethead[Bc]); 578*7c478bd9Sstevel@tonic-gate } 579*7c478bd9Sstevel@tonic-gate 580*7c478bd9Sstevel@tonic-gate bucket_t * 581*7c478bd9Sstevel@tonic-gate next_list(void) 582*7c478bd9Sstevel@tonic-gate { 583*7c478bd9Sstevel@tonic-gate return (Buckethead[++Bc]); 584*7c478bd9Sstevel@tonic-gate } 585*7c478bd9Sstevel@tonic-gate 586*7c478bd9Sstevel@tonic-gate 587*7c478bd9Sstevel@tonic-gate /* 588*7c478bd9Sstevel@tonic-gate * first, next, last_from_list -- iterators for individual lists. Serially 589*7c478bd9Sstevel@tonic-gate * reusable only. 590*7c478bd9Sstevel@tonic-gate */ 591*7c478bd9Sstevel@tonic-gate bucket_t * 592*7c478bd9Sstevel@tonic-gate first_from_list(const bucket_t *l) 593*7c478bd9Sstevel@tonic-gate { 594*7c478bd9Sstevel@tonic-gate return (Bp = (bucket_t *)l); 595*7c478bd9Sstevel@tonic-gate } 596*7c478bd9Sstevel@tonic-gate 597*7c478bd9Sstevel@tonic-gate bucket_t * 598*7c478bd9Sstevel@tonic-gate next_from_list(void) 599*7c478bd9Sstevel@tonic-gate { 600*7c478bd9Sstevel@tonic-gate return (Bp = Bp->b_parent); 601*7c478bd9Sstevel@tonic-gate } 602*7c478bd9Sstevel@tonic-gate 603*7c478bd9Sstevel@tonic-gate 604*7c478bd9Sstevel@tonic-gate 605*7c478bd9Sstevel@tonic-gate /* 606*7c478bd9Sstevel@tonic-gate * Iface print utility 607*7c478bd9Sstevel@tonic-gate */ 608*7c478bd9Sstevel@tonic-gate static void 609*7c478bd9Sstevel@tonic-gate print_iface(const Interface * p) 610*7c478bd9Sstevel@tonic-gate { 611*7c478bd9Sstevel@tonic-gate 612*7c478bd9Sstevel@tonic-gate errlog(TRACING, "%s (%s, %s, %s %d)", p->IF_name, 613*7c478bd9Sstevel@tonic-gate (p->IF_type == FUNCTION) ? "function" : 614*7c478bd9Sstevel@tonic-gate (p->IF_type == DATA) ? "data" : "unknown type", 615*7c478bd9Sstevel@tonic-gate (p->IF_version) ? p->IF_version : "unknown version", 616*7c478bd9Sstevel@tonic-gate (p->IF_class) ? p->IF_class : "unknown class", 617*7c478bd9Sstevel@tonic-gate p->IF_binding); 618*7c478bd9Sstevel@tonic-gate } 619*7c478bd9Sstevel@tonic-gate 620*7c478bd9Sstevel@tonic-gate 621*7c478bd9Sstevel@tonic-gate 622*7c478bd9Sstevel@tonic-gate #define HASHMAPSIZE 100 623*7c478bd9Sstevel@tonic-gate #define ERR (-1) 624*7c478bd9Sstevel@tonic-gate 625*7c478bd9Sstevel@tonic-gate static struct { 626*7c478bd9Sstevel@tonic-gate hashmap_t *hh_map; 627*7c478bd9Sstevel@tonic-gate int hh_map_size; 628*7c478bd9Sstevel@tonic-gate int hh_mapC; 629*7c478bd9Sstevel@tonic-gate hashmap_t *hh_last; 630*7c478bd9Sstevel@tonic-gate } Hashhead = { 631*7c478bd9Sstevel@tonic-gate NULL, -1, -1, NULL 632*7c478bd9Sstevel@tonic-gate }; 633*7c478bd9Sstevel@tonic-gate 634*7c478bd9Sstevel@tonic-gate static int checksum(const char *); 635*7c478bd9Sstevel@tonic-gate static void print_hashmap(const hashmap_t *); 636*7c478bd9Sstevel@tonic-gate 637*7c478bd9Sstevel@tonic-gate /* 638*7c478bd9Sstevel@tonic-gate * new_hashmap -- create the hash. 639*7c478bd9Sstevel@tonic-gate */ 640*7c478bd9Sstevel@tonic-gate static void 641*7c478bd9Sstevel@tonic-gate new_hashmap(void) 642*7c478bd9Sstevel@tonic-gate { 643*7c478bd9Sstevel@tonic-gate 644*7c478bd9Sstevel@tonic-gate errlog(BEGIN, "new_hashmap() {"); 645*7c478bd9Sstevel@tonic-gate if ((Hashhead.hh_map = calloc(sizeof (hashmap_t), HASHMAPSIZE)) 646*7c478bd9Sstevel@tonic-gate == NULL) { 647*7c478bd9Sstevel@tonic-gate errlog(FATAL, "out of memory creating a hash-map of " 648*7c478bd9Sstevel@tonic-gate "the versions"); 649*7c478bd9Sstevel@tonic-gate } 650*7c478bd9Sstevel@tonic-gate Hashhead.hh_mapC = 0; 651*7c478bd9Sstevel@tonic-gate errlog(END, "}"); 652*7c478bd9Sstevel@tonic-gate } 653*7c478bd9Sstevel@tonic-gate 654*7c478bd9Sstevel@tonic-gate /* 655*7c478bd9Sstevel@tonic-gate * add_to_hashmap -- add a bucket to the map. This is strictly for 656*7c478bd9Sstevel@tonic-gate * use by add_parent()/add_uncle(). 657*7c478bd9Sstevel@tonic-gate */ 658*7c478bd9Sstevel@tonic-gate static int 659*7c478bd9Sstevel@tonic-gate add_to_hashmap(const char *version_name, const bucket_t *bucket) 660*7c478bd9Sstevel@tonic-gate { 661*7c478bd9Sstevel@tonic-gate hashmap_t *p; 662*7c478bd9Sstevel@tonic-gate 663*7c478bd9Sstevel@tonic-gate assert(Hashhead.hh_map != NULL, 664*7c478bd9Sstevel@tonic-gate "Hashead.map was null in add_to_hashmap"); 665*7c478bd9Sstevel@tonic-gate assert(Hashhead.hh_mapC < HASHMAPSIZE, 666*7c478bd9Sstevel@tonic-gate "mapC too big in add_to_hashmap"); 667*7c478bd9Sstevel@tonic-gate errlog(BEGIN, "add_to_hashmap(%s, %s) {", version_name, bucket); 668*7c478bd9Sstevel@tonic-gate if (find_in_hashmap(version_name) != NULL) { 669*7c478bd9Sstevel@tonic-gate /* Seen for the second time. TBD... */ 670*7c478bd9Sstevel@tonic-gate errlog(END, "} /* add_to_hashmap */"); 671*7c478bd9Sstevel@tonic-gate return (ERR); 672*7c478bd9Sstevel@tonic-gate } 673*7c478bd9Sstevel@tonic-gate p = &Hashhead.hh_map[Hashhead.hh_mapC++]; 674*7c478bd9Sstevel@tonic-gate if ((p->h_version_name = strdup(version_name)) == NULL) { 675*7c478bd9Sstevel@tonic-gate errlog(FATAL, "out of memory storing a version name"); 676*7c478bd9Sstevel@tonic-gate 677*7c478bd9Sstevel@tonic-gate } 678*7c478bd9Sstevel@tonic-gate p->h_bucket = (bucket_t *)bucket; 679*7c478bd9Sstevel@tonic-gate p->h_hash = checksum(version_name); 680*7c478bd9Sstevel@tonic-gate Hashhead.hh_last = p; 681*7c478bd9Sstevel@tonic-gate print_hashmap(p); 682*7c478bd9Sstevel@tonic-gate errlog(END, "} /* add_to_hashmap */"); 683*7c478bd9Sstevel@tonic-gate return (0); 684*7c478bd9Sstevel@tonic-gate } 685*7c478bd9Sstevel@tonic-gate 686*7c478bd9Sstevel@tonic-gate 687*7c478bd9Sstevel@tonic-gate /* 688*7c478bd9Sstevel@tonic-gate * find_in_hashmap -- find a bucket by name. Strictly for use by addByName(). 689*7c478bd9Sstevel@tonic-gate */ 690*7c478bd9Sstevel@tonic-gate static bucket_t * 691*7c478bd9Sstevel@tonic-gate find_in_hashmap(const char *version_name) 692*7c478bd9Sstevel@tonic-gate { 693*7c478bd9Sstevel@tonic-gate hashmap_t *current; 694*7c478bd9Sstevel@tonic-gate int hash = checksum(version_name); 695*7c478bd9Sstevel@tonic-gate 696*7c478bd9Sstevel@tonic-gate assert(Hashhead.hh_map != NULL, 697*7c478bd9Sstevel@tonic-gate "Hashhead.hh_map was null in find_in_hashmap"); 698*7c478bd9Sstevel@tonic-gate errlog(BEGIN, "find_in_hashmap(%s) {", version_name); 699*7c478bd9Sstevel@tonic-gate if (Hashhead.hh_last != NULL && Hashhead.hh_last->h_hash == hash && 700*7c478bd9Sstevel@tonic-gate strcmp(Hashhead.hh_last->h_version_name, version_name) == 0) { 701*7c478bd9Sstevel@tonic-gate errlog(END, "}"); 702*7c478bd9Sstevel@tonic-gate return (Hashhead.hh_last->h_bucket); 703*7c478bd9Sstevel@tonic-gate } 704*7c478bd9Sstevel@tonic-gate for (current = Hashhead.hh_map; 705*7c478bd9Sstevel@tonic-gate current->h_version_name != NULL; ++current) { 706*7c478bd9Sstevel@tonic-gate if (current->h_hash == hash && 707*7c478bd9Sstevel@tonic-gate strcmp(current->h_version_name, version_name) == 0) { 708*7c478bd9Sstevel@tonic-gate /* Found it */ 709*7c478bd9Sstevel@tonic-gate Hashhead.hh_last = current; 710*7c478bd9Sstevel@tonic-gate errlog(END, "}"); 711*7c478bd9Sstevel@tonic-gate return (current->h_bucket); 712*7c478bd9Sstevel@tonic-gate } 713*7c478bd9Sstevel@tonic-gate } 714*7c478bd9Sstevel@tonic-gate /* Doesn't exist, meaning version name is bogus. */ 715*7c478bd9Sstevel@tonic-gate errlog(END, "}"); 716*7c478bd9Sstevel@tonic-gate return (NULL); 717*7c478bd9Sstevel@tonic-gate } 718*7c478bd9Sstevel@tonic-gate 719*7c478bd9Sstevel@tonic-gate /* 720*7c478bd9Sstevel@tonic-gate * checksum -- from sum(1), algorithm 1. 721*7c478bd9Sstevel@tonic-gate */ 722*7c478bd9Sstevel@tonic-gate static int 723*7c478bd9Sstevel@tonic-gate checksum(const char *p) 724*7c478bd9Sstevel@tonic-gate { 725*7c478bd9Sstevel@tonic-gate int sum; 726*7c478bd9Sstevel@tonic-gate 727*7c478bd9Sstevel@tonic-gate for (sum = 0; *p != NULL; ++p) { 728*7c478bd9Sstevel@tonic-gate if (sum & 01) 729*7c478bd9Sstevel@tonic-gate sum = (sum >> 1) + 0x8000; 730*7c478bd9Sstevel@tonic-gate else 731*7c478bd9Sstevel@tonic-gate sum >>= 1; 732*7c478bd9Sstevel@tonic-gate sum += *p; 733*7c478bd9Sstevel@tonic-gate sum &= 0xFFFF; 734*7c478bd9Sstevel@tonic-gate } 735*7c478bd9Sstevel@tonic-gate return (sum); 736*7c478bd9Sstevel@tonic-gate } 737*7c478bd9Sstevel@tonic-gate 738*7c478bd9Sstevel@tonic-gate static void 739*7c478bd9Sstevel@tonic-gate print_hashmap(const hashmap_t *h) 740*7c478bd9Sstevel@tonic-gate { 741*7c478bd9Sstevel@tonic-gate errlog(VERBOSE, "struct hashmap_t at 0x4.4x {", h); 742*7c478bd9Sstevel@tonic-gate errlog(VERBOSE, " int h_hash = %d;", h->h_hash); 743*7c478bd9Sstevel@tonic-gate errlog(VERBOSE, " char *h_version_name = \"%s\";", 744*7c478bd9Sstevel@tonic-gate h->h_version_name); 745*7c478bd9Sstevel@tonic-gate errlog(VERBOSE, " bucket_t *h_bucket = 0x%p;;", 746*7c478bd9Sstevel@tonic-gate (void *) h->h_bucket); 747*7c478bd9Sstevel@tonic-gate errlog(VERBOSE, "}"); 748*7c478bd9Sstevel@tonic-gate } 749