globals.c revision 2352:9cdfed81bb1c
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 2006 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 *	string - Buffer into which the resulting string is generated.
40 *	size - Size of string buffer (i.e. sizeof(string))
41 *	value - Value to be formatted.
42 *	fmt_flags - CONV_FMT_* values, used to specify formatting details.
43 *
44 * exit:
45 *	The formatted string, or as much as will fit, is placed into
46 *	string. String is returned.
47 */
48const char *
49conv_invalid_val(char *string, size_t size, Xword value, int fmt_flags)
50{
51	const char	*fmt;
52
53	if (fmt_flags & CONV_FMT_DECIMAL) {
54		if (fmt_flags & CONV_FMT_SPACE)
55			fmt = MSG_ORIG(MSG_GBL_FMT_DECS);
56		else
57			fmt = MSG_ORIG(MSG_GBL_FMT_DEC);
58	} else {
59		if (fmt_flags & CONV_FMT_SPACE)
60			fmt = MSG_ORIG(MSG_GBL_FMT_HEXS);
61		else
62			fmt = MSG_ORIG(MSG_GBL_FMT_HEX);
63	}
64	(void) snprintf(string, size, fmt, value);
65	return ((const char *)string);
66}
67
68
69
70/*
71 * cef_cp() is used by conv_expn_field() to fill in the output buffer.
72 * A CONV_EXPN_FIELD_STATE variable is used to maintain the buffer state
73 * as the operation progresses.
74 *
75 * entry:
76 *	arg - As passed to conv_expn_field().
77 *	state - Variable used to maintain buffer state between calls.
78 *	list_item - TRUE(1) if this is a list item, and FALSE(0)
79 *		if it is something else.
80 *	str - String to be added to the buffer.
81 *
82 * exit:
83 *	On Success:
84 *		buffer contains the output string, including a list
85 *		separator if appropriate. state has been updated.
86 *		TRUE(1) is returned.
87 *	On Failure:
88 *		Buffer contains the numeric representation for the flags,
89 *		and FALSE(0) is returned.
90 */
91typedef struct {
92	char *cur;		/* Current output position in buf */
93	size_t room;		/* # of bytes left in buf */
94	int list_cnt;		/* # of list items output into buf  */
95	const char *sep_str;	/* String used as list separator */
96	int sep_str_len;	/* strlen(sep_str) */
97} CONV_EXPN_FIELD_STATE;
98
99static int
100cef_cp(CONV_EXPN_FIELD_ARG *arg, CONV_EXPN_FIELD_STATE *state,
101	int list_item, const char *str)
102{
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(arg->buf, arg->bufsize, arg->oflags, 0);
134	return (FALSE);
135}
136
137
138
139/*
140 * Provide a focal point for expanding bit-fields values into
141 * their corresponding strings.
142 *
143 * entry:
144 *	arg - Specifies the operation to be carried out. See the
145 *		definition of CONV_EXPN_FIELD_ARG in conv.h for details.
146 *
147 * exit:
148 *	arg->buf contains the formatted result. True (1) is returned if there
149 *	was no error, and False (0) if the buffer was too small. In the failure
150 *	case, arg->buf contains a numeric representation of the value.
151 */
152int
153conv_expn_field(CONV_EXPN_FIELD_ARG *arg)
154{
155	const Val_desc *vde;
156	CONV_EXPN_FIELD_STATE state;
157	Xword rflags = arg->rflags;
158	const char **lead_str;
159
160
161	/* Initialize buffer state */
162	state.cur = arg->buf;
163	state.room = arg->bufsize;
164	state.list_cnt = 0;
165	state.sep_str = arg->sep ? arg->sep : MSG_ORIG(MSG_GBL_SEP);
166	state.sep_str_len = strlen(state.sep_str);
167
168	/* Prefix string */
169	if (!cef_cp(arg, &state, FALSE,
170	    (arg->prefix ? arg->prefix : MSG_ORIG(MSG_GBL_OSQBRKT))))
171		return (FALSE);
172
173	/* Any strings in the lead_str array go at the head of the list */
174	lead_str = arg->lead_str;
175	if (lead_str) {
176		while (*lead_str) {
177			if (!cef_cp(arg, &state, TRUE, *lead_str++))
178				return (FALSE);
179		}
180	}
181
182	/*
183	 * Traverse the callers Val_desc array and determine if the value
184	 * corresponds to any array item and add those that are to the list.
185	 */
186	for (vde = arg->vdp; vde->v_msg; vde++) {
187		if (arg->oflags & vde->v_val) {
188			if (!cef_cp(arg, &state, TRUE, vde->v_msg))
189				return (FALSE);
190
191			/* Indicate this item has been collected */
192			rflags &= ~(vde->v_val);
193		}
194	}
195
196	/*
197	 * If any flags remain, then they are unidentified.  Add the numeric
198	 * representation of these flags to the users output buffer.
199	 */
200	if (rflags) {
201		char ibuf[CONV_INV_STRSIZE];
202
203		(void) conv_invalid_val(ibuf, sizeof (ibuf), rflags, 0);
204		if (!cef_cp(arg, &state, TRUE, ibuf))
205			return (FALSE);
206	}
207
208	/* Suffix string */
209	if (!cef_cp(arg, &state, FALSE,
210	    (arg->suffix ? arg->suffix : MSG_ORIG(MSG_GBL_CSQBRKT))))
211		return (FALSE);
212
213	/* Terminate the buffer */
214	*state.cur = '\0';
215
216	return (TRUE);
217}
218