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