1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright (c) 1997-1999 by Sun Microsystems, Inc. 24 * All rights reserved. 25 */ 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * util.c -- low-level utilities used by map*.c 30 */ 31 #include <stdio.h> 32 #include <string.h> 33 #include <errno.h> 34 #include <stdlib.h> 35 #include "xlator.h" 36 #include "util.h" 37 #include "errlog.h" 38 39 /* 40 * String tables -- WARNING! This uses realloc to recreate tables, 41 * so always assign table_t * return value to the current 42 * table pointer, lest the table address change in the 43 * called function. 44 */ 45 static char *strset(char *, char *); 46 47 table_t * 48 create_stringtable(int size) 49 { 50 table_t *t; 51 52 /* Solaris idiom: malloc && memset. TBD. */ 53 if ((t = calloc((size_t)1, (size_t)(sizeof (table_t) + 54 ((sizeof (char *)) * size)))) == NULL) { 55 errlog(FATAL, 56 "\nOut of memory.\n" 57 "We wish to hold the whole sky,\n" 58 "But we never will.\n"); 59 } 60 t->nelem = size; 61 t->used = -1; 62 return (t); 63 } 64 65 66 table_t * 67 add_to_stringtable(table_t *t, char *value) 68 { 69 table_t *t2; 70 71 int i; 72 73 if (t == NULL) { 74 seterrline(__LINE__, __FILE__, NULL, NULL); 75 errlog(FATAL|PROGRAM, "programmer error: tried to add to " 76 "a NULL table"); 77 } 78 if (in_stringtable(t, value)) { 79 return (t); 80 } 81 ++t->used; 82 if (t->used >= t->nelem) { 83 if ((t2 = realloc(t, (size_t)(sizeof (table_t) + 84 ((sizeof (char *)) * (t->nelem + TABLE_INCREMENT))))) 85 == NULL) { 86 print_stringtable(t); 87 seterrline(__LINE__, __FILE__, NULL, NULL); 88 errlog(FATAL|PROGRAM, "out of memory extending a " 89 "string table"); 90 } 91 t = t2; 92 t->nelem += TABLE_INCREMENT; 93 for (i = t->used; i < t->nelem; ++i) { 94 t->elements[i] = NULL; 95 } 96 } 97 t->elements[t->used] = strset(t->elements[t->used], value); 98 return (t); 99 } 100 101 /* 102 * free_stringtable -- really only mark it empty for reuse. 103 */ 104 table_t * 105 free_stringtable(table_t *t) 106 { 107 108 if (t != NULL) { 109 t->used = -1; 110 } 111 return (t); 112 } 113 114 115 char * 116 get_stringtable(table_t *t, int index) 117 { 118 119 if (t == NULL) { 120 return (NULL); 121 } else if (index > t->used) { 122 return (NULL); 123 } else { 124 return (t->elements[index]); 125 } 126 } 127 128 int 129 in_stringtable(table_t *t, const char *value) 130 { 131 int i; 132 133 if (t == NULL) { 134 return (0); 135 } 136 for (i = 0; i <= t->used; ++i) { 137 if (strcmp(value, t->elements[i]) == 0) 138 return (1); 139 } 140 return (0); 141 } 142 143 144 void 145 print_stringtable(table_t *t) 146 { 147 int i; 148 149 if (t == NULL) 150 return; 151 152 errlog(VERBOSE, 153 "table size = %d elements out of %d elements/%d bytes\n", 154 t->used + 1, t->nelem, 155 sizeof (table_t) + (sizeof (char *) * t->nelem)); 156 157 for (i = 0; i <= t->used; ++i) { 158 (void) fprintf(stderr, "\t%s\n", 159 get_stringtable(t, i)); 160 } 161 } 162 163 static int 164 compare(const void *p, const void *q) 165 { 166 return (strcmp((char *)p, (char *)q)); 167 } 168 169 void 170 sort_stringtable(table_t *t) 171 { 172 173 if (t && t->used > 0) { 174 qsort((char *)t->elements, (size_t)t->used, 175 sizeof (char *), compare); 176 } 177 } 178 179 180 /* 181 * strset -- update a dynamically-allocated string or die trying. 182 */ 183 /*ARGSUSED*/ 184 static char * 185 strset(char *string, char *value) 186 { 187 size_t vlen; 188 189 assert(value != NULL, "passed a null value to strset"); 190 vlen = strlen(value); 191 if (string == NULL) { 192 /* It was never allocated, so allocate it. */ 193 if ((string = malloc(vlen + 1)) == NULL) { 194 seterrline(__LINE__, __FILE__, NULL, NULL); 195 errlog(FATAL|PROGRAM, "out of memory allocating a " 196 "string"); 197 } 198 } else if (strlen(string) < vlen) { 199 /* Reallocate bigger. */ 200 if ((string = realloc(string, vlen + 1)) == NULL) { 201 seterrline(__LINE__, __FILE__, NULL, NULL); 202 errlog(FATAL|PROGRAM, "out of memory reallocating" 203 "a string"); 204 } 205 } 206 (void) strcpy(string, value); 207 return (string); 208 } 209