globals.c revision 4734:a4708faa3e85
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 2007 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26#pragma ident	"%Z%%M%	%I%	%E% SMI"
27
28#include	<stdio.h>
29#include	<strings.h>
30#include	<sys/machelf.h>
31#include	"_conv.h"
32#include	"globals_msg.h"
33
34
35/*
36 * Given an integer value, generate an ASCII representation of it.
37 *
38 * entry:
39 *	inv_buf - Buffer into which the resulting string is generated.
40 *	value - Value to be formatted.
41 *	fmt_flags - CONV_FMT_* values, used to specify formatting details.
42 *
43 * exit:
44 *	The formatted string is placed into inv_buf. The pointer
45 *	to the string is returned.
46 */
47const char *
48conv_invalid_val(Conv_inv_buf_t *inv_buf, Xword value, int fmt_flags)
49{
50	const char	*fmt;
51
52	if (fmt_flags & CONV_FMT_DECIMAL) {
53		if (fmt_flags & CONV_FMT_SPACE)
54			fmt = MSG_ORIG(MSG_GBL_FMT_DECS);
55		else
56			fmt = MSG_ORIG(MSG_GBL_FMT_DEC);
57	} else {
58		if (fmt_flags & CONV_FMT_SPACE)
59			fmt = MSG_ORIG(MSG_GBL_FMT_HEXS);
60		else
61			fmt = MSG_ORIG(MSG_GBL_FMT_HEX);
62	}
63	(void) snprintf(inv_buf->buf, sizeof (inv_buf->buf), fmt, value);
64	return ((const char *)inv_buf->buf);
65}
66
67
68
69/*
70 * cef_cp() is used by conv_expn_field() to fill in the output buffer.
71 * A CONV_EXPN_FIELD_STATE variable is used to maintain the buffer state
72 * as the operation progresses.
73 *
74 * entry:
75 *	arg - As passed to conv_expn_field().
76 *	state - Variable used to maintain buffer state between calls.
77 *	list_item - TRUE(1) if this is a list item, and FALSE(0)
78 *		if it is something else.
79 *	str - String to be added to the buffer.
80 *
81 * exit:
82 *	On Success:
83 *		buffer contains the output string, including a list
84 *		separator if appropriate. state has been updated.
85 *		TRUE(1) is returned.
86 *	On Failure:
87 *		Buffer contains the numeric representation for the flags,
88 *		and FALSE(0) is returned.
89 */
90typedef struct {
91	char *cur;		/* Current output position in buf */
92	size_t room;		/* # of bytes left in buf */
93	int list_cnt;		/* # of list items output into buf  */
94	const char *sep_str;	/* String used as list separator */
95	int sep_str_len;	/* strlen(sep_str) */
96} CONV_EXPN_FIELD_STATE;
97
98static int
99cef_cp(CONV_EXPN_FIELD_ARG *arg, CONV_EXPN_FIELD_STATE *state,
100	int list_item, const char *str)
101{
102	Conv_inv_buf_t inv_buf;
103	int n;
104
105	if (list_item) {	/* This is a list item */
106		/*
107		 * If list is non-empty, and the buffer has room,
108		 * then insert the separator.
109		 */
110		if (state->list_cnt != 0) {
111			if (state->sep_str_len < state->room) {
112				(void) memcpy(state->cur, state->sep_str,
113				    state->sep_str_len);
114				state->cur += state->sep_str_len;
115				state->room -= state->sep_str_len;
116			} else {
117				/* Ensure code below will catch lack of room */
118				state->room = 0;
119			}
120		}
121		state->list_cnt++;
122	}
123
124	n = strlen(str);
125	if (n < state->room) {
126		(void) memcpy(state->cur, str, n);
127		state->cur += n;
128		state->room -= n;
129		return (TRUE);
130	}
131
132	/* Buffer too small. Fill in the numeric value and report failure */
133	(void) conv_invalid_val(&inv_buf, arg->oflags, 0);
134	(void) strlcpy(arg->buf, inv_buf.buf, arg->bufsize);
135	return (FALSE);
136}
137
138
139
140/*
141 * Provide a focal point for expanding bit-fields values into
142 * their corresponding strings.
143 *
144 * entry:
145 *	arg - Specifies the operation to be carried out. See the
146 *		definition of CONV_EXPN_FIELD_ARG in conv.h for details.
147 *
148 * exit:
149 *	arg->buf contains the formatted result. True (1) is returned if there
150 *	was no error, and False (0) if the buffer was too small. In the failure
151 *	case, arg->buf contains a numeric representation of the value.
152 */
153int
154conv_expn_field(CONV_EXPN_FIELD_ARG *arg)
155{
156	const Val_desc *vde;
157	CONV_EXPN_FIELD_STATE state;
158	Xword rflags = arg->rflags;
159	const char **lead_str;
160
161
162	/* Initialize buffer state */
163	state.cur = arg->buf;
164	state.room = arg->bufsize;
165	state.list_cnt = 0;
166	state.sep_str = arg->sep ? arg->sep : MSG_ORIG(MSG_GBL_SEP);
167	state.sep_str_len = strlen(state.sep_str);
168
169	/* Prefix string */
170	if (!cef_cp(arg, &state, FALSE,
171	    (arg->prefix ? arg->prefix : MSG_ORIG(MSG_GBL_OSQBRKT))))
172		return (FALSE);
173
174	/* Any strings in the lead_str array go at the head of the list */
175	lead_str = arg->lead_str;
176	if (lead_str) {
177		while (*lead_str) {
178			if (!cef_cp(arg, &state, TRUE, *lead_str++))
179				return (FALSE);
180		}
181	}
182
183	/*
184	 * Traverse the callers Val_desc array and determine if the value
185	 * corresponds to any array item and add those that are to the list.
186	 */
187	for (vde = arg->vdp; vde->v_msg; vde++) {
188		if (arg->oflags & vde->v_val) {
189			if (!cef_cp(arg, &state, TRUE, vde->v_msg))
190				return (FALSE);
191
192			/* Indicate this item has been collected */
193			rflags &= ~(vde->v_val);
194		}
195	}
196
197	/*
198	 * If any flags remain, then they are unidentified.  Add the numeric
199	 * representation of these flags to the users output buffer.
200	 */
201	if (rflags) {
202		Conv_inv_buf_t inv_buf;
203
204		(void) conv_invalid_val(&inv_buf, rflags, 0);
205		if (!cef_cp(arg, &state, TRUE, inv_buf.buf))
206			return (FALSE);
207	}
208
209	/* Suffix string */
210	if (!cef_cp(arg, &state, FALSE,
211	    (arg->suffix ? arg->suffix : MSG_ORIG(MSG_GBL_CSQBRKT))))
212		return (FALSE);
213
214	/* Terminate the buffer */
215	*state.cur = '\0';
216
217	return (TRUE);
218}
219