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.
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.
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]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
31 #include "globals_msg.h"
35 * Given an integer value, generate an ASCII representation of it.
38 * inv_buf - Buffer into which the resulting string is generated.
39 * value - Value to be formatted.
40 * fmt_flags - CONV_FMT_* values, used to specify formatting details.
43 * The formatted string is placed into inv_buf. The pointer
44 * to the string is returned.
47 conv_invalid_val(Conv_inv_buf_t
*inv_buf
, Xword value
,
48 Conv_fmt_flags_t fmt_flags
)
52 if (fmt_flags
& CONV_FMT_DECIMAL
) {
53 if (fmt_flags
& CONV_FMT_SPACE
)
54 fmt
= MSG_ORIG(MSG_GBL_FMT_DECS
);
56 fmt
= MSG_ORIG(MSG_GBL_FMT_DEC
);
58 if (fmt_flags
& CONV_FMT_SPACE
)
59 fmt
= MSG_ORIG(MSG_GBL_FMT_HEXS
);
61 fmt
= MSG_ORIG(MSG_GBL_FMT_HEX
);
63 (void) snprintf(inv_buf
->buf
, sizeof (inv_buf
->buf
), fmt
, value
);
64 return ((const char *)inv_buf
->buf
);
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.
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.
83 * buffer contains the output string, including a list
84 * separator if appropriate. state has been updated.
85 * TRUE(1) is returned.
87 * Buffer contains the numeric representation for the flags,
88 * and FALSE(0) is returned.
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
;
99 cef_cp(CONV_EXPN_FIELD_ARG
*arg
, CONV_EXPN_FIELD_STATE
*state
,
100 int list_item
, const char *str
)
102 Conv_inv_buf_t inv_buf
;
105 if (list_item
) { /* This is a list item */
107 * If list is non-empty, and the buffer has room,
108 * then insert the separator.
110 if (state
->list_cnt
!= 0) {
111 if (state
->sep_str_len
< state
->room
) {
112 (void) memcpy(state
->cur
, state
->sep_str
,
114 state
->cur
+= state
->sep_str_len
;
115 state
->room
-= state
->sep_str_len
;
117 /* Ensure code below will catch lack of room */
125 if (n
< state
->room
) {
126 (void) memcpy(state
->cur
, str
, n
);
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
);
141 * Common setup code for conv_expn_field() and conv_expn_field2()
144 cef_setup(CONV_EXPN_FIELD_ARG
*arg
, Conv_fmt_flags_t fmt_flags
,
145 CONV_EXPN_FIELD_STATE
*state
)
147 const char **lead_str
;
149 /* Initialize buffer state */
150 state
->cur
= arg
->buf
;
151 state
->room
= arg
->bufsize
;
153 state
->sep_str
= arg
->sep
? arg
->sep
: MSG_ORIG(MSG_GBL_SEP
);
154 state
->sep_str_len
= strlen(state
->sep_str
);
157 if ((fmt_flags
& CONV_FMT_NOBKT
) == 0)
158 if (!cef_cp(arg
, state
, FALSE
,
159 (arg
->prefix
? arg
->prefix
: MSG_ORIG(MSG_GBL_OSQBRKT
))))
162 /* Any strings in the lead_str array go at the head of the list */
163 lead_str
= arg
->lead_str
;
166 if (!cef_cp(arg
, state
, TRUE
, *lead_str
++))
175 * Common finishing code for conv_expn_field() and conv_expn_field2()
178 cef_wrap(CONV_EXPN_FIELD_ARG
*arg
, Conv_fmt_flags_t fmt_flags
,
179 CONV_EXPN_FIELD_STATE
*state
, Xword rflags
)
182 * If any flags remain, then they are unidentified. Add the numeric
183 * representation of these flags to the users output buffer.
186 Conv_inv_buf_t inv_buf
;
188 (void) conv_invalid_val(&inv_buf
, rflags
, fmt_flags
);
189 if (!cef_cp(arg
, state
, TRUE
, inv_buf
.buf
))
194 if ((fmt_flags
& CONV_FMT_NOBKT
) == 0)
195 if (!cef_cp(arg
, state
, FALSE
,
196 (arg
->suffix
? arg
->suffix
: MSG_ORIG(MSG_GBL_CSQBRKT
))))
199 /* Terminate the buffer */
206 * Provide a focal point for expanding bit-fields values into
207 * their corresponding strings.
210 * arg - Specifies the operation to be carried out. See the
211 * definition of CONV_EXPN_FIELD_ARG in conv.h for details.
212 * vdp - Array of value descriptors, giving the possible bit values,
213 * and their corresponding strings. Note that the final element
214 * must contain only NULL values. This terminates the list.
217 * arg->buf contains the formatted result. True (1) is returned if there
218 * was no error, and False (0) if the buffer was too small. In the failure
219 * case, arg->buf contains a numeric representation of the value.
222 * The Val_desc2 variant of this routine ignores entries from vdp that
223 * have a non-zero osabi or machine value that does not match that
224 * supplied by the caller.
228 _conv_expn_field(CONV_EXPN_FIELD_ARG
*arg
, const Val_desc
*vdp
,
229 Conv_fmt_flags_t fmt_flags
, const char *local_sgs_msg
)
231 CONV_EXPN_FIELD_STATE state
;
232 Xword rflags
= arg
->rflags
;
234 if (cef_setup(arg
, fmt_flags
, &state
) == FALSE
)
238 * Traverse the callers Val_desc array and determine if the value
239 * corresponds to any array item and add those that are to the list.
241 for (; vdp
->v_msg
; vdp
++) {
242 if (arg
->oflags
& vdp
->v_val
) {
243 if (!cef_cp(arg
, &state
, TRUE
,
244 MSG_ORIG_STRTAB(vdp
->v_msg
, local_sgs_msg
)))
247 /* Indicate this item has been collected */
248 rflags
&= ~(vdp
->v_val
);
252 return (cef_wrap(arg
, fmt_flags
, &state
, rflags
));
257 _conv_expn_field2(CONV_EXPN_FIELD_ARG
*arg
, uchar_t osabi
, Half mach
,
258 const Val_desc2
*vdp
, Conv_fmt_flags_t fmt_flags
, const char *local_sgs_msg
)
260 CONV_EXPN_FIELD_STATE state
;
261 Xword rflags
= arg
->rflags
;
263 if (cef_setup(arg
, fmt_flags
, &state
) == FALSE
)
267 * Traverse the callers Val_desc array and determine if the value
268 * corresponds to any array item and add those that are to the list.
270 for (; vdp
->v_msg
; vdp
++) {
271 if (CONV_VD2_SKIP(osabi
, mach
, vdp
))
274 if (arg
->oflags
& vdp
->v_val
) {
275 if (!cef_cp(arg
, &state
, TRUE
,
276 MSG_ORIG_STRTAB(vdp
->v_msg
, local_sgs_msg
)))
279 /* Indicate this item has been collected */
280 rflags
&= ~(vdp
->v_val
);
284 return (cef_wrap(arg
, fmt_flags
, &state
, rflags
));