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