1 /* $NetBSD: parse_cross.c,v 1.1.1.1 2024/06/11 09:15:38 wiz Exp $ */
2
3 #if HAVE_CONFIG_H
4 #include "config.h"
5 #endif
6 #include <nbcompat.h>
7 #if HAVE_SYS_CDEFS_H
8 #include <sys/cdefs.h>
9 #endif
10 __RCSID("$NetBSD: parse_cross.c,v 1.1.1.1 2024/06/11 09:15:38 wiz Exp $");
11
12 #if HAVE_ERR_H
13 #include <err.h>
14 #endif
15 #include "lib.h"
16 #include "add.h"
17
18 /*
19 * ${OPSYS}/${MACHINE_ARCH} ${OS_VERSION}
20 *
21 * or just
22 *
23 * ${MACHINE_ARCH}
24 */
25 void
parse_cross(const char * text,char ** machine_arch,char ** opsys,char ** os_version)26 parse_cross(const char *text, char **machine_arch, char **opsys,
27 char **os_version)
28 {
29 static const char safeset[] = /* XXX */
30 "abcdefghijklmnopqrstuvwxyz"
31 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
32 "0123456789"
33 "-._";
34 char *copy = xstrdup(text);
35 char *p = copy, *q, *r;
36
37 /*
38 * If there's no /, treat it as a single MACHINE_ARCH.
39 */
40 if ((q = strchr(p, '/')) == NULL) {
41 *machine_arch = copy;
42 *opsys = NULL;
43 *os_version = NULL;
44 } else {
45 /*
46 * NUL-terminate at the slash so p := text[0..slash)
47 * is the OPSYS.
48 */
49 *q++ = '\0';
50
51 /*
52 * If there's no SPC, fail.
53 */
54 if (*(r = strchr(q, ' ')) == '\0') {
55 goto fail;
56 }
57
58 /*
59 * NUL-terminate at the space so
60 *
61 * q := text(slash..space)
62 *
63 * is the MACHINE_ARCH.
64 */
65 *r++ = '\0';
66
67 /*
68 * The rest is already NUL-terminated, so
69 *
70 * r := text(space..NUL)
71 *
72 * is the OS_VERSION.
73 */
74 *opsys = p;
75 *machine_arch = q;
76 *os_version = r;
77 }
78
79 /*
80 * Verify that MACHINE_ARCH, and, if specified, OPSYS and
81 * OS_VERSION lie within the safe set, so we can reserve large
82 * amounts of the space of inputs for additional syntax.
83 * Ideally we would impose more constraints here with a
84 * regular expression to restrict the space even more, but
85 * this'll do for now.
86 */
87 if ((*machine_arch)[strspn(*machine_arch, safeset)] != '\0') {
88 goto fail;
89 }
90 if (*opsys != NULL && (*opsys)[strspn(*opsys, safeset)] != '\0') {
91 goto fail;
92 }
93 if (*os_version != NULL &&
94 (*os_version)[strspn(*os_version, safeset)] != '\0') {
95 goto fail;
96 }
97 return;
98
99 fail: errx(1, "Invalid -m argument: ${OPSYS}/${MACHINE_ARCH} ${OS_VERSION}");
100 }
101