1*9273SAli.Bahrami@Sun.COM /*
2*9273SAli.Bahrami@Sun.COM * CDDL HEADER START
3*9273SAli.Bahrami@Sun.COM *
4*9273SAli.Bahrami@Sun.COM * The contents of this file are subject to the terms of the
5*9273SAli.Bahrami@Sun.COM * Common Development and Distribution License (the "License").
6*9273SAli.Bahrami@Sun.COM * You may not use this file except in compliance with the License.
7*9273SAli.Bahrami@Sun.COM *
8*9273SAli.Bahrami@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*9273SAli.Bahrami@Sun.COM * or http://www.opensolaris.org/os/licensing.
10*9273SAli.Bahrami@Sun.COM * See the License for the specific language governing permissions
11*9273SAli.Bahrami@Sun.COM * and limitations under the License.
12*9273SAli.Bahrami@Sun.COM *
13*9273SAli.Bahrami@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
14*9273SAli.Bahrami@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*9273SAli.Bahrami@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
16*9273SAli.Bahrami@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
17*9273SAli.Bahrami@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
18*9273SAli.Bahrami@Sun.COM *
19*9273SAli.Bahrami@Sun.COM * CDDL HEADER END
20*9273SAli.Bahrami@Sun.COM */
21*9273SAli.Bahrami@Sun.COM
22*9273SAli.Bahrami@Sun.COM /*
23*9273SAli.Bahrami@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24*9273SAli.Bahrami@Sun.COM * Use is subject to license terms.
25*9273SAli.Bahrami@Sun.COM */
26*9273SAli.Bahrami@Sun.COM
27*9273SAli.Bahrami@Sun.COM #include <stdio.h>
28*9273SAli.Bahrami@Sun.COM #include <strings.h>
29*9273SAli.Bahrami@Sun.COM #include <_machelf.h>
30*9273SAli.Bahrami@Sun.COM #include "_conv.h"
31*9273SAli.Bahrami@Sun.COM #include "globals_msg.h"
32*9273SAli.Bahrami@Sun.COM
33*9273SAli.Bahrami@Sun.COM
34*9273SAli.Bahrami@Sun.COM /*
35*9273SAli.Bahrami@Sun.COM * Given an integer value, generate an ASCII representation of it.
36*9273SAli.Bahrami@Sun.COM *
37*9273SAli.Bahrami@Sun.COM * entry:
38*9273SAli.Bahrami@Sun.COM * inv_buf - Buffer into which the resulting string is generated.
39*9273SAli.Bahrami@Sun.COM * value - Value to be formatted.
40*9273SAli.Bahrami@Sun.COM * fmt_flags - CONV_FMT_* values, used to specify formatting details.
41*9273SAli.Bahrami@Sun.COM *
42*9273SAli.Bahrami@Sun.COM * exit:
43*9273SAli.Bahrami@Sun.COM * The formatted string is placed into inv_buf. The pointer
44*9273SAli.Bahrami@Sun.COM * to the string is returned.
45*9273SAli.Bahrami@Sun.COM */
46*9273SAli.Bahrami@Sun.COM const char *
conv_invalid_val(Conv_inv_buf_t * inv_buf,Xword value,Conv_fmt_flags_t fmt_flags)47*9273SAli.Bahrami@Sun.COM conv_invalid_val(Conv_inv_buf_t *inv_buf, Xword value,
48*9273SAli.Bahrami@Sun.COM Conv_fmt_flags_t fmt_flags)
49*9273SAli.Bahrami@Sun.COM {
50*9273SAli.Bahrami@Sun.COM const char *fmt;
51*9273SAli.Bahrami@Sun.COM
52*9273SAli.Bahrami@Sun.COM if (fmt_flags & CONV_FMT_DECIMAL) {
53*9273SAli.Bahrami@Sun.COM if (fmt_flags & CONV_FMT_SPACE)
54*9273SAli.Bahrami@Sun.COM fmt = MSG_ORIG(MSG_GBL_FMT_DECS);
55*9273SAli.Bahrami@Sun.COM else
56*9273SAli.Bahrami@Sun.COM fmt = MSG_ORIG(MSG_GBL_FMT_DEC);
57*9273SAli.Bahrami@Sun.COM } else {
58*9273SAli.Bahrami@Sun.COM if (fmt_flags & CONV_FMT_SPACE)
59*9273SAli.Bahrami@Sun.COM fmt = MSG_ORIG(MSG_GBL_FMT_HEXS);
60*9273SAli.Bahrami@Sun.COM else
61*9273SAli.Bahrami@Sun.COM fmt = MSG_ORIG(MSG_GBL_FMT_HEX);
62*9273SAli.Bahrami@Sun.COM }
63*9273SAli.Bahrami@Sun.COM (void) snprintf(inv_buf->buf, sizeof (inv_buf->buf), fmt, value);
64*9273SAli.Bahrami@Sun.COM return ((const char *)inv_buf->buf);
65*9273SAli.Bahrami@Sun.COM }
66*9273SAli.Bahrami@Sun.COM
67*9273SAli.Bahrami@Sun.COM
68*9273SAli.Bahrami@Sun.COM
69*9273SAli.Bahrami@Sun.COM /*
70*9273SAli.Bahrami@Sun.COM * cef_cp() is used by conv_expn_field() to fill in the output buffer.
71*9273SAli.Bahrami@Sun.COM * A CONV_EXPN_FIELD_STATE variable is used to maintain the buffer state
72*9273SAli.Bahrami@Sun.COM * as the operation progresses.
73*9273SAli.Bahrami@Sun.COM *
74*9273SAli.Bahrami@Sun.COM * entry:
75*9273SAli.Bahrami@Sun.COM * arg - As passed to conv_expn_field().
76*9273SAli.Bahrami@Sun.COM * state - Variable used to maintain buffer state between calls.
77*9273SAli.Bahrami@Sun.COM * list_item - TRUE(1) if this is a list item, and FALSE(0)
78*9273SAli.Bahrami@Sun.COM * if it is something else.
79*9273SAli.Bahrami@Sun.COM * str - String to be added to the buffer.
80*9273SAli.Bahrami@Sun.COM *
81*9273SAli.Bahrami@Sun.COM * exit:
82*9273SAli.Bahrami@Sun.COM * On Success:
83*9273SAli.Bahrami@Sun.COM * buffer contains the output string, including a list
84*9273SAli.Bahrami@Sun.COM * separator if appropriate. state has been updated.
85*9273SAli.Bahrami@Sun.COM * TRUE(1) is returned.
86*9273SAli.Bahrami@Sun.COM * On Failure:
87*9273SAli.Bahrami@Sun.COM * Buffer contains the numeric representation for the flags,
88*9273SAli.Bahrami@Sun.COM * and FALSE(0) is returned.
89*9273SAli.Bahrami@Sun.COM */
90*9273SAli.Bahrami@Sun.COM typedef struct {
91*9273SAli.Bahrami@Sun.COM char *cur; /* Current output position in buf */
92*9273SAli.Bahrami@Sun.COM size_t room; /* # of bytes left in buf */
93*9273SAli.Bahrami@Sun.COM int list_cnt; /* # of list items output into buf */
94*9273SAli.Bahrami@Sun.COM const char *sep_str; /* String used as list separator */
95*9273SAli.Bahrami@Sun.COM int sep_str_len; /* strlen(sep_str) */
96*9273SAli.Bahrami@Sun.COM } CONV_EXPN_FIELD_STATE;
97*9273SAli.Bahrami@Sun.COM
98*9273SAli.Bahrami@Sun.COM static int
cef_cp(CONV_EXPN_FIELD_ARG * arg,CONV_EXPN_FIELD_STATE * state,int list_item,const char * str)99*9273SAli.Bahrami@Sun.COM cef_cp(CONV_EXPN_FIELD_ARG *arg, CONV_EXPN_FIELD_STATE *state,
100*9273SAli.Bahrami@Sun.COM int list_item, const char *str)
101*9273SAli.Bahrami@Sun.COM {
102*9273SAli.Bahrami@Sun.COM Conv_inv_buf_t inv_buf;
103*9273SAli.Bahrami@Sun.COM int n;
104*9273SAli.Bahrami@Sun.COM
105*9273SAli.Bahrami@Sun.COM if (list_item) { /* This is a list item */
106*9273SAli.Bahrami@Sun.COM /*
107*9273SAli.Bahrami@Sun.COM * If list is non-empty, and the buffer has room,
108*9273SAli.Bahrami@Sun.COM * then insert the separator.
109*9273SAli.Bahrami@Sun.COM */
110*9273SAli.Bahrami@Sun.COM if (state->list_cnt != 0) {
111*9273SAli.Bahrami@Sun.COM if (state->sep_str_len < state->room) {
112*9273SAli.Bahrami@Sun.COM (void) memcpy(state->cur, state->sep_str,
113*9273SAli.Bahrami@Sun.COM state->sep_str_len);
114*9273SAli.Bahrami@Sun.COM state->cur += state->sep_str_len;
115*9273SAli.Bahrami@Sun.COM state->room -= state->sep_str_len;
116*9273SAli.Bahrami@Sun.COM } else {
117*9273SAli.Bahrami@Sun.COM /* Ensure code below will catch lack of room */
118*9273SAli.Bahrami@Sun.COM state->room = 0;
119*9273SAli.Bahrami@Sun.COM }
120*9273SAli.Bahrami@Sun.COM }
121*9273SAli.Bahrami@Sun.COM state->list_cnt++;
122*9273SAli.Bahrami@Sun.COM }
123*9273SAli.Bahrami@Sun.COM
124*9273SAli.Bahrami@Sun.COM n = strlen(str);
125*9273SAli.Bahrami@Sun.COM if (n < state->room) {
126*9273SAli.Bahrami@Sun.COM (void) memcpy(state->cur, str, n);
127*9273SAli.Bahrami@Sun.COM state->cur += n;
128*9273SAli.Bahrami@Sun.COM state->room -= n;
129*9273SAli.Bahrami@Sun.COM return (TRUE);
130*9273SAli.Bahrami@Sun.COM }
131*9273SAli.Bahrami@Sun.COM
132*9273SAli.Bahrami@Sun.COM /* Buffer too small. Fill in the numeric value and report failure */
133*9273SAli.Bahrami@Sun.COM (void) conv_invalid_val(&inv_buf, arg->oflags, 0);
134*9273SAli.Bahrami@Sun.COM (void) strlcpy(arg->buf, inv_buf.buf, arg->bufsize);
135*9273SAli.Bahrami@Sun.COM return (FALSE);
136*9273SAli.Bahrami@Sun.COM }
137*9273SAli.Bahrami@Sun.COM
138*9273SAli.Bahrami@Sun.COM
139*9273SAli.Bahrami@Sun.COM
140*9273SAli.Bahrami@Sun.COM /*
141*9273SAli.Bahrami@Sun.COM * Common setup code for conv_expn_field() and conv_expn_field2()
142*9273SAli.Bahrami@Sun.COM */
143*9273SAli.Bahrami@Sun.COM static int
cef_setup(CONV_EXPN_FIELD_ARG * arg,Conv_fmt_flags_t fmt_flags,CONV_EXPN_FIELD_STATE * state)144*9273SAli.Bahrami@Sun.COM cef_setup(CONV_EXPN_FIELD_ARG *arg, Conv_fmt_flags_t fmt_flags,
145*9273SAli.Bahrami@Sun.COM CONV_EXPN_FIELD_STATE *state)
146*9273SAli.Bahrami@Sun.COM {
147*9273SAli.Bahrami@Sun.COM const char **lead_str;
148*9273SAli.Bahrami@Sun.COM
149*9273SAli.Bahrami@Sun.COM /* Initialize buffer state */
150*9273SAli.Bahrami@Sun.COM state->cur = arg->buf;
151*9273SAli.Bahrami@Sun.COM state->room = arg->bufsize;
152*9273SAli.Bahrami@Sun.COM state->list_cnt = 0;
153*9273SAli.Bahrami@Sun.COM state->sep_str = arg->sep ? arg->sep : MSG_ORIG(MSG_GBL_SEP);
154*9273SAli.Bahrami@Sun.COM state->sep_str_len = strlen(state->sep_str);
155*9273SAli.Bahrami@Sun.COM
156*9273SAli.Bahrami@Sun.COM /* Prefix string */
157*9273SAli.Bahrami@Sun.COM if ((fmt_flags & CONV_FMT_NOBKT) == 0)
158*9273SAli.Bahrami@Sun.COM if (!cef_cp(arg, state, FALSE,
159*9273SAli.Bahrami@Sun.COM (arg->prefix ? arg->prefix : MSG_ORIG(MSG_GBL_OSQBRKT))))
160*9273SAli.Bahrami@Sun.COM return (FALSE);
161*9273SAli.Bahrami@Sun.COM
162*9273SAli.Bahrami@Sun.COM /* Any strings in the lead_str array go at the head of the list */
163*9273SAli.Bahrami@Sun.COM lead_str = arg->lead_str;
164*9273SAli.Bahrami@Sun.COM if (lead_str) {
165*9273SAli.Bahrami@Sun.COM while (*lead_str) {
166*9273SAli.Bahrami@Sun.COM if (!cef_cp(arg, state, TRUE, *lead_str++))
167*9273SAli.Bahrami@Sun.COM return (FALSE);
168*9273SAli.Bahrami@Sun.COM }
169*9273SAli.Bahrami@Sun.COM }
170*9273SAli.Bahrami@Sun.COM
171*9273SAli.Bahrami@Sun.COM return (TRUE);
172*9273SAli.Bahrami@Sun.COM }
173*9273SAli.Bahrami@Sun.COM
174*9273SAli.Bahrami@Sun.COM /*
175*9273SAli.Bahrami@Sun.COM * Common finishing code for conv_expn_field() and conv_expn_field2()
176*9273SAli.Bahrami@Sun.COM */
177*9273SAli.Bahrami@Sun.COM static int
cef_wrap(CONV_EXPN_FIELD_ARG * arg,Conv_fmt_flags_t fmt_flags,CONV_EXPN_FIELD_STATE * state,Xword rflags)178*9273SAli.Bahrami@Sun.COM cef_wrap(CONV_EXPN_FIELD_ARG *arg, Conv_fmt_flags_t fmt_flags,
179*9273SAli.Bahrami@Sun.COM CONV_EXPN_FIELD_STATE *state, Xword rflags)
180*9273SAli.Bahrami@Sun.COM {
181*9273SAli.Bahrami@Sun.COM /*
182*9273SAli.Bahrami@Sun.COM * If any flags remain, then they are unidentified. Add the numeric
183*9273SAli.Bahrami@Sun.COM * representation of these flags to the users output buffer.
184*9273SAli.Bahrami@Sun.COM */
185*9273SAli.Bahrami@Sun.COM if (rflags) {
186*9273SAli.Bahrami@Sun.COM Conv_inv_buf_t inv_buf;
187*9273SAli.Bahrami@Sun.COM
188*9273SAli.Bahrami@Sun.COM (void) conv_invalid_val(&inv_buf, rflags, fmt_flags);
189*9273SAli.Bahrami@Sun.COM if (!cef_cp(arg, state, TRUE, inv_buf.buf))
190*9273SAli.Bahrami@Sun.COM return (FALSE);
191*9273SAli.Bahrami@Sun.COM }
192*9273SAli.Bahrami@Sun.COM
193*9273SAli.Bahrami@Sun.COM /* Suffix string */
194*9273SAli.Bahrami@Sun.COM if ((fmt_flags & CONV_FMT_NOBKT) == 0)
195*9273SAli.Bahrami@Sun.COM if (!cef_cp(arg, state, FALSE,
196*9273SAli.Bahrami@Sun.COM (arg->suffix ? arg->suffix : MSG_ORIG(MSG_GBL_CSQBRKT))))
197*9273SAli.Bahrami@Sun.COM return (FALSE);
198*9273SAli.Bahrami@Sun.COM
199*9273SAli.Bahrami@Sun.COM /* Terminate the buffer */
200*9273SAli.Bahrami@Sun.COM *state->cur = '\0';
201*9273SAli.Bahrami@Sun.COM
202*9273SAli.Bahrami@Sun.COM return (TRUE);
203*9273SAli.Bahrami@Sun.COM }
204*9273SAli.Bahrami@Sun.COM
205*9273SAli.Bahrami@Sun.COM /*
206*9273SAli.Bahrami@Sun.COM * Provide a focal point for expanding bit-fields values into
207*9273SAli.Bahrami@Sun.COM * their corresponding strings.
208*9273SAli.Bahrami@Sun.COM *
209*9273SAli.Bahrami@Sun.COM * entry:
210*9273SAli.Bahrami@Sun.COM * arg - Specifies the operation to be carried out. See the
211*9273SAli.Bahrami@Sun.COM * definition of CONV_EXPN_FIELD_ARG in conv.h for details.
212*9273SAli.Bahrami@Sun.COM * vdp - Array of value descriptors, giving the possible bit values,
213*9273SAli.Bahrami@Sun.COM * and their corresponding strings. Note that the final element
214*9273SAli.Bahrami@Sun.COM * must contain only NULL values. This terminates the list.
215*9273SAli.Bahrami@Sun.COM *
216*9273SAli.Bahrami@Sun.COM * exit:
217*9273SAli.Bahrami@Sun.COM * arg->buf contains the formatted result. True (1) is returned if there
218*9273SAli.Bahrami@Sun.COM * was no error, and False (0) if the buffer was too small. In the failure
219*9273SAli.Bahrami@Sun.COM * case, arg->buf contains a numeric representation of the value.
220*9273SAli.Bahrami@Sun.COM *
221*9273SAli.Bahrami@Sun.COM * note:
222*9273SAli.Bahrami@Sun.COM * The Val_desc2 variant of this routine ignores entries from vdp that
223*9273SAli.Bahrami@Sun.COM * have a non-zero osabi or machine value that does not match that
224*9273SAli.Bahrami@Sun.COM * supplied by the caller.
225*9273SAli.Bahrami@Sun.COM */
226*9273SAli.Bahrami@Sun.COM /*ARGSUSED3*/
227*9273SAli.Bahrami@Sun.COM int
_conv_expn_field(CONV_EXPN_FIELD_ARG * arg,const Val_desc * vdp,Conv_fmt_flags_t fmt_flags,const char * local_sgs_msg)228*9273SAli.Bahrami@Sun.COM _conv_expn_field(CONV_EXPN_FIELD_ARG *arg, const Val_desc *vdp,
229*9273SAli.Bahrami@Sun.COM Conv_fmt_flags_t fmt_flags, const char *local_sgs_msg)
230*9273SAli.Bahrami@Sun.COM {
231*9273SAli.Bahrami@Sun.COM CONV_EXPN_FIELD_STATE state;
232*9273SAli.Bahrami@Sun.COM Xword rflags = arg->rflags;
233*9273SAli.Bahrami@Sun.COM
234*9273SAli.Bahrami@Sun.COM if (cef_setup(arg, fmt_flags, &state) == FALSE)
235*9273SAli.Bahrami@Sun.COM return (FALSE);
236*9273SAli.Bahrami@Sun.COM
237*9273SAli.Bahrami@Sun.COM /*
238*9273SAli.Bahrami@Sun.COM * Traverse the callers Val_desc array and determine if the value
239*9273SAli.Bahrami@Sun.COM * corresponds to any array item and add those that are to the list.
240*9273SAli.Bahrami@Sun.COM */
241*9273SAli.Bahrami@Sun.COM for (; vdp->v_msg; vdp++) {
242*9273SAli.Bahrami@Sun.COM if (arg->oflags & vdp->v_val) {
243*9273SAli.Bahrami@Sun.COM if (!cef_cp(arg, &state, TRUE,
244*9273SAli.Bahrami@Sun.COM MSG_ORIG_STRTAB(vdp->v_msg, local_sgs_msg)))
245*9273SAli.Bahrami@Sun.COM return (FALSE);
246*9273SAli.Bahrami@Sun.COM
247*9273SAli.Bahrami@Sun.COM /* Indicate this item has been collected */
248*9273SAli.Bahrami@Sun.COM rflags &= ~(vdp->v_val);
249*9273SAli.Bahrami@Sun.COM }
250*9273SAli.Bahrami@Sun.COM }
251*9273SAli.Bahrami@Sun.COM
252*9273SAli.Bahrami@Sun.COM return (cef_wrap(arg, fmt_flags, &state, rflags));
253*9273SAli.Bahrami@Sun.COM }
254*9273SAli.Bahrami@Sun.COM
255*9273SAli.Bahrami@Sun.COM /*ARGSUSED5*/
256*9273SAli.Bahrami@Sun.COM int
_conv_expn_field2(CONV_EXPN_FIELD_ARG * arg,uchar_t osabi,Half mach,const Val_desc2 * vdp,Conv_fmt_flags_t fmt_flags,const char * local_sgs_msg)257*9273SAli.Bahrami@Sun.COM _conv_expn_field2(CONV_EXPN_FIELD_ARG *arg, uchar_t osabi, Half mach,
258*9273SAli.Bahrami@Sun.COM const Val_desc2 *vdp, Conv_fmt_flags_t fmt_flags, const char *local_sgs_msg)
259*9273SAli.Bahrami@Sun.COM {
260*9273SAli.Bahrami@Sun.COM CONV_EXPN_FIELD_STATE state;
261*9273SAli.Bahrami@Sun.COM Xword rflags = arg->rflags;
262*9273SAli.Bahrami@Sun.COM
263*9273SAli.Bahrami@Sun.COM if (cef_setup(arg, fmt_flags, &state) == FALSE)
264*9273SAli.Bahrami@Sun.COM return (FALSE);
265*9273SAli.Bahrami@Sun.COM
266*9273SAli.Bahrami@Sun.COM /*
267*9273SAli.Bahrami@Sun.COM * Traverse the callers Val_desc array and determine if the value
268*9273SAli.Bahrami@Sun.COM * corresponds to any array item and add those that are to the list.
269*9273SAli.Bahrami@Sun.COM */
270*9273SAli.Bahrami@Sun.COM for (; vdp->v_msg; vdp++) {
271*9273SAli.Bahrami@Sun.COM if (CONV_VD2_SKIP(osabi, mach, vdp))
272*9273SAli.Bahrami@Sun.COM continue;
273*9273SAli.Bahrami@Sun.COM
274*9273SAli.Bahrami@Sun.COM if (arg->oflags & vdp->v_val) {
275*9273SAli.Bahrami@Sun.COM if (!cef_cp(arg, &state, TRUE,
276*9273SAli.Bahrami@Sun.COM MSG_ORIG_STRTAB(vdp->v_msg, local_sgs_msg)))
277*9273SAli.Bahrami@Sun.COM return (FALSE);
278*9273SAli.Bahrami@Sun.COM
279*9273SAli.Bahrami@Sun.COM /* Indicate this item has been collected */
280*9273SAli.Bahrami@Sun.COM rflags &= ~(vdp->v_val);
281*9273SAli.Bahrami@Sun.COM }
282*9273SAli.Bahrami@Sun.COM }
283*9273SAli.Bahrami@Sun.COM
284*9273SAli.Bahrami@Sun.COM return (cef_wrap(arg, fmt_flags, &state, rflags));
285*9273SAli.Bahrami@Sun.COM }
286