10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 51618Srie * Common Development and Distribution License (the "License"). 61618Srie * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 211618Srie 220Sstevel@tonic-gate /* 231618Srie * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate 280Sstevel@tonic-gate #include <stdio.h> 291618Srie #include <strings.h> 300Sstevel@tonic-gate #include <sys/machelf.h> 311618Srie #include "_conv.h" 320Sstevel@tonic-gate #include "globals_msg.h" 330Sstevel@tonic-gate 341976Sab196087 351976Sab196087 /* 361976Sab196087 * Given an integer value, generate an ASCII representation of it. 371976Sab196087 * 381976Sab196087 * entry: 391976Sab196087 * string - Buffer into which the resulting string is generated. 401976Sab196087 * size - Size of string buffer (i.e. sizeof(string)) 411976Sab196087 * value - Value to be formatted. 421976Sab196087 * fmt_flags - CONV_FMT_* values, used to specify formatting details. 431976Sab196087 * 441976Sab196087 * exit: 451976Sab196087 * The formatted string, or as much as will fit, is placed into 461976Sab196087 * string. String is returned. 471976Sab196087 */ 480Sstevel@tonic-gate const char * 491976Sab196087 conv_invalid_val(char *string, size_t size, Xword value, int fmt_flags) 500Sstevel@tonic-gate { 511618Srie const char *fmt; 520Sstevel@tonic-gate 531976Sab196087 if (fmt_flags & CONV_FMT_DECIMAL) { 541976Sab196087 if (fmt_flags & CONV_FMT_SPACE) 551618Srie fmt = MSG_ORIG(MSG_GBL_FMT_DECS); 561618Srie else 571618Srie fmt = MSG_ORIG(MSG_GBL_FMT_DEC); 581618Srie } else { 591976Sab196087 if (fmt_flags & CONV_FMT_SPACE) 601618Srie fmt = MSG_ORIG(MSG_GBL_FMT_HEXS); 611618Srie else 621618Srie fmt = MSG_ORIG(MSG_GBL_FMT_HEX); 631618Srie } 641618Srie (void) snprintf(string, size, fmt, value); 650Sstevel@tonic-gate return ((const char *)string); 660Sstevel@tonic-gate } 671618Srie 681976Sab196087 691976Sab196087 701618Srie /* 71*2352Sab196087 * cef_cp() is used by conv_expn_field() to fill in the output buffer. 72*2352Sab196087 * A CONV_EXPN_FIELD_STATE variable is used to maintain the buffer state 73*2352Sab196087 * as the operation progresses. 74*2352Sab196087 * 75*2352Sab196087 * entry: 76*2352Sab196087 * arg - As passed to conv_expn_field(). 77*2352Sab196087 * state - Variable used to maintain buffer state between calls. 78*2352Sab196087 * list_item - TRUE(1) if this is a list item, and FALSE(0) 79*2352Sab196087 * if it is something else. 80*2352Sab196087 * str - String to be added to the buffer. 81*2352Sab196087 * 82*2352Sab196087 * exit: 83*2352Sab196087 * On Success: 84*2352Sab196087 * buffer contains the output string, including a list 85*2352Sab196087 * separator if appropriate. state has been updated. 86*2352Sab196087 * TRUE(1) is returned. 87*2352Sab196087 * On Failure: 88*2352Sab196087 * Buffer contains the numeric representation for the flags, 89*2352Sab196087 * and FALSE(0) is returned. 90*2352Sab196087 */ 91*2352Sab196087 typedef struct { 92*2352Sab196087 char *cur; /* Current output position in buf */ 93*2352Sab196087 size_t room; /* # of bytes left in buf */ 94*2352Sab196087 int list_cnt; /* # of list items output into buf */ 95*2352Sab196087 const char *sep_str; /* String used as list separator */ 96*2352Sab196087 int sep_str_len; /* strlen(sep_str) */ 97*2352Sab196087 } CONV_EXPN_FIELD_STATE; 98*2352Sab196087 99*2352Sab196087 static int 100*2352Sab196087 cef_cp(CONV_EXPN_FIELD_ARG *arg, CONV_EXPN_FIELD_STATE *state, 101*2352Sab196087 int list_item, const char *str) 102*2352Sab196087 { 103*2352Sab196087 int n; 104*2352Sab196087 105*2352Sab196087 if (list_item) { /* This is a list item */ 106*2352Sab196087 /* 107*2352Sab196087 * If list is non-empty, and the buffer has room, 108*2352Sab196087 * then insert the separator. 109*2352Sab196087 */ 110*2352Sab196087 if (state->list_cnt != 0) { 111*2352Sab196087 if (state->sep_str_len < state->room) { 112*2352Sab196087 (void) memcpy(state->cur, state->sep_str, 113*2352Sab196087 state->sep_str_len); 114*2352Sab196087 state->cur += state->sep_str_len; 115*2352Sab196087 state->room -= state->sep_str_len; 116*2352Sab196087 } else { 117*2352Sab196087 /* Ensure code below will catch lack of room */ 118*2352Sab196087 state->room = 0; 119*2352Sab196087 } 120*2352Sab196087 } 121*2352Sab196087 state->list_cnt++; 122*2352Sab196087 } 123*2352Sab196087 124*2352Sab196087 n = strlen(str); 125*2352Sab196087 if (n < state->room) { 126*2352Sab196087 (void) memcpy(state->cur, str, n); 127*2352Sab196087 state->cur += n; 128*2352Sab196087 state->room -= n; 129*2352Sab196087 return (TRUE); 130*2352Sab196087 } 131*2352Sab196087 132*2352Sab196087 /* Buffer too small. Fill in the numeric value and report failure */ 133*2352Sab196087 (void) conv_invalid_val(arg->buf, arg->bufsize, arg->oflags, 0); 134*2352Sab196087 return (FALSE); 135*2352Sab196087 } 136*2352Sab196087 137*2352Sab196087 138*2352Sab196087 139*2352Sab196087 /* 1401976Sab196087 * Provide a focal point for expanding bit-fields values into 1411618Srie * their corresponding strings. 1421976Sab196087 * 1431976Sab196087 * entry: 144*2352Sab196087 * arg - Specifies the operation to be carried out. See the 145*2352Sab196087 * definition of CONV_EXPN_FIELD_ARG in conv.h for details. 1461976Sab196087 * 1471976Sab196087 * exit: 148*2352Sab196087 * arg->buf contains the formatted result. True (1) is returned if there 149*2352Sab196087 * was no error, and False (0) if the buffer was too small. In the failure 150*2352Sab196087 * case, arg->buf contains a numeric representation of the value. 1511618Srie */ 1521618Srie int 153*2352Sab196087 conv_expn_field(CONV_EXPN_FIELD_ARG *arg) 1541618Srie { 155*2352Sab196087 const Val_desc *vde; 156*2352Sab196087 CONV_EXPN_FIELD_STATE state; 157*2352Sab196087 Xword rflags = arg->rflags; 158*2352Sab196087 const char **lead_str; 159*2352Sab196087 160*2352Sab196087 161*2352Sab196087 /* Initialize buffer state */ 162*2352Sab196087 state.cur = arg->buf; 163*2352Sab196087 state.room = arg->bufsize; 164*2352Sab196087 state.list_cnt = 0; 165*2352Sab196087 state.sep_str = arg->sep ? arg->sep : MSG_ORIG(MSG_GBL_SEP); 166*2352Sab196087 state.sep_str_len = strlen(state.sep_str); 167*2352Sab196087 168*2352Sab196087 /* Prefix string */ 169*2352Sab196087 if (!cef_cp(arg, &state, FALSE, 170*2352Sab196087 (arg->prefix ? arg->prefix : MSG_ORIG(MSG_GBL_OSQBRKT)))) 171*2352Sab196087 return (FALSE); 172*2352Sab196087 173*2352Sab196087 /* Any strings in the lead_str array go at the head of the list */ 174*2352Sab196087 lead_str = arg->lead_str; 175*2352Sab196087 if (lead_str) { 176*2352Sab196087 while (*lead_str) { 177*2352Sab196087 if (!cef_cp(arg, &state, TRUE, *lead_str++)) 178*2352Sab196087 return (FALSE); 179*2352Sab196087 } 180*2352Sab196087 } 1811618Srie 1821618Srie /* 1831618Srie * Traverse the callers Val_desc array and determine if the value 184*2352Sab196087 * corresponds to any array item and add those that are to the list. 1851618Srie */ 186*2352Sab196087 for (vde = arg->vdp; vde->v_msg; vde++) { 187*2352Sab196087 if (arg->oflags & vde->v_val) { 188*2352Sab196087 if (!cef_cp(arg, &state, TRUE, vde->v_msg)) 189*2352Sab196087 return (FALSE); 1901618Srie 191*2352Sab196087 /* Indicate this item has been collected */ 1921618Srie rflags &= ~(vde->v_val); 1931618Srie } 1941618Srie } 1951618Srie 1961618Srie /* 197*2352Sab196087 * If any flags remain, then they are unidentified. Add the numeric 1981618Srie * representation of these flags to the users output buffer. 1991618Srie */ 2001618Srie if (rflags) { 201*2352Sab196087 char ibuf[CONV_INV_STRSIZE]; 2021618Srie 203*2352Sab196087 (void) conv_invalid_val(ibuf, sizeof (ibuf), rflags, 0); 204*2352Sab196087 if (!cef_cp(arg, &state, TRUE, ibuf)) 205*2352Sab196087 return (FALSE); 2061618Srie } 2071618Srie 208*2352Sab196087 /* Suffix string */ 209*2352Sab196087 if (!cef_cp(arg, &state, FALSE, 210*2352Sab196087 (arg->suffix ? arg->suffix : MSG_ORIG(MSG_GBL_CSQBRKT)))) 211*2352Sab196087 return (FALSE); 212*2352Sab196087 213*2352Sab196087 /* Terminate the buffer */ 214*2352Sab196087 *state.cur = '\0'; 215*2352Sab196087 216*2352Sab196087 return (TRUE); 2171618Srie } 218