1 /* $NetBSD: split_nameval.c,v 1.1.1.2 2014/07/06 19:27:58 tron Exp $ */
2
3 /*++
4 /* NAME
5 /* split_nameval 3
6 /* SUMMARY
7 /* name-value splitter
8 /* SYNOPSIS
9 /* #include <split_nameval.h>
10 /*
11 /* const char *split_nameval(buf, name, value)
12 /* char *buf;
13 /* char **name;
14 /* char **value;
15 /* DESCRIPTION
16 /* split_nameval() takes a logical line from readlline() and expects
17 /* text of the form "name = value" or "name =". The buffer
18 /* argument is broken up into name and value substrings.
19 /*
20 /* Arguments:
21 /* .IP buf
22 /* Result from readlline() or equivalent. The buffer is modified.
23 /* .IP name
24 /* Upon successful completion, this is set to the name
25 /* substring.
26 /* .IP value
27 /* Upon successful completion, this is set to the value
28 /* substring.
29 /* FEATURES
30 /* SEE ALSO
31 /* dict(3) mid-level dictionary routines
32 /* BUGS
33 /* DIAGNOSTICS
34 /* Fatal errors: out of memory.
35 /*
36 /* The result is a null pointer in case of success, a string
37 /* describing the error otherwise: missing '=' after attribute
38 /* name; missing attribute name.
39 /* LICENSE
40 /* .ad
41 /* .fi
42 /* The Secure Mailer license must be distributed with this software.
43 /* AUTHOR(S)
44 /* Wietse Venema
45 /* IBM T.J. Watson Research
46 /* P.O. Box 704
47 /* Yorktown Heights, NY 10598, USA
48 /*--*/
49
50 /* System libraries. */
51
52 #include "sys_defs.h"
53 #include <ctype.h>
54 #include <string.h>
55
56 /* Utility library. */
57
58 #include <msg.h>
59 #include <stringops.h>
60
61 /* split_nameval - split text into name and value */
62
split_nameval(char * buf,char ** name,char ** value)63 const char *split_nameval(char *buf, char **name, char **value)
64 {
65 char *np; /* name substring */
66 char *vp; /* value substring */
67 char *cp;
68 char *ep;
69
70 /*
71 * Ugly macros to make complex expressions less unreadable.
72 */
73 #define SKIP(start, var, cond) do { \
74 for (var = start; *var && (cond); var++) \
75 /* void */; \
76 } while (0)
77
78 #define TRIM(s) do { \
79 char *p; \
80 for (p = (s) + strlen(s); p > (s) && ISSPACE(p[-1]); p--) \
81 /* void */; \
82 *p = 0; \
83 } while (0)
84
85 SKIP(buf, np, ISSPACE(*np)); /* find name begin */
86 if (*np == 0)
87 return ("missing attribute name");
88 SKIP(np, ep, !ISSPACE(*ep) && *ep != '='); /* find name end */
89 SKIP(ep, cp, ISSPACE(*cp)); /* skip blanks before '=' */
90 if (*cp != '=') /* need '=' */
91 return ("missing '=' after attribute name");
92 *ep = 0; /* terminate name */
93 cp++; /* skip over '=' */
94 SKIP(cp, vp, ISSPACE(*vp)); /* skip leading blanks */
95 TRIM(vp); /* trim trailing blanks */
96 *name = np;
97 *value = vp;
98 return (0);
99 }
100