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