xref: /illumos-gate/usr/src/cmd/sgs/libconv/common/globals.c (revision 4f680cc668fa6cf678c531083400ade9a9c7934c)
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 (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #include	<stdio.h>
28 #include	<strings.h>
29 #include	<ctype.h>
30 #include	<_machelf.h>
31 #include	"_conv.h"
32 #include	"globals_msg.h"
33 
34 
35 /*
36  * Map an integer into a descriptive string.
37  *
38  * entry:
39  *	inv_buf - A buffer into which this routine can format
40  *		a result string, if necessary.
41  *	val - The value for which a string is desired.
42  *	flags - CONV_FMT_* values to be passed to conv_invalid_val() if
43  *		necessary. The caller is reponsible for having examined
44  *		the CONV_FMT_ALT_* part of flags and passing the proper
45  *		msg array.
46  *	num_msg - # of Msg entries in msg.
47  *	msg - Array of num_msg Msg items corresponding to the possible
48  *		strings corresponding to val.
49  *	local_sgs_msg - Message string table from module from which
50  *		this function is called.
51  *
52  * exit:
53  *	If val lies in the range [0-(num_msg-1)], then the string
54  *	corresponding to it is returned. If val is outside the range,
55  *	conv_invalid_val() is called to format an ASCII representation
56  *	of it into inv_buf, and that is returned.
57  */
58 /*ARGSUSED5*/
59 static const char *
60 map_msg2str(Conv_inv_buf_t *inv_buf, Conv_elfvalue_t val,
61     Conv_fmt_flags_t flags, size_t num_msg, const Msg *msg,
62     const char *local_sgs_msg)
63 {
64 	if ((val < num_msg) && (msg[val] != 0))
65 		return (MSG_ORIG_STRTAB(msg[val], local_sgs_msg));
66 
67 	/* If we get here, it's an unknown value */
68 	return (conv_invalid_val(inv_buf, val, flags));
69 }
70 
71 /*
72  * Map an integer into a descriptive string from a NULL terminated
73  * array of Val_desc or Val_desc2 descriptors.
74  *
75  * entry:
76  *	inv_buf - A buffer into which this routine can format
77  *		a result string, if necessary.
78  *	osabi,mach (_conv_vd22str only) - The osab/mach under which
79  *		val is to be interpreted. Items with a non-0 osabi or machine
80  *		that do not match are quietly ignored.
81  *	val - The value for which a string is desired.
82  *	flags - CONV_FMT_* values to be passed to conv_invalid_val() if
83  *		necessary. The caller is reponsible for having examined
84  *		the CONV_FMT_ALT_* part of flags and passing the proper
85  *		descriptor array.
86  *	vdp - Pointer to NULL terminated array of Val_desc descriptors.
87  *	local_sgs_msg - Message string table from module from which
88  *		this function is called.
89  *
90  * exit:
91  *	If val is found in the vdp array, and in the osabi version of
92  *	this function if the osabi matches, then the string corresponding
93  *	val is returned. If a string for val is not found, conv_invalid_val()
94  *	is called to format an ASCII representation of it into inv_buf, and
95  *	that is returned.
96  */
97 /*ARGSUSED4*/
98 static const char *
99 map_vd2str(Conv_inv_buf_t *inv_buf, Conv_elfvalue_t val,
100     Conv_fmt_flags_t flags, const Val_desc *vdp, const char *local_sgs_msg)
101 {
102 	for (; vdp->v_msg; vdp++) {
103 		if (val == vdp->v_val)
104 			return (MSG_ORIG_STRTAB(vdp->v_msg, local_sgs_msg));
105 	}
106 
107 	/* If we get here, it's an unknown value */
108 	return (conv_invalid_val(inv_buf, val, flags));
109 }
110 
111 /*ARGSUSED6*/
112 static const char *
113 map_vd22str(Conv_inv_buf_t *inv_buf, uchar_t osabi, Half mach,
114     Conv_elfvalue_t val, Conv_fmt_flags_t flags, const Val_desc2 *vdp,
115     const char *local_sgs_msg)
116 {
117 	for (; vdp->v_msg; vdp++) {
118 		if (CONV_VD2_SKIP(osabi, mach, vdp))
119 			continue;
120 
121 		if (val == vdp->v_val)
122 			return (MSG_ORIG_STRTAB(vdp->v_msg, local_sgs_msg));
123 	}
124 
125 	/* If we get here, it's an unknown value */
126 	return (conv_invalid_val(inv_buf, val, flags));
127 }
128 
129 /*
130  * Process an array of conv_ds_XXX_t structures and call the appropriate
131  * map functions for the format of the strings given.
132  */
133 const char *
134 _conv_map_ds(uchar_t osabi, Half mach, Conv_elfvalue_t value,
135     const conv_ds_t **dsp, Conv_fmt_flags_t fmt_flags, Conv_inv_buf_t *inv_buf,
136     const char *local_sgs_msg)
137 {
138 	const conv_ds_t *ds;
139 
140 	for (ds = *dsp; ds != NULL; ds = *(++dsp)) {
141 		if ((value < ds->ds_baseval) || (value > ds->ds_topval))
142 			continue;
143 
144 		switch (ds->ds_type) {
145 		case CONV_DS_MSGARR:
146 			return (map_msg2str(inv_buf, value - ds->ds_baseval,
147 			    fmt_flags, ds->ds_topval - ds->ds_baseval + 1,
148 			    /*LINTED*/
149 			    ((conv_ds_msg_t *)ds)->ds_msg,
150 			    local_sgs_msg));
151 
152 		case CONV_DS_VD:
153 			return (map_vd2str(inv_buf, value, fmt_flags,
154 			    /*LINTED*/
155 			    ((conv_ds_vd_t *)ds)->ds_vd,
156 			    local_sgs_msg));
157 
158 		case CONV_DS_VD2:
159 			return (map_vd22str(inv_buf, osabi, mach, value,
160 			    fmt_flags,
161 			    /*LINTED*/
162 			    ((conv_ds_vd2_t *)ds)->ds_vd2,
163 			    local_sgs_msg));
164 		}
165 	}
166 
167 	return (conv_invalid_val(inv_buf, value, fmt_flags));
168 }
169 
170 /*
171  * Iterate over every message string in a given array of Msg codes,
172  * calling a user supplied callback for each one.
173  *
174  * entry:
175  *	basevalue - Value corresponding to the first Msg in the array.
176  *	local_sgs_msg - Pointer to the __sgs_msg array for the
177  *		libconv module making the call.
178  *	num_msg - # of items in array referenced by msg
179  *	msg - Array of Msg indexes for the strings to iterate over.
180  *		The value corresponding to each element of msg must be:
181  *			value[i] = basevalue + i
182  *	func, uvalue - User supplied function to be called for each
183  *		string in msg. uvalue is an arbitrary user supplied pointer
184  *		to be passed to func.
185  *	local_sgs_msg - Pointer to the __sgs_msg array for the
186  *		libconv module making the call.
187  *
188  * exit:
189  *	The callback function is called for every non-zero item in
190  *	msg[]. If any callback returns CONV_ITER_DONE, execution stops
191  *	with that item and the function returns immediately. Otherwise,
192  *	it continues to the end of the array.
193  *
194  *	The value from the last callback is returned.
195  */
196 /*ARGSUSED5*/
197 static conv_iter_ret_t
198 _conv_iter_msgarr(uint32_t basevalue, const Msg *msg, size_t num_msg,
199     conv_iter_cb_t func, void *uvalue, const char *local_sgs_msg)
200 {
201 	for (; num_msg-- > 0; basevalue++, msg++) {
202 		if (*msg != 0)
203 			if ((* func)(MSG_ORIG_STRTAB(*msg, local_sgs_msg),
204 			    basevalue, uvalue) == CONV_ITER_DONE)
205 				return (CONV_ITER_DONE);
206 	}
207 
208 	return (CONV_ITER_CONT);
209 }
210 
211 /*
212  * Iterate over every message string in a given array of Val_desc or
213  * Val_desc2 descriptors, calling a user supplied callback for each one.
214  *
215  * entry:
216  *	osabi,mach (_conv_iter_vd2 only) - The osabi/mach for which
217  *		strings are desired. Strings with a non-0 osabi or machine
218  *		that do not match are quietly ignored.
219  *	vdp - Pointer to NULL terminated array of Val_desc descriptors.
220  *	func, uvalue - User supplied function to be called for each
221  *		string in msg. uvalue is an arbitrary user supplied pointer
222  *		to be passed to func.
223  *	local_sgs_msg - Pointer to the __sgs_msg array for the
224  *		libconv module making the call.
225  *
226  * exit:
227  *	The callback function is called for every descriptor referenced by
228  *	vdp. In the case of the OSABI-version of this function, strings from
229  *	the wrong osabi are not used. If any callback returns CONV_ITER_DONE,
230  *	execution stops with that item and the function returns immediately.
231  *	Otherwise, it continues to the end of the array.
232  *
233  *	The value from the last callback is returned.
234  */
235 /*ARGSUSED3*/
236 conv_iter_ret_t
237 _conv_iter_vd(const Val_desc *vdp, conv_iter_cb_t func, void *uvalue,
238     const char *local_sgs_msg)
239 {
240 	for (; vdp->v_msg; vdp++) {
241 		if ((* func)(MSG_ORIG_STRTAB(vdp->v_msg, local_sgs_msg),
242 		    vdp->v_val, uvalue) == CONV_ITER_DONE)
243 			return (CONV_ITER_DONE);
244 	}
245 
246 	return (CONV_ITER_CONT);
247 }
248 
249 /*ARGSUSED5*/
250 conv_iter_ret_t
251 _conv_iter_vd2(conv_iter_osabi_t osabi, Half mach, const Val_desc2 *vdp,
252     conv_iter_cb_t func, void *uvalue, const char *local_sgs_msg)
253 {
254 	for (; vdp->v_msg; vdp++) {
255 		if (CONV_ITER_VD2_SKIP(osabi, mach, vdp))
256 			continue;
257 
258 		if ((* func)(MSG_ORIG_STRTAB(vdp->v_msg, local_sgs_msg),
259 		    vdp->v_val, uvalue) == CONV_ITER_DONE)
260 			return (CONV_ITER_DONE);
261 	}
262 
263 	return (CONV_ITER_CONT);
264 }
265 
266 /*
267  * Process an array of conv_ds_XXX_t structures and call the appropriate
268  * iteration functions for the format of the strings given.
269  */
270 conv_iter_ret_t
271 _conv_iter_ds(conv_iter_osabi_t osabi, Half mach, const conv_ds_t **dsp,
272     conv_iter_cb_t func, void *uvalue, const char *local_sgs_msg)
273 {
274 	const conv_ds_t *ds;
275 
276 	for (ds = *dsp; ds != NULL; ds = *(++dsp)) {
277 		switch (ds->ds_type) {
278 		case CONV_DS_MSGARR:
279 			if (_conv_iter_msgarr(ds->ds_baseval,
280 			    /*LINTED*/
281 			    ((conv_ds_msg_t *)ds)->ds_msg,
282 			    ds->ds_topval - ds->ds_baseval + 1, func, uvalue,
283 			    local_sgs_msg) == CONV_ITER_DONE)
284 				return (CONV_ITER_DONE);
285 			break;
286 
287 		case CONV_DS_VD:
288 			/*LINTED*/
289 			if (_conv_iter_vd(((conv_ds_vd_t *)ds)->ds_vd,
290 			    func, uvalue, local_sgs_msg) == CONV_ITER_DONE)
291 				return (CONV_ITER_DONE);
292 			break;
293 
294 		case CONV_DS_VD2:
295 			if (_conv_iter_vd2(osabi, mach,
296 			    /*LINTED*/
297 			    ((conv_ds_vd2_t *)ds)->ds_vd2,
298 			    func, uvalue, local_sgs_msg) == CONV_ITER_DONE)
299 				return (CONV_ITER_DONE);
300 			break;
301 		}
302 	}
303 
304 	return (CONV_ITER_CONT);
305 }
306 
307 /*
308  * Initialize the uvalue block prior to use of an interation function
309  * employing conv_iter_strtol().
310  *
311  * entry:
312  *	str - String to be matched to a value
313  *	uvalue - Pointer to uninitialized uvalue block
314  *
315  * exit:
316  *	Initializes the uvalue block for use. Returns True (1) if a non-empty
317  *	string was supplied, and False (0).
318  */
319 int
320 conv_iter_strtol_init(const char *str, conv_strtol_uvalue_t *uvalue)
321 {
322 	const char	*tail;
323 
324 	while (isspace(*str))
325 		str++;
326 	uvalue->csl_str = str;
327 	uvalue->csl_found = 0;
328 
329 	tail = str + strlen(str);
330 	while ((tail > str) && isspace(*(tail - 1)))
331 		tail--;
332 	uvalue->csl_strlen = tail - str;
333 
334 	return (uvalue->csl_strlen > 0);
335 }
336 
337 /*
338  * conv_iter_strtol() is used with iteration functions to map a string
339  * to the value of its corresponding ELF constant.
340  *
341  * entry:
342  *	str - String supplied by this iteration
343  *	value - Value of ELF constant corresponding to str
344  *	uvalue - Pointer to conv_strtol_uvalue_t block previously
345  *		initialized by a call to conv_iter_strtol_init().
346  */
347 conv_iter_ret_t
348 conv_iter_strtol(const char *str, uint32_t value, void *uvalue)
349 {
350 	conv_strtol_uvalue_t *state = (conv_strtol_uvalue_t *)uvalue;
351 
352 	if ((strlen(str) == state->csl_strlen) &&
353 	    (strncasecmp(str, state->csl_str, state->csl_strlen) == 0)) {
354 		state->csl_found = 1;
355 		state->csl_value = value;
356 		return (CONV_ITER_DONE);	/* Found it. Stop now. */
357 	}
358 
359 	return (CONV_ITER_CONT);		/* Keep looking */
360 }
361