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