1/* 2 * Copyright (c) 2006 "David Kirchner" <dpk@dpk.net>. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26#include <sys/types.h> 27#include <stdbool.h> 28#include <stdio.h> 29#include <stdlib.h> 30 31#include "support.h" 32 33const char * 34lookup_value(struct name_table *table, uintmax_t val) 35{ 36 37 for (; table->str != NULL; table++) 38 if (table->val == val) 39 return (table->str); 40 return (NULL); 41} 42 43/* 44 * Used when the value maps to a bitmask of #definition values in the 45 * table. This is a helper routine which outputs a symbolic mask of 46 * matched masks. Multiple masks are separated by a pipe ('|'). 47 * The value is modified on return to only hold unmatched bits. 48 */ 49void 50print_mask_part(FILE *fp, struct name_table *table, uintmax_t *valp, 51 bool *printed) 52{ 53 uintmax_t rem; 54 55 rem = *valp; 56 for (; table->str != NULL; table++) { 57 if ((table->val & rem) == table->val) { 58 /* 59 * Only print a zero mask if the raw value is 60 * zero. 61 */ 62 if (table->val == 0 && *valp != 0) 63 continue; 64 fprintf(fp, "%s%s", *printed ? "|" : "", table->str); 65 *printed = true; 66 rem &= ~table->val; 67 } 68 } 69 70 *valp = rem; 71} 72 73/* 74 * Used when the value maps to a bitmask of #definition values in the 75 * table. The return value is true if something was printed. If 76 * rem is not NULL, *rem holds any bits not decoded if something was 77 * printed. If nothing was printed and rem is not NULL, *rem holds 78 * the original value. 79 */ 80bool 81print_mask_int(FILE *fp, struct name_table *table, int ival, int *rem) 82{ 83 uintmax_t val; 84 bool printed; 85 86 printed = false; 87 val = (unsigned)ival; 88 print_mask_part(fp, table, &val, &printed); 89 if (rem != NULL) 90 *rem = val; 91 return (printed); 92} 93 94/* 95 * Used for a mask of optional flags where a value of 0 is valid. 96 */ 97bool 98print_mask_0(FILE *fp, struct name_table *table, int val, int *rem) 99{ 100 101 if (val == 0) { 102 fputs("0", fp); 103 if (rem != NULL) 104 *rem = 0; 105 return (true); 106 } 107 return (print_mask_int(fp, table, val, rem)); 108} 109 110/* 111 * Like print_mask_0 but for a unsigned long instead of an int. 112 */ 113bool 114print_mask_0ul(FILE *fp, struct name_table *table, u_long lval, u_long *rem) 115{ 116 uintmax_t val; 117 bool printed; 118 119 if (lval == 0) { 120 fputs("0", fp); 121 if (rem != NULL) 122 *rem = 0; 123 return (true); 124 } 125 126 printed = false; 127 val = lval; 128 print_mask_part(fp, table, &val, &printed); 129 if (rem != NULL) 130 *rem = val; 131 return (printed); 132} 133 134void 135print_integer(FILE *fp, int val, int base) 136{ 137 138 switch (base) { 139 case 8: 140 fprintf(fp, "0%o", val); 141 break; 142 case 10: 143 fprintf(fp, "%d", val); 144 break; 145 case 16: 146 fprintf(fp, "0x%x", val); 147 break; 148 default: 149 abort2("bad base", 0, NULL); 150 break; 151 } 152} 153 154bool 155print_value(FILE *fp, struct name_table *table, uintmax_t val) 156{ 157 const char *str; 158 159 str = lookup_value(table, val); 160 if (str != NULL) { 161 fputs(str, fp); 162 return (true); 163 } 164 return (false); 165} 166