1 1.20 thorpej /* $NetBSD: parse.c,v 1.20 2020/06/07 06:02:58 thorpej Exp $ */ 2 1.2 dyoung 3 1.2 dyoung /*- 4 1.7 dyoung * Copyright (c) 2008 David Young. All rights reserved. 5 1.2 dyoung * 6 1.2 dyoung * Redistribution and use in source and binary forms, with or without 7 1.2 dyoung * modification, are permitted provided that the following conditions 8 1.2 dyoung * are met: 9 1.2 dyoung * 1. Redistributions of source code must retain the above copyright 10 1.2 dyoung * notice, this list of conditions and the following disclaimer. 11 1.2 dyoung * 2. Redistributions in binary form must reproduce the above copyright 12 1.2 dyoung * notice, this list of conditions and the following disclaimer in the 13 1.2 dyoung * documentation and/or other materials provided with the distribution. 14 1.2 dyoung * 15 1.2 dyoung * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 1.2 dyoung * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 1.2 dyoung * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 1.2 dyoung * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 1.2 dyoung * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 1.2 dyoung * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 1.2 dyoung * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 1.2 dyoung * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 1.2 dyoung * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 1.2 dyoung * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 1.2 dyoung * SUCH DAMAGE. 26 1.2 dyoung */ 27 1.2 dyoung 28 1.9 dyoung #include <sys/cdefs.h> 29 1.9 dyoung #ifndef lint 30 1.20 thorpej __RCSID("$NetBSD: parse.c,v 1.20 2020/06/07 06:02:58 thorpej Exp $"); 31 1.9 dyoung #endif /* not lint */ 32 1.9 dyoung 33 1.1 dyoung #include <err.h> 34 1.1 dyoung #include <errno.h> 35 1.1 dyoung #include <limits.h> 36 1.1 dyoung #include <netdb.h> 37 1.1 dyoung #include <stddef.h> 38 1.1 dyoung #include <stdio.h> 39 1.1 dyoung #include <stdlib.h> 40 1.1 dyoung #include <string.h> 41 1.1 dyoung 42 1.1 dyoung #include <arpa/inet.h> 43 1.1 dyoung #include <sys/param.h> 44 1.1 dyoung #include <net/if.h> 45 1.6 dyoung #include <net/if_dl.h> 46 1.1 dyoung #include <netatalk/at.h> 47 1.1 dyoung 48 1.1 dyoung #include "env.h" 49 1.1 dyoung #include "parse.h" 50 1.1 dyoung #include "util.h" 51 1.1 dyoung 52 1.18 christos #ifdef DEBUG 53 1.18 christos #define dbg_warnx(__fmt, ...) warnx(__fmt, __VA_ARGS__) 54 1.18 christos #else 55 1.1 dyoung #define dbg_warnx(__fmt, ...) /* empty */ 56 1.18 christos #endif 57 1.1 dyoung 58 1.1 dyoung static int parser_default_init(struct parser *); 59 1.1 dyoung static int pbranch_init(struct parser *); 60 1.1 dyoung static int pkw_init(struct parser *); 61 1.1 dyoung 62 1.1 dyoung static int pterm_match(const struct parser *, const struct match *, 63 1.1 dyoung struct match *, int, const char *); 64 1.1 dyoung 65 1.1 dyoung static int paddr_match(const struct parser *, const struct match *, 66 1.1 dyoung struct match *, int, const char *); 67 1.1 dyoung 68 1.1 dyoung static int pbranch_match(const struct parser *, const struct match *, 69 1.1 dyoung struct match *, int, const char *); 70 1.1 dyoung 71 1.1 dyoung static int piface_match(const struct parser *, const struct match *, 72 1.1 dyoung struct match *, int, const char *); 73 1.1 dyoung 74 1.1 dyoung static int pstr_match(const struct parser *, const struct match *, 75 1.1 dyoung struct match *, int, const char *); 76 1.1 dyoung 77 1.1 dyoung static int pinteger_match(const struct parser *, const struct match *, 78 1.1 dyoung struct match *, int, const char *); 79 1.1 dyoung 80 1.1 dyoung static int pkw_match(const struct parser *, const struct match *, 81 1.1 dyoung struct match *, int, const char *); 82 1.1 dyoung 83 1.1 dyoung const struct parser_methods pterm_methods = { 84 1.1 dyoung .pm_match = pterm_match 85 1.1 dyoung , .pm_init = NULL 86 1.1 dyoung }; 87 1.1 dyoung 88 1.1 dyoung const struct parser_methods pstr_methods = { 89 1.1 dyoung .pm_match = pstr_match 90 1.1 dyoung , .pm_init = parser_default_init 91 1.1 dyoung }; 92 1.1 dyoung 93 1.1 dyoung const struct parser_methods pinteger_methods = { 94 1.1 dyoung .pm_match = pinteger_match 95 1.1 dyoung , .pm_init = parser_default_init 96 1.1 dyoung }; 97 1.1 dyoung 98 1.1 dyoung const struct parser_methods paddr_methods = { 99 1.1 dyoung .pm_match = paddr_match 100 1.1 dyoung , .pm_init = parser_default_init 101 1.1 dyoung }; 102 1.1 dyoung 103 1.1 dyoung const struct parser_methods piface_methods = { 104 1.1 dyoung .pm_match = piface_match 105 1.1 dyoung , .pm_init = parser_default_init 106 1.1 dyoung }; 107 1.1 dyoung 108 1.1 dyoung const struct parser_methods pbranch_methods = { 109 1.1 dyoung .pm_match = pbranch_match 110 1.1 dyoung , .pm_init = pbranch_init 111 1.1 dyoung }; 112 1.1 dyoung 113 1.1 dyoung const struct parser_methods pkw_methods = { 114 1.1 dyoung .pm_match = pkw_match 115 1.1 dyoung , .pm_init = pkw_init 116 1.1 dyoung }; 117 1.1 dyoung 118 1.1 dyoung static int 119 1.1 dyoung match_setenv(const struct match *im, struct match *om, const char *key, 120 1.1 dyoung prop_object_t o) 121 1.1 dyoung { 122 1.1 dyoung if (im == NULL) 123 1.1 dyoung om->m_env = prop_dictionary_create(); 124 1.1 dyoung else 125 1.1 dyoung om->m_env = prop_dictionary_copy(im->m_env); 126 1.1 dyoung 127 1.1 dyoung if (om->m_env == NULL) 128 1.1 dyoung goto delobj; 129 1.1 dyoung 130 1.1 dyoung if (key != NULL && !prop_dictionary_set(om->m_env, key, o)) 131 1.1 dyoung goto deldict; 132 1.1 dyoung 133 1.1 dyoung if (o != NULL) 134 1.1 dyoung prop_object_release((prop_object_t)o); 135 1.1 dyoung 136 1.1 dyoung return 0; 137 1.1 dyoung deldict: 138 1.1 dyoung prop_object_release((prop_object_t)om->m_env); 139 1.1 dyoung om->m_env = NULL; 140 1.1 dyoung delobj: 141 1.1 dyoung prop_object_release((prop_object_t)o); 142 1.1 dyoung errno = ENOMEM; 143 1.1 dyoung return -1; 144 1.1 dyoung } 145 1.1 dyoung 146 1.1 dyoung int 147 1.1 dyoung pstr_match(const struct parser *p, const struct match *im, struct match *om, 148 1.1 dyoung int argidx, const char *arg) 149 1.1 dyoung { 150 1.1 dyoung prop_object_t o; 151 1.1 dyoung const struct pstr *ps = (const struct pstr *)p; 152 1.1 dyoung uint8_t buf[128]; 153 1.1 dyoung int len; 154 1.1 dyoung 155 1.5 dyoung if (arg == NULL) { 156 1.5 dyoung errno = EINVAL; 157 1.5 dyoung return -1; 158 1.5 dyoung } 159 1.5 dyoung 160 1.1 dyoung len = (int)sizeof(buf); 161 1.16 dyoung if (get_string(arg, NULL, buf, &len, ps->ps_hexok) == NULL) { 162 1.1 dyoung errno = EINVAL; 163 1.1 dyoung return -1; 164 1.1 dyoung } 165 1.1 dyoung 166 1.20 thorpej o = (prop_object_t)prop_data_create_copy(buf, len); 167 1.1 dyoung 168 1.1 dyoung if (o == NULL) { 169 1.1 dyoung errno = ENOMEM; 170 1.1 dyoung return -1; 171 1.1 dyoung } 172 1.1 dyoung 173 1.1 dyoung if (match_setenv(im, om, ps->ps_key, o) == -1) 174 1.1 dyoung return -1; 175 1.1 dyoung 176 1.1 dyoung om->m_argidx = argidx; 177 1.1 dyoung om->m_parser = p; 178 1.1 dyoung om->m_nextparser = p->p_nextparser; 179 1.1 dyoung 180 1.1 dyoung return 0; 181 1.1 dyoung } 182 1.1 dyoung 183 1.1 dyoung int 184 1.1 dyoung pinteger_match(const struct parser *p, const struct match *im, struct match *om, 185 1.1 dyoung int argidx, const char *arg) 186 1.1 dyoung { 187 1.1 dyoung prop_object_t o; 188 1.1 dyoung const struct pinteger *pi = (const struct pinteger *)p; 189 1.1 dyoung char *end; 190 1.1 dyoung int64_t val; 191 1.5 dyoung 192 1.5 dyoung if (arg == NULL) { 193 1.5 dyoung errno = EINVAL; 194 1.5 dyoung return -1; 195 1.5 dyoung } 196 1.5 dyoung 197 1.1 dyoung val = strtoimax(arg, &end, pi->pi_base); 198 1.1 dyoung if ((val == INTMAX_MIN || val == INTMAX_MAX) && errno == ERANGE) 199 1.1 dyoung return -1; 200 1.1 dyoung 201 1.1 dyoung if (*end != '\0') { 202 1.1 dyoung errno = EINVAL; 203 1.1 dyoung return -1; 204 1.1 dyoung } 205 1.1 dyoung 206 1.1 dyoung if (val < pi->pi_min || val > pi->pi_max) { 207 1.1 dyoung errno = ERANGE; 208 1.1 dyoung return -1; 209 1.1 dyoung } 210 1.1 dyoung 211 1.20 thorpej o = (prop_object_t)prop_number_create_signed(val); 212 1.1 dyoung 213 1.1 dyoung if (o == NULL) { 214 1.1 dyoung errno = ENOMEM; 215 1.1 dyoung return -1; 216 1.1 dyoung } 217 1.1 dyoung 218 1.1 dyoung if (match_setenv(im, om, pi->pi_key, o) == -1) 219 1.1 dyoung return -1; 220 1.1 dyoung 221 1.1 dyoung om->m_argidx = argidx; 222 1.1 dyoung om->m_parser = p; 223 1.1 dyoung om->m_nextparser = p->p_nextparser; 224 1.1 dyoung 225 1.1 dyoung return 0; 226 1.1 dyoung } 227 1.1 dyoung 228 1.1 dyoung static int 229 1.6 dyoung parse_linkaddr(const char *addr, struct sockaddr_storage *ss) 230 1.6 dyoung { 231 1.6 dyoung static const size_t maxlen = 232 1.6 dyoung sizeof(*ss) - offsetof(struct sockaddr_dl, sdl_data[0]); 233 1.6 dyoung enum { 234 1.6 dyoung LLADDR_S_INITIAL = 0, 235 1.7 dyoung LLADDR_S_ONE_OCTET = 1, 236 1.7 dyoung LLADDR_S_TWO_OCTETS = 2, 237 1.7 dyoung LLADDR_S_COLON = 3 238 1.6 dyoung } state = LLADDR_S_INITIAL; 239 1.6 dyoung uint8_t octet = 0, val; 240 1.6 dyoung struct sockaddr_dl *sdl; 241 1.6 dyoung const char *p; 242 1.13 lukem size_t i; 243 1.6 dyoung 244 1.6 dyoung memset(ss, 0, sizeof(*ss)); 245 1.6 dyoung ss->ss_family = AF_LINK; 246 1.6 dyoung sdl = (struct sockaddr_dl *)ss; 247 1.6 dyoung 248 1.6 dyoung for (i = 0, p = addr; i < maxlen; p++) { 249 1.7 dyoung dbg_warnx("%s.%d: *p == %c, state %d", __func__, __LINE__, *p, 250 1.7 dyoung state); 251 1.6 dyoung if (*p == '\0') { 252 1.7 dyoung dbg_warnx("%s.%d", __func__, __LINE__); 253 1.6 dyoung if (state != LLADDR_S_ONE_OCTET && 254 1.6 dyoung state != LLADDR_S_TWO_OCTETS) 255 1.6 dyoung return -1; 256 1.7 dyoung dbg_warnx("%s.%d", __func__, __LINE__); 257 1.6 dyoung sdl->sdl_data[i++] = octet; 258 1.15 plunky sdl->sdl_len = offsetof(struct sockaddr_dl, sdl_data) 259 1.15 plunky + i * sizeof(sdl->sdl_data[0]); 260 1.7 dyoung sdl->sdl_alen = i; 261 1.6 dyoung return 0; 262 1.6 dyoung } 263 1.6 dyoung if (*p == ':') { 264 1.7 dyoung dbg_warnx("%s.%d", __func__, __LINE__); 265 1.6 dyoung if (state != LLADDR_S_ONE_OCTET && 266 1.6 dyoung state != LLADDR_S_TWO_OCTETS) 267 1.6 dyoung return -1; 268 1.7 dyoung dbg_warnx("%s.%d", __func__, __LINE__); 269 1.6 dyoung sdl->sdl_data[i++] = octet; 270 1.6 dyoung state = LLADDR_S_COLON; 271 1.7 dyoung continue; 272 1.6 dyoung } 273 1.6 dyoung if ('a' <= *p && *p <= 'f') 274 1.6 dyoung val = 10 + *p - 'a'; 275 1.6 dyoung else if ('A' <= *p && *p <= 'F') 276 1.6 dyoung val = 10 + *p - 'A'; 277 1.6 dyoung else if ('0' <= *p && *p <= '9') 278 1.6 dyoung val = *p - '0'; 279 1.6 dyoung else 280 1.6 dyoung return -1; 281 1.6 dyoung 282 1.7 dyoung dbg_warnx("%s.%d", __func__, __LINE__); 283 1.6 dyoung if (state == LLADDR_S_ONE_OCTET) { 284 1.6 dyoung state = LLADDR_S_TWO_OCTETS; 285 1.6 dyoung octet <<= 4; 286 1.6 dyoung octet |= val; 287 1.6 dyoung } else if (state != LLADDR_S_INITIAL && state != LLADDR_S_COLON) 288 1.6 dyoung return -1; 289 1.6 dyoung else { 290 1.6 dyoung state = LLADDR_S_ONE_OCTET; 291 1.6 dyoung octet = val; 292 1.6 dyoung } 293 1.7 dyoung dbg_warnx("%s.%d", __func__, __LINE__); 294 1.6 dyoung } 295 1.6 dyoung return -1; 296 1.6 dyoung } 297 1.6 dyoung 298 1.6 dyoung static int 299 1.1 dyoung paddr_match(const struct parser *p, const struct match *im, struct match *om, 300 1.1 dyoung int argidx, const char *arg0) 301 1.1 dyoung { 302 1.1 dyoung unsigned int net, node; 303 1.1 dyoung int nread; 304 1.1 dyoung union { 305 1.1 dyoung struct sockaddr sa; 306 1.1 dyoung struct sockaddr_at sat; 307 1.1 dyoung struct sockaddr_in sin; 308 1.6 dyoung struct sockaddr_storage ss; 309 1.1 dyoung } u; 310 1.1 dyoung const struct paddr *pa = (const struct paddr *)p; 311 1.1 dyoung prop_data_t d; 312 1.1 dyoung prop_object_t o; 313 1.3 dyoung int64_t af0; 314 1.1 dyoung int af, rc; 315 1.1 dyoung struct paddr_prefix *pfx, *mask; 316 1.1 dyoung const struct sockaddr *sa = NULL; 317 1.1 dyoung struct addrinfo hints, *result = NULL; 318 1.1 dyoung char *arg, *end, *plen = NULL, *servname0; 319 1.1 dyoung const char *servname; 320 1.4 dyoung long prefixlen = -1; 321 1.1 dyoung size_t len; 322 1.1 dyoung 323 1.5 dyoung if (arg0 == NULL) { 324 1.5 dyoung errno = EINVAL; 325 1.1 dyoung return -1; 326 1.5 dyoung } 327 1.1 dyoung 328 1.1 dyoung if (pa->pa_activator != NULL && 329 1.1 dyoung prop_dictionary_get(im->m_env, pa->pa_activator) == NULL) 330 1.1 dyoung return -1; 331 1.1 dyoung 332 1.1 dyoung if (pa->pa_deactivator != NULL && 333 1.1 dyoung prop_dictionary_get(im->m_env, pa->pa_deactivator) != NULL) 334 1.1 dyoung return -1; 335 1.1 dyoung 336 1.3 dyoung if (!prop_dictionary_get_int64(im->m_env, "af", &af0)) 337 1.3 dyoung af = AF_UNSPEC; 338 1.3 dyoung else 339 1.3 dyoung af = af0; 340 1.1 dyoung 341 1.11 dyoung memset(&u, 0, sizeof(u)); 342 1.11 dyoung 343 1.1 dyoung switch (af) { 344 1.1 dyoung case AF_UNSPEC: 345 1.1 dyoung case AF_INET: 346 1.1 dyoung case AF_INET6: 347 1.1 dyoung if ((arg = strdup(arg0)) == NULL) 348 1.1 dyoung return -1; 349 1.1 dyoung 350 1.1 dyoung servname0 = arg; 351 1.1 dyoung (void)strsep(&servname0, ","); 352 1.1 dyoung servname = (servname0 == NULL) ? "0" : servname0; 353 1.1 dyoung 354 1.1 dyoung if (pa->pa_maskkey == NULL) 355 1.1 dyoung ; 356 1.1 dyoung else if ((plen = strrchr(arg, '/')) != NULL) 357 1.1 dyoung *plen++ = '\0'; 358 1.1 dyoung 359 1.1 dyoung memset(&hints, 0, sizeof(hints)); 360 1.1 dyoung 361 1.1 dyoung hints.ai_flags = AI_NUMERICHOST | AI_PASSIVE; 362 1.1 dyoung hints.ai_family = af; 363 1.1 dyoung hints.ai_socktype = SOCK_DGRAM; 364 1.1 dyoung 365 1.1 dyoung for (;;) { 366 1.1 dyoung rc = getaddrinfo(arg, servname, &hints, &result); 367 1.1 dyoung if (rc == 0) { 368 1.1 dyoung if (result->ai_next == NULL) 369 1.1 dyoung sa = result->ai_addr; 370 1.1 dyoung else 371 1.1 dyoung errno = EMLINK; 372 1.1 dyoung break; 373 1.1 dyoung } else if ((hints.ai_flags & AI_NUMERICHOST) != 0 && 374 1.1 dyoung (af == AF_INET || af == AF_UNSPEC) && 375 1.1 dyoung inet_aton(arg, &u.sin.sin_addr) == 1) { 376 1.1 dyoung u.sin.sin_family = AF_INET; 377 1.1 dyoung u.sin.sin_len = sizeof(u.sin); 378 1.1 dyoung sa = &u.sa; 379 1.1 dyoung break; 380 1.1 dyoung } else if ((hints.ai_flags & AI_NUMERICHOST) == 0 || 381 1.1 dyoung rc != EAI_NONAME) { 382 1.1 dyoung errno = ENOENT; 383 1.1 dyoung break; 384 1.1 dyoung } 385 1.1 dyoung hints.ai_flags &= ~AI_NUMERICHOST; 386 1.1 dyoung } 387 1.1 dyoung 388 1.1 dyoung 389 1.1 dyoung if (plen == NULL) 390 1.4 dyoung prefixlen = -1; 391 1.1 dyoung else { 392 1.1 dyoung prefixlen = strtol(plen, &end, 10); 393 1.1 dyoung if (end != NULL && *end != '\0') 394 1.1 dyoung sa = NULL; 395 1.4 dyoung if (prefixlen < 0 || prefixlen >= UINT8_MAX) { 396 1.4 dyoung errno = ERANGE; 397 1.4 dyoung sa = NULL; 398 1.4 dyoung } 399 1.1 dyoung } 400 1.1 dyoung 401 1.1 dyoung free(arg); 402 1.1 dyoung if (sa != NULL || af != AF_UNSPEC) 403 1.1 dyoung break; 404 1.1 dyoung /*FALLTHROUGH*/ 405 1.1 dyoung case AF_APPLETALK: 406 1.1 dyoung if (sscanf(arg0, "%u.%u%n", &net, &node, &nread) == 2 && 407 1.1 dyoung net != 0 && net <= 0xffff && node != 0 && node <= 0xfe && 408 1.1 dyoung arg0[nread] == '\0') { 409 1.1 dyoung u.sat.sat_family = AF_APPLETALK; 410 1.1 dyoung u.sat.sat_len = sizeof(u.sat); 411 1.1 dyoung u.sat.sat_addr.s_net = htons(net); 412 1.1 dyoung u.sat.sat_addr.s_node = node; 413 1.1 dyoung sa = &u.sa; 414 1.1 dyoung } 415 1.8 dyoung break; 416 1.6 dyoung case AF_LINK: 417 1.6 dyoung if (parse_linkaddr(arg0, &u.ss) == -1) 418 1.6 dyoung sa = NULL; 419 1.6 dyoung else 420 1.6 dyoung sa = &u.sa; 421 1.6 dyoung break; 422 1.1 dyoung } 423 1.1 dyoung 424 1.1 dyoung if (sa == NULL) 425 1.1 dyoung return -1; 426 1.1 dyoung 427 1.1 dyoung len = offsetof(struct paddr_prefix, pfx_addr) + sa->sa_len; 428 1.1 dyoung 429 1.1 dyoung if ((pfx = malloc(len)) == NULL) 430 1.1 dyoung return -1; 431 1.1 dyoung 432 1.1 dyoung #if 0 433 1.1 dyoung { 434 1.1 dyoung int i; 435 1.1 dyoung 436 1.1 dyoung for (i = 0; i < sa->sa_len; i++) 437 1.1 dyoung printf(" %02x", ((const uint8_t *)sa)[i]); 438 1.1 dyoung printf("\n"); 439 1.1 dyoung } 440 1.1 dyoung #endif 441 1.1 dyoung 442 1.4 dyoung pfx->pfx_len = (int16_t)prefixlen; 443 1.1 dyoung memcpy(&pfx->pfx_addr, sa, sa->sa_len); 444 1.1 dyoung af = sa->sa_family; 445 1.1 dyoung 446 1.1 dyoung if (result != NULL) 447 1.1 dyoung freeaddrinfo(result); 448 1.1 dyoung 449 1.20 thorpej o = (prop_object_t)prop_data_create_copy(pfx, len); 450 1.1 dyoung 451 1.1 dyoung free(pfx); 452 1.1 dyoung 453 1.1 dyoung if (o == NULL) 454 1.1 dyoung return -1; 455 1.1 dyoung 456 1.1 dyoung if (match_setenv(im, om, pa->pa_addrkey, o) == -1) 457 1.1 dyoung return -1; 458 1.1 dyoung 459 1.1 dyoung if (pa->pa_maskkey != NULL && plen != NULL) { 460 1.1 dyoung size_t masklen; 461 1.1 dyoung 462 1.1 dyoung if ((mask = prefixlen_to_mask(af, prefixlen)) == NULL) { 463 1.1 dyoung err(EXIT_FAILURE, "%s: prefixlen_to_mask(%d, %ld)", 464 1.1 dyoung __func__, af, prefixlen); 465 1.1 dyoung return -1; 466 1.1 dyoung } 467 1.1 dyoung 468 1.12 dyoung masklen = paddr_prefix_size(mask); 469 1.1 dyoung 470 1.20 thorpej d = prop_data_create_copy(mask, masklen); 471 1.1 dyoung free(mask); 472 1.1 dyoung 473 1.1 dyoung if (d == NULL) { 474 1.20 thorpej err(EXIT_FAILURE, "%s: prop_data_create_copy", 475 1.1 dyoung __func__); 476 1.1 dyoung return -1; 477 1.1 dyoung } 478 1.1 dyoung 479 1.1 dyoung rc = prop_dictionary_set(om->m_env, pa->pa_maskkey, 480 1.1 dyoung (prop_object_t)d) ? 0 : -1; 481 1.1 dyoung 482 1.1 dyoung prop_object_release((prop_object_t)d); 483 1.1 dyoung 484 1.1 dyoung if (rc != 0) { 485 1.1 dyoung err(EXIT_FAILURE, "%s: prop_dictionary_set", __func__); 486 1.1 dyoung return rc; 487 1.1 dyoung } 488 1.1 dyoung } 489 1.1 dyoung 490 1.1 dyoung om->m_argidx = argidx; 491 1.1 dyoung om->m_parser = p; 492 1.1 dyoung om->m_nextparser = p->p_nextparser; 493 1.1 dyoung return 0; 494 1.1 dyoung } 495 1.1 dyoung 496 1.1 dyoung static int 497 1.1 dyoung pterm_match(const struct parser *p, const struct match *im, 498 1.1 dyoung struct match *om, int argidx, const char *arg) 499 1.1 dyoung { 500 1.1 dyoung const struct pterm *pt = (const struct pterm *)p; 501 1.1 dyoung prop_bool_t b; 502 1.1 dyoung 503 1.1 dyoung if (arg != NULL) { 504 1.1 dyoung errno = EINVAL; 505 1.1 dyoung return -1; 506 1.1 dyoung } 507 1.1 dyoung b = prop_bool_create(true); 508 1.1 dyoung 509 1.1 dyoung if (match_setenv(im, om, pt->pt_key, (prop_object_t)b) == -1) 510 1.1 dyoung return -1; 511 1.1 dyoung 512 1.1 dyoung om->m_argidx = argidx; 513 1.1 dyoung om->m_parser = p; 514 1.1 dyoung om->m_nextparser = NULL; 515 1.1 dyoung return 0; 516 1.1 dyoung } 517 1.1 dyoung 518 1.1 dyoung static int 519 1.1 dyoung piface_match(const struct parser *p, const struct match *im, 520 1.1 dyoung struct match *om, int argidx, const char *arg) 521 1.1 dyoung { 522 1.1 dyoung const struct piface *pif = (const struct piface *)p; 523 1.1 dyoung prop_object_t o; 524 1.1 dyoung 525 1.1 dyoung if (arg == NULL || strlen(arg) > IFNAMSIZ) { 526 1.1 dyoung errno = EINVAL; 527 1.1 dyoung return -1; 528 1.1 dyoung } 529 1.1 dyoung 530 1.20 thorpej if ((o = (prop_object_t)prop_string_create_copy(arg)) == NULL) { 531 1.1 dyoung errno = ENOMEM; 532 1.1 dyoung return -1; 533 1.1 dyoung } 534 1.1 dyoung 535 1.1 dyoung if (match_setenv(im, om, pif->pif_key, o) == -1) 536 1.1 dyoung return -1; 537 1.1 dyoung 538 1.1 dyoung om->m_argidx = argidx; 539 1.1 dyoung om->m_parser = p; 540 1.1 dyoung om->m_nextparser = p->p_nextparser; 541 1.1 dyoung return 0; 542 1.1 dyoung } 543 1.1 dyoung 544 1.1 dyoung static void 545 1.1 dyoung match_cleanup(struct match *dst) 546 1.1 dyoung { 547 1.1 dyoung if (dst->m_env != NULL) 548 1.1 dyoung prop_object_release((prop_object_t)dst->m_env); 549 1.1 dyoung memset(dst, 0, sizeof(*dst)); 550 1.1 dyoung } 551 1.1 dyoung 552 1.1 dyoung static void 553 1.1 dyoung match_copy(struct match *dst, const struct match *src) 554 1.1 dyoung { 555 1.1 dyoung match_cleanup(dst); 556 1.1 dyoung 557 1.1 dyoung prop_object_retain((prop_object_t)src->m_env); 558 1.1 dyoung *dst = *src; 559 1.1 dyoung } 560 1.1 dyoung 561 1.1 dyoung static int 562 1.1 dyoung pbranch_match(const struct parser *p, const struct match *im, 563 1.1 dyoung struct match *om, int argidx, const char *arg) 564 1.1 dyoung { 565 1.1 dyoung const struct parser *nextp; 566 1.1 dyoung struct branch *b; 567 1.1 dyoung const struct pbranch *pb = (const struct pbranch *)p; 568 1.1 dyoung struct match tmpm; 569 1.1 dyoung int nforbid = 0, nmatch = 0, rc; 570 1.1 dyoung parser_match_t matchfunc; 571 1.1 dyoung 572 1.1 dyoung memset(&tmpm, 0, sizeof(tmpm)); 573 1.1 dyoung 574 1.1 dyoung SIMPLEQ_FOREACH(b, &pb->pb_branches, b_next) { 575 1.1 dyoung nextp = b->b_nextparser; 576 1.18 christos dbg_warnx("%s: b->b_nextparser %p [%s]", __func__, 577 1.18 christos nextp, nextp ? nextp->p_name : "(null)"); 578 1.1 dyoung if (nextp == NULL) { 579 1.1 dyoung if (arg == NULL) { 580 1.1 dyoung nmatch++; 581 1.1 dyoung match_setenv(im, om, NULL, NULL); 582 1.1 dyoung om->m_nextparser = NULL; 583 1.1 dyoung om->m_parser = p; 584 1.1 dyoung om->m_argidx = argidx; 585 1.1 dyoung } 586 1.1 dyoung continue; 587 1.1 dyoung } 588 1.1 dyoung matchfunc = nextp->p_methods->pm_match; 589 1.1 dyoung rc = (*matchfunc)(nextp, im, &tmpm, argidx, arg); 590 1.1 dyoung if (rc == 0) { 591 1.1 dyoung match_copy(om, &tmpm); 592 1.1 dyoung match_cleanup(&tmpm); 593 1.1 dyoung nmatch++; 594 1.19 msaitoh dbg_warnx("%s: branch %s ok", __func__, nextp->p_name); 595 1.1 dyoung if (pb->pb_match_first) 596 1.1 dyoung break; 597 1.1 dyoung } else if (rc == 1) { 598 1.1 dyoung nforbid++; 599 1.1 dyoung if (pb->pb_match_first) 600 1.1 dyoung break; 601 1.1 dyoung } else { 602 1.1 dyoung dbg_warnx("%s: fail branch %s", __func__, 603 1.19 msaitoh nextp->p_name); 604 1.1 dyoung } 605 1.1 dyoung } 606 1.1 dyoung switch (nmatch) { 607 1.1 dyoung case 0: 608 1.1 dyoung errno = ENOENT; 609 1.1 dyoung return (nforbid == 0) ? -1 : 1; 610 1.1 dyoung case 1: 611 1.19 msaitoh dbg_warnx("%s: branch ok", __func__); 612 1.1 dyoung return 0; 613 1.1 dyoung default: 614 1.1 dyoung match_cleanup(om); 615 1.1 dyoung errno = EMLINK; 616 1.1 dyoung return -1; 617 1.1 dyoung } 618 1.1 dyoung } 619 1.1 dyoung 620 1.1 dyoung static int 621 1.1 dyoung pkw_match(const struct parser *p, const struct match *im, 622 1.1 dyoung struct match *om, int argidx, const char *arg) 623 1.1 dyoung { 624 1.1 dyoung prop_object_t o = NULL; 625 1.1 dyoung struct kwinst *k; 626 1.1 dyoung union kwval *u = NULL; 627 1.1 dyoung const struct pkw *pk = (const struct pkw *)p; 628 1.1 dyoung 629 1.1 dyoung if (arg == NULL) { 630 1.1 dyoung errno = EINVAL; 631 1.1 dyoung return -1; 632 1.1 dyoung } 633 1.1 dyoung 634 1.1 dyoung SIMPLEQ_FOREACH(k, &pk->pk_keywords, k_next) { 635 1.1 dyoung if (k->k_act != NULL && 636 1.1 dyoung prop_dictionary_get(im->m_env, k->k_act) == NULL) 637 1.1 dyoung continue; 638 1.1 dyoung 639 1.1 dyoung if (k->k_neg && arg[0] == '-' && 640 1.1 dyoung strcmp(k->k_word, arg + 1) == 0) 641 1.1 dyoung u = &k->k_negu; 642 1.1 dyoung else if (strcmp(k->k_word, arg) == 0) 643 1.1 dyoung u = &k->k_u; 644 1.1 dyoung else 645 1.1 dyoung continue; 646 1.1 dyoung 647 1.1 dyoung if (k->k_altdeact != NULL && 648 1.1 dyoung prop_dictionary_get(im->m_env, k->k_altdeact) != NULL) 649 1.1 dyoung return 1; 650 1.1 dyoung 651 1.1 dyoung if (k->k_deact != NULL && 652 1.1 dyoung prop_dictionary_get(im->m_env, k->k_deact) != NULL) 653 1.1 dyoung return 1; 654 1.1 dyoung break; 655 1.1 dyoung } 656 1.1 dyoung if (k == NULL) { 657 1.1 dyoung errno = ENOENT; 658 1.1 dyoung return -1; 659 1.1 dyoung } 660 1.1 dyoung switch (k->k_type) { 661 1.1 dyoung case KW_T_NONE: 662 1.1 dyoung break; 663 1.1 dyoung case KW_T_BOOL: 664 1.1 dyoung o = (prop_object_t)prop_bool_create(u->u_bool); 665 1.1 dyoung if (o == NULL) 666 1.1 dyoung goto err; 667 1.1 dyoung break; 668 1.8 dyoung case KW_T_INT: 669 1.20 thorpej o = (prop_object_t)prop_number_create_signed(u->u_sint); 670 1.8 dyoung if (o == NULL) 671 1.8 dyoung goto err; 672 1.8 dyoung break; 673 1.8 dyoung case KW_T_UINT: 674 1.20 thorpej o = (prop_object_t)prop_number_create_unsigned(u->u_uint); 675 1.1 dyoung if (o == NULL) 676 1.1 dyoung goto err; 677 1.1 dyoung break; 678 1.1 dyoung case KW_T_OBJ: 679 1.1 dyoung o = u->u_obj; 680 1.1 dyoung break; 681 1.1 dyoung case KW_T_STR: 682 1.20 thorpej o = (prop_object_t)prop_string_create_nocopy(u->u_str); 683 1.1 dyoung if (o == NULL) 684 1.1 dyoung goto err; 685 1.1 dyoung break; 686 1.1 dyoung default: 687 1.1 dyoung errx(EXIT_FAILURE, "unknown keyword type %d", k->k_type); 688 1.1 dyoung } 689 1.1 dyoung 690 1.1 dyoung if (match_setenv(im, om, (o == NULL) ? NULL : k->k_key, o) == -1) 691 1.1 dyoung return -1; 692 1.1 dyoung 693 1.1 dyoung om->m_argidx = argidx; 694 1.1 dyoung om->m_parser = p; 695 1.1 dyoung om->m_nextparser = k->k_nextparser; 696 1.1 dyoung om->m_exec = k->k_exec; 697 1.1 dyoung return 0; 698 1.1 dyoung err: 699 1.1 dyoung errno = ENOMEM; 700 1.1 dyoung return -1; 701 1.1 dyoung } 702 1.1 dyoung 703 1.1 dyoung struct paddr * 704 1.1 dyoung paddr_create(const char *name, parser_exec_t pexec, const char *addrkey, 705 1.1 dyoung const char *maskkey, struct parser *next) 706 1.1 dyoung { 707 1.1 dyoung struct paddr *pa; 708 1.1 dyoung 709 1.1 dyoung if ((pa = calloc(sizeof(*pa), 1)) == NULL) 710 1.1 dyoung return NULL; 711 1.1 dyoung 712 1.1 dyoung pa->pa_parser.p_methods = &paddr_methods; 713 1.1 dyoung pa->pa_parser.p_exec = pexec; 714 1.1 dyoung pa->pa_parser.p_name = name; 715 1.1 dyoung pa->pa_parser.p_nextparser = next; 716 1.1 dyoung 717 1.1 dyoung pa->pa_addrkey = addrkey; 718 1.1 dyoung pa->pa_maskkey = maskkey; 719 1.1 dyoung 720 1.1 dyoung return pa; 721 1.1 dyoung } 722 1.1 dyoung 723 1.1 dyoung struct piface * 724 1.1 dyoung piface_create(const char *name, parser_exec_t pexec, const char *defkey, 725 1.1 dyoung struct parser *defnext) 726 1.1 dyoung { 727 1.1 dyoung struct piface *pif; 728 1.1 dyoung 729 1.1 dyoung if ((pif = calloc(sizeof(*pif), 1)) == NULL) 730 1.1 dyoung return NULL; 731 1.1 dyoung 732 1.1 dyoung pif->pif_parser.p_methods = &piface_methods; 733 1.1 dyoung pif->pif_parser.p_exec = pexec; 734 1.1 dyoung pif->pif_parser.p_name = name; 735 1.1 dyoung pif->pif_parser.p_nextparser = defnext; 736 1.1 dyoung 737 1.1 dyoung pif->pif_key = defkey; 738 1.1 dyoung 739 1.1 dyoung return pif; 740 1.1 dyoung } 741 1.1 dyoung 742 1.1 dyoung int 743 1.9 dyoung pbranch_addbranch(struct pbranch *pb, struct parser *p) 744 1.9 dyoung { 745 1.9 dyoung struct branch *b; 746 1.9 dyoung 747 1.9 dyoung if ((b = malloc(sizeof(*b))) == NULL) 748 1.9 dyoung return -1; 749 1.9 dyoung b->b_nextparser = p; 750 1.9 dyoung SIMPLEQ_INSERT_HEAD(&pb->pb_branches, b, b_next); 751 1.9 dyoung pb->pb_parser.p_initialized = false; 752 1.9 dyoung return parser_init(&pb->pb_parser); 753 1.9 dyoung } 754 1.9 dyoung 755 1.9 dyoung int 756 1.1 dyoung pbranch_setbranches(struct pbranch *pb, const struct branch *brs, size_t nbr) 757 1.1 dyoung { 758 1.1 dyoung struct branch *b; 759 1.13 lukem size_t i; 760 1.1 dyoung 761 1.1 dyoung dbg_warnx("%s: nbr %zu", __func__, nbr); 762 1.1 dyoung 763 1.1 dyoung while ((b = SIMPLEQ_FIRST(&pb->pb_branches)) != NULL) { 764 1.1 dyoung SIMPLEQ_REMOVE_HEAD(&pb->pb_branches, b_next); 765 1.1 dyoung free(b); 766 1.1 dyoung } 767 1.1 dyoung 768 1.1 dyoung for (i = 0; i < nbr; i++) { 769 1.1 dyoung if ((b = malloc(sizeof(*b))) == NULL) 770 1.1 dyoung goto err; 771 1.1 dyoung *b = brs[i]; 772 1.18 christos dbg_warnx("%s: b->b_nextparser %p [%s]", __func__, 773 1.18 christos b->b_nextparser, b->b_nextparser ? b->b_nextparser->p_name 774 1.18 christos : "(null)"); 775 1.1 dyoung SIMPLEQ_INSERT_TAIL(&pb->pb_branches, b, b_next); 776 1.1 dyoung } 777 1.1 dyoung 778 1.1 dyoung return 0; 779 1.1 dyoung err: 780 1.1 dyoung while ((b = SIMPLEQ_FIRST(&pb->pb_branches)) != NULL) { 781 1.1 dyoung SIMPLEQ_REMOVE_HEAD(&pb->pb_branches, b_next); 782 1.1 dyoung free(b); 783 1.1 dyoung } 784 1.1 dyoung return -1; 785 1.1 dyoung } 786 1.1 dyoung 787 1.1 dyoung static int 788 1.1 dyoung pbranch_init(struct parser *p) 789 1.1 dyoung { 790 1.1 dyoung struct branch *b; 791 1.1 dyoung struct pbranch *pb = (struct pbranch *)p; 792 1.1 dyoung struct parser *np; 793 1.1 dyoung 794 1.9 dyoung if (pb->pb_nbrinit == 0) 795 1.9 dyoung ; 796 1.9 dyoung else if (pbranch_setbranches(pb, pb->pb_brinit, pb->pb_nbrinit) == -1) 797 1.9 dyoung return -1; 798 1.1 dyoung 799 1.9 dyoung pb->pb_nbrinit = 0; 800 1.1 dyoung 801 1.1 dyoung SIMPLEQ_FOREACH(b, &pb->pb_branches, b_next) { 802 1.1 dyoung np = b->b_nextparser; 803 1.1 dyoung if (np != NULL && parser_init(np) == -1) 804 1.1 dyoung return -1; 805 1.1 dyoung } 806 1.1 dyoung return 0; 807 1.1 dyoung } 808 1.1 dyoung 809 1.1 dyoung struct pbranch * 810 1.1 dyoung pbranch_create(const char *name, const struct branch *brs, size_t nbr, 811 1.1 dyoung bool match_first) 812 1.1 dyoung { 813 1.1 dyoung struct pbranch *pb; 814 1.1 dyoung 815 1.1 dyoung dbg_warnx("%s: nbr %zu", __func__, nbr); 816 1.1 dyoung 817 1.1 dyoung if ((pb = calloc(1, sizeof(*pb))) == NULL) 818 1.1 dyoung return NULL; 819 1.1 dyoung 820 1.1 dyoung pb->pb_parser.p_methods = &pbranch_methods; 821 1.1 dyoung pb->pb_parser.p_name = name; 822 1.1 dyoung 823 1.1 dyoung SIMPLEQ_INIT(&pb->pb_branches); 824 1.1 dyoung 825 1.1 dyoung if (pbranch_setbranches(pb, brs, nbr) == -1) 826 1.1 dyoung goto post_pb_err; 827 1.1 dyoung 828 1.1 dyoung pb->pb_match_first = match_first; 829 1.1 dyoung return pb; 830 1.1 dyoung post_pb_err: 831 1.1 dyoung free(pb); 832 1.1 dyoung return NULL; 833 1.1 dyoung } 834 1.1 dyoung 835 1.1 dyoung static int 836 1.1 dyoung parser_default_init(struct parser *p) 837 1.1 dyoung { 838 1.1 dyoung struct parser *np; 839 1.1 dyoung 840 1.1 dyoung np = p->p_nextparser; 841 1.1 dyoung if (np != NULL && parser_init(np) == -1) 842 1.1 dyoung return -1; 843 1.1 dyoung 844 1.1 dyoung return 0; 845 1.1 dyoung } 846 1.1 dyoung 847 1.1 dyoung static int 848 1.1 dyoung pkw_setwords(struct pkw *pk, parser_exec_t defexec, const char *defkey, 849 1.1 dyoung const struct kwinst *kws, size_t nkw, struct parser *defnext) 850 1.1 dyoung { 851 1.1 dyoung struct kwinst *k; 852 1.13 lukem size_t i; 853 1.1 dyoung 854 1.1 dyoung for (i = 0; i < nkw; i++) { 855 1.9 dyoung if (kws[i].k_word == NULL) 856 1.9 dyoung continue; 857 1.1 dyoung if ((k = malloc(sizeof(*k))) == NULL) 858 1.1 dyoung goto post_pk_err; 859 1.1 dyoung *k = kws[i]; 860 1.1 dyoung if (k->k_nextparser == NULL) 861 1.1 dyoung k->k_nextparser = defnext; 862 1.1 dyoung if (k->k_key == NULL) 863 1.1 dyoung k->k_key = defkey; 864 1.1 dyoung if (k->k_exec == NULL) 865 1.1 dyoung k->k_exec = defexec; 866 1.1 dyoung SIMPLEQ_INSERT_TAIL(&pk->pk_keywords, k, k_next); 867 1.1 dyoung } 868 1.1 dyoung return 0; 869 1.1 dyoung 870 1.1 dyoung post_pk_err: 871 1.1 dyoung while ((k = SIMPLEQ_FIRST(&pk->pk_keywords)) != NULL) { 872 1.1 dyoung SIMPLEQ_REMOVE_HEAD(&pk->pk_keywords, k_next); 873 1.1 dyoung free(k); 874 1.1 dyoung } 875 1.1 dyoung return -1; 876 1.1 dyoung } 877 1.1 dyoung 878 1.1 dyoung static int 879 1.1 dyoung pkw_init(struct parser *p) 880 1.1 dyoung { 881 1.1 dyoung struct kwinst *k; 882 1.1 dyoung struct pkw *pk = (struct pkw *)p; 883 1.1 dyoung struct parser *np; 884 1.1 dyoung 885 1.9 dyoung if (pk->pk_nkwinit == 0) 886 1.9 dyoung ; 887 1.9 dyoung else if (pkw_setwords(pk, pk->pk_execinit, pk->pk_keyinit, 888 1.9 dyoung pk->pk_kwinit, pk->pk_nkwinit, pk->pk_nextinit) == -1) 889 1.1 dyoung return -1; 890 1.9 dyoung 891 1.9 dyoung pk->pk_nkwinit = 0; 892 1.9 dyoung 893 1.1 dyoung SIMPLEQ_FOREACH(k, &pk->pk_keywords, k_next) { 894 1.1 dyoung np = k->k_nextparser; 895 1.1 dyoung if (np != NULL && parser_init(np) == -1) 896 1.1 dyoung return -1; 897 1.1 dyoung } 898 1.1 dyoung return 0; 899 1.1 dyoung } 900 1.1 dyoung 901 1.1 dyoung struct pkw * 902 1.1 dyoung pkw_create(const char *name, parser_exec_t defexec, const char *defkey, 903 1.1 dyoung const struct kwinst *kws, size_t nkw, struct parser *defnext) 904 1.1 dyoung { 905 1.1 dyoung struct pkw *pk; 906 1.1 dyoung 907 1.1 dyoung if ((pk = calloc(1, sizeof(*pk))) == NULL) 908 1.1 dyoung return NULL; 909 1.1 dyoung 910 1.1 dyoung pk->pk_parser.p_methods = &pkw_methods; 911 1.1 dyoung pk->pk_parser.p_exec = defexec; 912 1.1 dyoung pk->pk_parser.p_name = name; 913 1.1 dyoung 914 1.1 dyoung SIMPLEQ_INIT(&pk->pk_keywords); 915 1.1 dyoung 916 1.1 dyoung if (pkw_setwords(pk, defexec, defkey, kws, nkw, defnext) == -1) 917 1.1 dyoung goto err; 918 1.1 dyoung 919 1.1 dyoung return pk; 920 1.1 dyoung err: 921 1.1 dyoung free(pk); 922 1.1 dyoung return NULL; 923 1.1 dyoung } 924 1.1 dyoung 925 1.1 dyoung int 926 1.1 dyoung parse(int argc, char **argv, const struct parser *p0, struct match *matches, 927 1.1 dyoung size_t *nmatch, int *narg) 928 1.1 dyoung { 929 1.1 dyoung int i, rc = 0; 930 1.1 dyoung struct match *lastm = NULL, *m = matches; 931 1.1 dyoung const struct parser *p = p0; 932 1.1 dyoung 933 1.1 dyoung for (i = 0; i < argc && p != NULL; i++) { 934 1.13 lukem if ((size_t)(m - matches) >= *nmatch) { 935 1.1 dyoung errno = EFBIG; 936 1.1 dyoung rc = -1; 937 1.1 dyoung break; 938 1.1 dyoung } 939 1.1 dyoung rc = (*p->p_methods->pm_match)(p, lastm, m, i, argv[i]); 940 1.1 dyoung if (rc != 0) 941 1.1 dyoung goto out; 942 1.1 dyoung p = m->m_nextparser; 943 1.1 dyoung lastm = m++; 944 1.1 dyoung } 945 1.13 lukem for (; (size_t)(m - matches) < *nmatch && p != NULL; ) { 946 1.1 dyoung rc = (*p->p_methods->pm_match)(p, lastm, m, i, NULL); 947 1.1 dyoung if (rc != 0) 948 1.1 dyoung break; 949 1.1 dyoung p = m->m_nextparser; 950 1.1 dyoung lastm = m++; 951 1.1 dyoung } 952 1.1 dyoung out: 953 1.1 dyoung *nmatch = m - matches; 954 1.1 dyoung *narg = i; 955 1.1 dyoung return rc; 956 1.1 dyoung } 957 1.1 dyoung 958 1.1 dyoung int 959 1.10 dyoung matches_exec(const struct match *matches, prop_dictionary_t oenv, size_t nmatch) 960 1.1 dyoung { 961 1.13 lukem size_t i; 962 1.13 lukem int rc = 0; 963 1.1 dyoung const struct match *m; 964 1.1 dyoung parser_exec_t pexec; 965 1.1 dyoung prop_dictionary_t d; 966 1.1 dyoung 967 1.1 dyoung for (i = 0; i < nmatch; i++) { 968 1.1 dyoung m = &matches[i]; 969 1.13 lukem dbg_warnx("%s.%d: i %zu", __func__, __LINE__, i); 970 1.1 dyoung pexec = (m->m_parser->p_exec != NULL) 971 1.1 dyoung ? m->m_parser->p_exec : m->m_exec; 972 1.1 dyoung if (pexec == NULL) 973 1.1 dyoung continue; 974 1.1 dyoung dbg_warnx("%s.%d: m->m_parser->p_name %s", __func__, __LINE__, 975 1.1 dyoung m->m_parser->p_name); 976 1.10 dyoung d = prop_dictionary_augment(m->m_env, oenv); 977 1.10 dyoung rc = (*pexec)(d, oenv); 978 1.1 dyoung prop_object_release((prop_object_t)d); 979 1.1 dyoung if (rc == -1) 980 1.1 dyoung break; 981 1.1 dyoung } 982 1.1 dyoung return rc; 983 1.1 dyoung } 984 1.9 dyoung 985 1.9 dyoung int 986 1.9 dyoung parser_init(struct parser *p) 987 1.9 dyoung { 988 1.9 dyoung if (p->p_initialized) 989 1.9 dyoung return 0; 990 1.9 dyoung p->p_initialized = true; 991 1.9 dyoung if (p->p_methods->pm_init == NULL) 992 1.9 dyoung return 0; 993 1.9 dyoung return (*p->p_methods->pm_init)(p); 994 1.9 dyoung } 995