1 /* $NetBSD: txtwalk.c,v 1.1 2014/07/26 19:30:44 dholland Exp $ */ 2 3 /* 4 * Copyright 1997 Piermont Information Systems Inc. 5 * All rights reserved. 6 * 7 * Written by Philip A. Nelson for Piermont Information Systems Inc. 8 * 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. The name of Piermont Information Systems Inc. may not be used to endorse 18 * or promote products derived from item software without specific prior 19 * written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS'' 22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE 25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 31 * THE POSSIBILITY OF SUCH DAMAGE. 32 * 33 */ 34 35 /* 36 * walk a text buffer, processing matched lines 37 * 38 * Written by Philip A. Nelson. 39 * 7/29/97 40 * 41 */ 42 43 #undef DEBUG 44 45 #include <stdio.h> 46 #include <string.h> 47 #include <ctype.h> 48 #include <unistd.h> 49 #include <stdlib.h> 50 51 #include "txtwalk.h" 52 53 /* prototypes */ 54 55 static int process(const struct lookfor *, char *); 56 static int match(char *, const struct lookfor *, size_t); 57 static int finddata(const struct lookfor *, char *, struct data *, size_t *); 58 59 /* 60 * Walk the buffer, call match for each line. 61 */ 62 int 63 walk(char *buffer, size_t size, const struct lookfor *these, size_t numthese) 64 { 65 size_t i = 0; 66 size_t len; 67 int line = 1; 68 int error; 69 70 while (i < size) { 71 /* Ignore zero characters. */ 72 if (*buffer == '\0') { 73 buffer++; 74 i++; 75 } else { 76 /* Assume item starts a line. */ 77 len = 0; 78 while (buffer[len] != '\n' && buffer[len] != '\0') 79 len++; 80 buffer[len] = '\0'; 81 #ifdef DEBUG 82 printf ("%5d: %s\n", line, buffer); 83 #endif 84 error = match(buffer, these, numthese); 85 if (error != 0) 86 return error; 87 buffer += len+1; 88 i += len+1; 89 line++; 90 } 91 } 92 return 0; 93 } 94 95 /* 96 * Match the current line with a string of interest. 97 * For each match in these, process the match. 98 */ 99 static int 100 match(char *line, const struct lookfor *these, size_t numthese) 101 { 102 size_t linelen; /* Line length */ 103 size_t patlen; /* Pattern length */ 104 size_t which; /* Which pattern we are using */ 105 int error; 106 107 linelen = strlen(line); 108 109 for (which = 0; which < numthese; which++) { 110 patlen = strlen(these[which].head); 111 if (linelen < patlen) 112 continue; 113 if (strncmp(these[which].head, line, patlen) == 0) { 114 error = process(&these[which], line); 115 if (error != 0) 116 return error; 117 } 118 } 119 return 0; 120 } 121 122 123 /* process the matched line. */ 124 static int 125 process(const struct lookfor *item, char *line) 126 { 127 struct data found[MAXDATA]; 128 size_t numfound = 0; 129 const char *p; 130 char *np; 131 size_t i, j; 132 int error; 133 134 if (finddata(item, line, found, &numfound)) { 135 #ifdef DEBUG 136 printf("process: \"%s\"\n", line); 137 for (i = 0; i < numfound; i++) { 138 printf ("\t%d: ", i); 139 switch (found[i].what) { 140 case INT: 141 printf ("%d\n", found[i].u.i_val); 142 break; 143 case STR: 144 printf ("'%s'\n", found[i].u.s_val); 145 break; 146 } 147 } 148 #endif 149 /* Process the stuff. */ 150 switch (item->todo[0]) { 151 case 'a': /* Assign data */ 152 p = item->todo; 153 j = 0; 154 while (*p && *p != '$') 155 p++; 156 if (*p) 157 p++; 158 for (;;) { 159 i = strtoul(p, &np, 10); 160 if (p == np) 161 break; 162 p = np; 163 switch (found[i].what) { 164 case INT: 165 *((int *)item->var+j) 166 = found[i].u.i_val; 167 break; 168 case STR: 169 strlcpy(*((char **)item->var+j), 170 found[i].u.s_val, 171 item->size); 172 break; 173 } 174 while (*p && *p != '$') 175 p++; 176 if (*p) 177 p++; 178 j++; 179 if (j >= item->nument) 180 break; 181 } 182 break; 183 case 'c': /* Call a function with data. */ 184 error = (*item->func)(found, numfound); 185 if (error != 0) 186 return error; 187 break; 188 } 189 } 190 return 0; 191 } 192 193 /* 194 * find the expected data. Return 1 if successful, return 0 if not. 195 * Successful means running into the end of the expect string before 196 * running out of line data or encountering other bad data. 197 * 198 * Side Effect -- sets numfound and found. 199 */ 200 static int 201 finddata(const struct lookfor *item, char *line, struct data *found, size_t *numfound) 202 { 203 const char *fmt; 204 size_t len; 205 char *np; 206 int i; 207 208 *numfound = 0; 209 for (fmt = item->fmt; *fmt; fmt++) { 210 if (!*line && *fmt) 211 return 0; 212 if (*fmt == '%') { 213 fmt++; 214 if (!*fmt) 215 return 0; 216 switch (*fmt) { 217 case '%': /* The char %. */ 218 if (*line != '%') 219 return 0; 220 line++; 221 break; 222 case 'i': /* Ignore characters */ 223 if (!fmt[1]) 224 return 1; 225 if (fmt[1] == ' ') 226 while (*line && !isspace((unsigned char)*line)) 227 line++; 228 else 229 while (*line && *line != fmt[1]) 230 line++; 231 break; 232 case 'd': /* Nextoken should be an integer. */ 233 i = strtoul(line, &np, 10); 234 if (line == np) 235 return 0; 236 found[*numfound].what = INT; 237 found[(*numfound)++].u.i_val = i; 238 line = np; 239 break; 240 case 's': /* Matches a 'space' separated string. */ 241 len = 0; 242 while (line[len] && !isspace((unsigned char)line[len]) 243 && line[len] != fmt[1]) 244 len++; 245 found[*numfound].what = STR; 246 found[(*numfound)++].u.s_val = line; 247 line[len] = 0; 248 line += len + 1; 249 break; 250 default: 251 return 0; 252 } 253 continue; 254 255 } 256 if (*fmt == ' ') { 257 while (isspace((unsigned char)*line)) 258 line++; 259 continue; 260 } 261 if (*line == *fmt) { 262 line++; 263 continue; 264 } 265 /* Mis match! */ 266 return 0; 267 } 268 269 /* Ran out of fmt. */ 270 return 1; 271 } 272