globals.c revision 2850:689acf945b89
1251881Speter/*
2251881Speter * CDDL HEADER START
3251881Speter *
4251881Speter * The contents of this file are subject to the terms of the
5251881Speter * Common Development and Distribution License (the "License").
6251881Speter * You may not use this file except in compliance with the License.
7251881Speter *
8251881Speter * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9251881Speter * or http://www.opensolaris.org/os/licensing.
10251881Speter * See the License for the specific language governing permissions
11251881Speter * and limitations under the License.
12251881Speter *
13251881Speter * When distributing Covered Code, include this CDDL HEADER in each
14251881Speter * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15251881Speter * If applicable, add the following below this CDDL HEADER, with the
16251881Speter * fields enclosed by brackets "[]" replaced with your own identifying
17251881Speter * information: Portions Copyright [yyyy] [name of copyright owner]
18251881Speter *
19251881Speter * CDDL HEADER END
20251881Speter */
21251881Speter
22251881Speter/*
23251881Speter * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24251881Speter * Use is subject to license terms.
25251881Speter */
26251881Speter#pragma ident	"%Z%%M%	%I%	%E% SMI"
27251881Speter
28251881Speter#include	<stdio.h>
29251881Speter#include	<strings.h>
30251881Speter#include	<sys/machelf.h>
31251881Speter#include	"_conv.h"
32251881Speter#include	"globals_msg.h"
33251881Speter
34251881Speter
35251881Speter/*
36251881Speter * Given an integer value, generate an ASCII representation of it.
37251881Speter *
38251881Speter * entry:
39251881Speter *	string - Buffer into which the resulting string is generated.
40251881Speter *	size - Size of string buffer (i.e. sizeof(string))
41251881Speter *	value - Value to be formatted.
42251881Speter *	fmt_flags - CONV_FMT_* values, used to specify formatting details.
43251881Speter *
44251881Speter * exit:
45251881Speter *	The formatted string, or as much as will fit, is placed into
46251881Speter *	string. String is returned.
47251881Speter */
48251881Speterconst char *
49251881Speterconv_invalid_val(char *string, size_t size, Xword value, int fmt_flags)
50251881Speter{
51251881Speter	const char	*fmt;
52251881Speter
53251881Speter	if (fmt_flags & CONV_FMT_DECIMAL) {
54251881Speter		if (fmt_flags & CONV_FMT_SPACE)
55251881Speter			fmt = MSG_ORIG(MSG_GBL_FMT_DECS);
56251881Speter		else
57251881Speter			fmt = MSG_ORIG(MSG_GBL_FMT_DEC);
58251881Speter	} else {
59251881Speter		if (fmt_flags & CONV_FMT_SPACE)
60251881Speter			fmt = MSG_ORIG(MSG_GBL_FMT_HEXS);
61251881Speter		else
62251881Speter			fmt = MSG_ORIG(MSG_GBL_FMT_HEX);
63251881Speter	}
64251881Speter	(void) snprintf(string, size, fmt, value);
65251881Speter	return ((const char *)string);
66251881Speter}
67251881Speter
68251881Speter
69251881Speter
70251881Speter/*
71251881Speter * cef_cp() is used by conv_expn_field() to fill in the output buffer.
72251881Speter * A CONV_EXPN_FIELD_STATE variable is used to maintain the buffer state
73251881Speter * as the operation progresses.
74251881Speter *
75251881Speter * entry:
76251881Speter *	arg - As passed to conv_expn_field().
77251881Speter *	state - Variable used to maintain buffer state between calls.
78251881Speter *	list_item - TRUE(1) if this is a list item, and FALSE(0)
79251881Speter *		if it is something else.
80251881Speter *	str - String to be added to the buffer.
81251881Speter *
82251881Speter * exit:
83251881Speter *	On Success:
84251881Speter *		buffer contains the output string, including a list
85251881Speter *		separator if appropriate. state has been updated.
86251881Speter *		TRUE(1) is returned.
87251881Speter *	On Failure:
88251881Speter *		Buffer contains the numeric representation for the flags,
89251881Speter *		and FALSE(0) is returned.
90251881Speter */
91251881Spetertypedef struct {
92251881Speter	char *cur;		/* Current output position in buf */
93251881Speter	size_t room;		/* # of bytes left in buf */
94251881Speter	int list_cnt;		/* # of list items output into buf  */
95251881Speter	const char *sep_str;	/* String used as list separator */
96251881Speter	int sep_str_len;	/* strlen(sep_str) */
97251881Speter} CONV_EXPN_FIELD_STATE;
98251881Speter
99251881Speterstatic int
100251881Spetercef_cp(CONV_EXPN_FIELD_ARG *arg, CONV_EXPN_FIELD_STATE *state,
101251881Speter	int list_item, const char *str)
102251881Speter{
103251881Speter	int n;
104251881Speter
105251881Speter	if (list_item) {	/* This is a list item */
106251881Speter		/*
107251881Speter		 * If list is non-empty, and the buffer has room,
108251881Speter		 * then insert the separator.
109251881Speter		 */
110251881Speter		if (state->list_cnt != 0) {
111251881Speter			if (state->sep_str_len < state->room) {
112251881Speter				(void) memcpy(state->cur, state->sep_str,
113251881Speter					state->sep_str_len);
114251881Speter				state->cur += state->sep_str_len;
115251881Speter				state->room -= state->sep_str_len;
116251881Speter			} else {
117251881Speter				/* Ensure code below will catch lack of room */
118251881Speter				state->room = 0;
119251881Speter			}
120251881Speter		}
121251881Speter		state->list_cnt++;
122251881Speter	}
123251881Speter
124251881Speter	n = strlen(str);
125251881Speter	if (n < state->room) {
126251881Speter		(void) memcpy(state->cur, str, n);
127251881Speter		state->cur += n;
128251881Speter		state->room -= n;
129251881Speter		return (TRUE);
130251881Speter	}
131251881Speter
132251881Speter	/* Buffer too small. Fill in the numeric value and report failure */
133251881Speter	(void) conv_invalid_val(arg->buf, arg->bufsize, arg->oflags, 0);
134251881Speter	return (FALSE);
135251881Speter}
136251881Speter
137251881Speter
138251881Speter
139251881Speter/*
140251881Speter * Provide a focal point for expanding bit-fields values into
141251881Speter * their corresponding strings.
142251881Speter *
143251881Speter * entry:
144251881Speter *	arg - Specifies the operation to be carried out. See the
145251881Speter *		definition of CONV_EXPN_FIELD_ARG in conv.h for details.
146251881Speter *
147251881Speter * exit:
148251881Speter *	arg->buf contains the formatted result. True (1) is returned if there
149251881Speter *	was no error, and False (0) if the buffer was too small. In the failure
150251881Speter *	case, arg->buf contains a numeric representation of the value.
151251881Speter */
152251881Speterint
153251881Speterconv_expn_field(CONV_EXPN_FIELD_ARG *arg)
154251881Speter{
155251881Speter	const Val_desc *vde;
156251881Speter	CONV_EXPN_FIELD_STATE state;
157251881Speter	Xword rflags = arg->rflags;
158251881Speter	const char **lead_str;
159251881Speter
160251881Speter
161251881Speter	/* Initialize buffer state */
162251881Speter	state.cur = arg->buf;
163251881Speter	state.room = arg->bufsize;
164251881Speter	state.list_cnt = 0;
165251881Speter	state.sep_str = arg->sep ? arg->sep : MSG_ORIG(MSG_GBL_SEP);
166251881Speter	state.sep_str_len = strlen(state.sep_str);
167251881Speter
168251881Speter	/* Prefix string */
169251881Speter	if (!cef_cp(arg, &state, FALSE,
170251881Speter	    (arg->prefix ? arg->prefix : MSG_ORIG(MSG_GBL_OSQBRKT))))
171251881Speter		return (FALSE);
172251881Speter
173251881Speter	/* Any strings in the lead_str array go at the head of the list */
174251881Speter	lead_str = arg->lead_str;
175251881Speter	if (lead_str) {
176251881Speter		while (*lead_str) {
177251881Speter			if (!cef_cp(arg, &state, TRUE, *lead_str++))
178251881Speter				return (FALSE);
179251881Speter		}
180251881Speter	}
181251881Speter
182251881Speter	/*
183251881Speter	 * Traverse the callers Val_desc array and determine if the value
184251881Speter	 * corresponds to any array item and add those that are to the list.
185251881Speter	 */
186251881Speter	for (vde = arg->vdp; vde->v_msg; vde++) {
187251881Speter		if (arg->oflags & vde->v_val) {
188251881Speter			if (!cef_cp(arg, &state, TRUE, vde->v_msg))
189251881Speter				return (FALSE);
190251881Speter
191251881Speter			/* Indicate this item has been collected */
192251881Speter			rflags &= ~(vde->v_val);
193251881Speter		}
194251881Speter	}
195251881Speter
196251881Speter	/*
197251881Speter	 * If any flags remain, then they are unidentified.  Add the numeric
198251881Speter	 * representation of these flags to the users output buffer.
199251881Speter	 */
200251881Speter	if (rflags) {
201251881Speter		Conv_inv_buf_t ibuf;
202251881Speter
203251881Speter		(void) conv_invalid_val(ibuf, sizeof (ibuf), rflags, 0);
204251881Speter		if (!cef_cp(arg, &state, TRUE, ibuf))
205251881Speter			return (FALSE);
206251881Speter	}
207251881Speter
208251881Speter	/* Suffix string */
209251881Speter	if (!cef_cp(arg, &state, FALSE,
210251881Speter	    (arg->suffix ? arg->suffix : MSG_ORIG(MSG_GBL_CSQBRKT))))
211251881Speter		return (FALSE);
212251881Speter
213251881Speter	/* Terminate the buffer */
214251881Speter	*state.cur = '\0';
215251881Speter
216251881Speter	return (TRUE);
217251881Speter}
218251881Speter