Expand PMF_FN_* macros.
[netbsd-mini2440.git] / distrib / utils / sysinst / txtwalk.c
blob60faedf62360512638cb60ed7c6e968179c35d2d
1 /* $NetBSD: txtwalk.c,v 1.11 2004/11/11 20:14:02 dsl Exp $ */
3 /*
4 * Copyright 1997 Piermont Information Systems Inc.
5 * All rights reserved.
7 * Written by Philip A. Nelson for Piermont Information Systems Inc.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, item list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, item list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of item software
18 * must display the following acknowledgement:
19 * This product includes software developed for the NetBSD Project by
20 * Piermont Information Systems Inc.
21 * 4. The name of Piermont Information Systems Inc. may not be used to endorse
22 * or promote products derived from item software without specific prior
23 * written permission.
25 * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS''
26 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
29 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
35 * THE POSSIBILITY OF SUCH DAMAGE.
40 * walk a text buffer, processing matched lines
42 * Written by Philip A. Nelson.
43 * 7/29/97
47 #undef DEBUG
49 #include <stdio.h>
50 #include <string.h>
51 #include <ctype.h>
52 #include <unistd.h>
53 #include <stdlib.h>
55 #include "txtwalk.h"
57 /* prototypes */
59 static int process(const struct lookfor *, char *);
60 static int match(char *, const struct lookfor *, size_t);
61 static int finddata(const struct lookfor *, char *, struct data *, size_t *);
64 * Walk the buffer, call match for each line.
66 int
67 walk(char *buffer, size_t size, const struct lookfor *these, size_t numthese)
69 size_t i = 0;
70 size_t len;
71 int line = 1;
72 int error;
74 while (i < size) {
75 /* Ignore zero characters. */
76 if (*buffer == '\0') {
77 buffer++;
78 i++;
79 } else {
80 /* Assume item starts a line. */
81 len = 0;
82 while (buffer[len] != '\n' && buffer[len] != '\0')
83 len++;
84 buffer[len] = '\0';
85 #ifdef DEBUG
86 printf ("%5d: %s\n", line, buffer);
87 #endif
88 error = match(buffer, these, numthese);
89 if (error != 0)
90 return error;
91 buffer += len+1;
92 i += len+1;
93 line++;
96 return 0;
100 * Match the current line with a string of interest.
101 * For each match in these, process the match.
103 static int
104 match(char *line, const struct lookfor *these, size_t numthese)
106 size_t linelen; /* Line length */
107 size_t patlen; /* Pattern length */
108 size_t which; /* Which pattern we are using */
109 int error;
111 linelen = strlen(line);
113 for (which = 0; which < numthese; which++) {
114 patlen = strlen(these[which].head);
115 if (linelen < patlen)
116 continue;
117 if (strncmp(these[which].head, line, patlen) == 0) {
118 error = process(&these[which], line);
119 if (error != 0)
120 return error;
123 return 0;
127 /* process the matched line. */
128 static int
129 process(const struct lookfor *item, char *line)
131 struct data found[MAXDATA];
132 size_t numfound = 0;
133 const char *p;
134 char *np;
135 size_t i, j;
136 int error;
138 if (finddata(item, line, found, &numfound)) {
139 #ifdef DEBUG
140 printf("process: \"%s\"\n", line);
141 for (i = 0; i < numfound; i++) {
142 printf ("\t%d: ", i);
143 switch (found[i].what) {
144 case INT:
145 printf ("%d\n", found[i].u.i_val);
146 break;
147 case STR:
148 printf ("'%s'\n", found[i].u.s_val);
149 break;
152 #endif
153 /* Process the stuff. */
154 switch (item->todo[0]) {
155 case 'a': /* Assign data */
156 p = item->todo;
157 j = 0;
158 while (*p && *p != '$')
159 p++;
160 if (*p)
161 p++;
162 for (;;) {
163 i = strtoul(p, &np, 10);
164 if (p == np)
165 break;
166 p = np;
167 switch (found[i].what) {
168 case INT:
169 *((int *)item->var+j)
170 = found[i].u.i_val;
171 break;
172 case STR:
173 strlcpy(*((char **)item->var+j),
174 found[i].u.s_val,
175 item->size);
176 break;
178 while (*p && *p != '$')
179 p++;
180 if (*p)
181 p++;
182 j++;
183 if (j >= item->nument)
184 break;
186 break;
187 case 'c': /* Call a function with data. */
188 error = (*item->func)(found, numfound);
189 if (error != 0)
190 return error;
191 break;
194 return 0;
198 * find the expected data. Return 1 if successful, return 0 if not.
199 * Successful means running into the end of the expect string before
200 * running out of line data or encountering other bad data.
202 * Side Effect -- sets numfound and found.
204 static int
205 finddata(const struct lookfor *item, char *line, struct data *found, size_t *numfound)
207 const char *fmt;
208 size_t len;
209 char *np;
210 int i;
212 *numfound = 0;
213 for (fmt = item->fmt; *fmt; fmt++) {
214 if (!*line && *fmt)
215 return 0;
216 if (*fmt == '%') {
217 fmt++;
218 if (!*fmt)
219 return 0;
220 switch (*fmt) {
221 case '%': /* The char %. */
222 if (*line != '%')
223 return 0;
224 line++;
225 break;
226 case 'i': /* Ignore characters */
227 if (!fmt[1])
228 return 1;
229 if (fmt[1] == ' ')
230 while (*line && !isspace((unsigned char)*line))
231 line++;
232 else
233 while (*line && *line != fmt[1])
234 line++;
235 break;
236 case 'd': /* Nextoken should be an integer. */
237 i = strtoul(line, &np, 10);
238 if (line == np)
239 return 0;
240 found[*numfound].what = INT;
241 found[(*numfound)++].u.i_val = i;
242 line = np;
243 break;
244 case 's': /* Matches a 'space' separated string. */
245 len = 0;
246 while (line[len] && !isspace((unsigned char)line[len])
247 && line[len] != fmt[1])
248 len++;
249 found[*numfound].what = STR;
250 found[(*numfound)++].u.s_val = line;
251 line[len] = 0;
252 line += len + 1;
253 break;
254 default:
255 return 0;
257 continue;
260 if (*fmt == ' ') {
261 while (isspace((unsigned char)*line))
262 line++;
263 continue;
265 if (*line == *fmt) {
266 line++;
267 continue;
269 /* Mis match! */
270 return 0;
273 /* Ran out of fmt. */
274 return 1;