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/cdefs.h> 27 __FBSDID("$FreeBSD$"); 28 29 #include <sys/types.h> 30 #include <stdbool.h> 31 #include <stdio.h> 32 #include <stdlib.h> 33 34 #include "support.h" 35 36 const char * 37 lookup_value(struct name_table *table, uintmax_t val) 38 { 39 40 for (; table->str != NULL; table++) 41 if (table->val == val) 42 return (table->str); 43 return (NULL); 44 } 45 46 /* 47 * Used when the value maps to a bitmask of #definition values in the 48 * table. This is a helper routine which outputs a symbolic mask of 49 * matched masks. Multiple masks are separated by a pipe ('|'). 50 * The value is modified on return to only hold unmatched bits. 51 */ 52 void 53 print_mask_part(FILE *fp, struct name_table *table, uintmax_t *valp, 54 bool *printed) 55 { 56 uintmax_t rem; 57 58 rem = *valp; 59 for (; table->str != NULL; table++) { 60 if ((table->val & rem) == table->val) { 61 /* 62 * Only print a zero mask if the raw value is 63 * zero. 64 */ 65 if (table->val == 0 && *valp != 0) 66 continue; 67 fprintf(fp, "%s%s", *printed ? "|" : "", table->str); 68 *printed = true; 69 rem &= ~table->val; 70 } 71 } 72 73 *valp = rem; 74 } 75 76 /* 77 * Used when the value maps to a bitmask of #definition values in the 78 * table. The return value is true if something was printed. If 79 * rem is not NULL, *rem holds any bits not decoded if something was 80 * printed. If nothing was printed and rem is not NULL, *rem holds 81 * the original value. 82 */ 83 bool 84 print_mask_int(FILE *fp, struct name_table *table, int ival, int *rem) 85 { 86 uintmax_t val; 87 bool printed; 88 89 printed = false; 90 val = (unsigned)ival; 91 print_mask_part(fp, table, &val, &printed); 92 if (rem != NULL) 93 *rem = val; 94 return (printed); 95 } 96 97 /* 98 * Used for a mask of optional flags where a value of 0 is valid. 99 */ 100 bool 101 print_mask_0(FILE *fp, struct name_table *table, int val, int *rem) 102 { 103 104 if (val == 0) { 105 fputs("0", fp); 106 if (rem != NULL) 107 *rem = 0; 108 return (true); 109 } 110 return (print_mask_int(fp, table, val, rem)); 111 } 112 113 /* 114 * Like print_mask_0 but for a unsigned long instead of an int. 115 */ 116 bool 117 print_mask_0ul(FILE *fp, struct name_table *table, u_long lval, u_long *rem) 118 { 119 uintmax_t val; 120 bool printed; 121 122 if (lval == 0) { 123 fputs("0", fp); 124 if (rem != NULL) 125 *rem = 0; 126 return (true); 127 } 128 129 printed = false; 130 val = lval; 131 print_mask_part(fp, table, &val, &printed); 132 if (rem != NULL) 133 *rem = val; 134 return (printed); 135 } 136 137 void 138 print_integer(FILE *fp, int val, int base) 139 { 140 141 switch (base) { 142 case 8: 143 fprintf(fp, "0%o", val); 144 break; 145 case 10: 146 fprintf(fp, "%d", val); 147 break; 148 case 16: 149 fprintf(fp, "0x%x", val); 150 break; 151 default: 152 abort2("bad base", 0, NULL); 153 break; 154 } 155 } 156 157 bool 158 print_value(FILE *fp, struct name_table *table, uintmax_t val) 159 { 160 const char *str; 161 162 str = lookup_value(table, val); 163 if (str != NULL) { 164 fputs(str, fp); 165 return (true); 166 } 167 return (false); 168 } 169