xref: /freebsd/lib/libsysdecode/support.c (revision 2008043f386721d58158e37e0d7e50df8095942d)
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