~canonical-scott/grepmap/trunk

« back to all changes in this revision

Viewing changes to src/util.c

  • Committer: Scott James Remnant
  • Date: 2005-09-29 03:10:21 UTC
  • Revision ID: scott@netsplit.com-20050929031021-6b3c52391841a21f
* src/util.c (parse_array): Taken from inputmap.c and turned into
a function we can use anywhere; removed the pos argument and
logic to move beyond the end of the array, changed array_sz to
array_len and made it the number of elements not the sizeof.
(match_array): Also taken from input.c with array_sz changed to
array_len.
* src/inputmap.c (_parse_array, _match_array): Remove old static
function definitions from this file.
(inputmap_modules): Adjust to use parse_array, match_array and
parse_line functions from util.c, remember array lengths using
an enum. 
* src/ieee1394map.c (ieee1394map_modules): Update to use new
parse_line() function so we gain the same flexibility benefit.
* src/pcimap.c (pcimap_modules): Update to use parse_line().
* src/usbmap.c (usbmap_modules): Update to use parse_line().
* tests/ieee1394map.at (ieee1394map works without 0x prefixes):
Add test case for more liberal file parsing.
* tests/inputmap.at (inputmap works without 0x prefixes): New test.
* tests/pcimap.at (pcimap works without 0x prefixes): New test.
* tests/usbmap.at (usbmap works without 0x prefixes): New test.

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
 *
3
3
 * util.c - utility functions
4
4
 *
5
 
 * Copyright © 2004 Canonical Ltd.
 
5
 * Copyright © 2005 Canonical Ltd.
6
6
 * Author: Scott James Remnant <scott@canonical.com>.
7
7
 *
8
8
 * This program is free software; you can redistribute it and/or modify
26
26
 
27
27
#include <stdio.h>
28
28
#include <stdlib.h>
 
29
#include <stdarg.h>
29
30
#include <string.h>
30
31
 
31
32
#include "grepmap.h"
91
92
parse_hex (const char   *str,
92
93
           unsigned int *hex)
93
94
{
 
95
        int end;
 
96
 
94
97
        if (! strncmp (str, "0x", 2)) {
95
98
                str += 2;
96
99
        } else if (! strncmp (str, "&#x", 3)) {
99
102
                str += 1;
100
103
        }
101
104
 
102
 
        if (sscanf (str, "%x", hex) != 1)
103
 
                return 1;
 
105
        if (sscanf (str, "%x%n", hex, &end) < 1)
 
106
                return 1;
 
107
 
 
108
        str += end;
 
109
        if (*str && (! strchr (" \t\r\n", *str)))
 
110
                return 1;
 
111
 
 
112
        return 0;
 
113
}
 
114
 
 
115
/**
 
116
 * parse_array:
 
117
 * @str: string to parse.
 
118
 * @array: integer array to fill.
 
119
 * @array_len: number of elements of integer array.
 
120
 *
 
121
 * Scans @str and reads a colon separated array of hexadecimal numbers.
 
122
 *
 
123
 * These arrays are a little strange, the kernel actually prints them
 
124
 * backwards starting from the first non-zero part; so they may not actually
 
125
 * be complete.
 
126
 *
 
127
 * Returns: 0 on success, 1 on failure.
 
128
 **/
 
129
int
 
130
parse_array (const char   *str,
 
131
             unsigned int *array,
 
132
             size_t        array_len)
 
133
{
 
134
        int i, j;
 
135
 
 
136
        memset (array, 0, array_len * sizeof (unsigned int));
 
137
        i = array_len;
 
138
 
 
139
        while (*str && i) {
 
140
                int end;
 
141
 
 
142
                if (sscanf (str, "%x%n", &array[--i], &end) < 1)
 
143
                        break;
 
144
 
 
145
                str += end;
 
146
                if (*str == ':') {
 
147
                        str++;
 
148
                } else if (*str && (! strchr (" \t\r\n", *str))) {
 
149
                        return 1;
 
150
                } else {
 
151
                        break;
 
152
                }
 
153
        }
 
154
 
 
155
        for (j = 0; j < array_len; j++, i++)
 
156
                array[j] = (i < array_len ? array[i] : 0);
 
157
 
 
158
        return 0;
 
159
}
 
160
 
 
161
/**
 
162
 * parse_line:
 
163
 * @line: line to parse.
 
164
 * @format: expected values.
 
165
 *
 
166
 * Parses the line according to the @format string, after skipping any
 
167
 * initial module name.  The format string should be a sequence of 'x'
 
168
 * or 'a' characters; for each 'x' character an unsigned int pointer
 
169
 * should be passed and a hexadecimal number parsed from the line will
 
170
 * be placed in it;  for each 'a' character an unsigned int pointer
 
171
 * should be passed with enough space for as many elements as specified
 
172
 * by a size_t parameter also passed.
 
173
 *
 
174
 * Example:
 
175
 *   parse_line(line, "xxa", &hex1, &hex2, array, 4)
 
176
 *
 
177
 * Returns: 0 if all values are pased, 1 if not.
 
178
 */
 
179
int
 
180
parse_line (const char *line,
 
181
            const char *format,
 
182
            ...)
 
183
{
 
184
        const char *c;
 
185
        va_list     args;
 
186
 
 
187
        va_start (args, format);
 
188
 
 
189
        for (c = format; *c; c++) {
 
190
                unsigned int *val;
 
191
                size_t        len;
 
192
 
 
193
                line += strcspn (line, " \t\r\n");
 
194
                line += strspn (line, " \t\r\n");
 
195
 
 
196
                switch (*c) {
 
197
                case 'x':
 
198
                        val = va_arg (args, unsigned int *);
 
199
                        if (parse_hex (line, val))
 
200
                                return 1;
 
201
 
 
202
                        break;
 
203
                case 'a':
 
204
                        val = va_arg (args, unsigned int *);
 
205
                        len = va_arg (args, size_t);
 
206
                        if (parse_array (line, val, len))
 
207
                                return 1;
 
208
 
 
209
                        break;
 
210
                }
 
211
        }
 
212
 
 
213
        va_end (args);
 
214
 
 
215
        return 0;
 
216
}
 
217
 
 
218
/**
 
219
 * match_array:
 
220
 * @mask: bits that must be present in the array.
 
221
 * @array: array to check.
 
222
 * @array_len: number of elements in both arrays.
 
223
 *
 
224
 * Check that @array has all of the bits present in @mask.
 
225
 *
 
226
 * Returns: 0 if the arrays match, non-zero if not.
 
227
 **/
 
228
int
 
229
match_array (const unsigned int *mask,
 
230
             const unsigned int *array,
 
231
             size_t              array_len)
 
232
{
 
233
        int i;
 
234
 
 
235
        for (i = 0; i < array_len; i++) {
 
236
                if (! FLAG_SET(array[i], mask[i]))
 
237
                        return 1;
 
238
        }
104
239
 
105
240
        return 0;
106
241
}