]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libsysdecode/support.c
strfmon: Silence scan-build warning
[FreeBSD/FreeBSD.git] / lib / libsysdecode / support.c
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 }