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 33 const char * 34 lookup_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 */ 49 void 50 print_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 */ 80 bool 81 print_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 */ 97 bool 98 print_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 */ 113 bool 114 print_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 134 void 135 print_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 154 bool 155 print_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