summaryrefslogtreecommitdiffstats
path: root/src/util/split_nameval.c
blob: 0359f1a13aa11a60345aea4727655764cd7062ee (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/*++
/* NAME
/*	split_nameval 3
/* SUMMARY
/*	name-value splitter
/* SYNOPSIS
/*	#include <split_nameval.h>
/*
/*	const char *split_nameval(buf, name, value)
/*	char	*buf;
/*	char	**name;
/*	char	**value;
/* DESCRIPTION
/*	split_nameval() takes a logical line from readlline() and expects
/*	text of the form "name = value" or "name =". The buffer
/*	argument is broken up into name and value substrings.
/*
/*	Arguments:
/* .IP buf
/*	Result from readlline() or equivalent. The buffer is modified.
/* .IP name
/*	Upon successful completion, this is set to the name
/*	substring.
/* .IP value
/*	Upon successful completion, this is set to the value
/*	substring.
/* FEATURES
/* SEE ALSO
/*	dict(3) mid-level dictionary routines
/* BUGS
/* DIAGNOSTICS
/*	Fatal errors: out of memory.
/*
/*	The result is a null pointer in case of success, a string
/*	describing the error otherwise: missing '=' after attribute
/*	name; missing attribute name.
/* LICENSE
/* .ad
/* .fi
/*	The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/*	Wietse Venema
/*	IBM T.J. Watson Research
/*	P.O. Box 704
/*	Yorktown Heights, NY 10598, USA
/*--*/

/* System libraries. */

#include "sys_defs.h"
#include <ctype.h>
#include <string.h>

/* Utility library. */

#include <msg.h>
#include <stringops.h>

/* split_nameval - split text into name and value */

const char *split_nameval(char *buf, char **name, char **value)
{
    char   *np;				/* name substring */
    char   *vp;				/* value substring */
    char   *cp;
    char   *ep;

    /*
     * Ugly macros to make complex expressions less unreadable.
     */
#define SKIP(start, var, cond) do { \
	for (var = start; *var && (cond); var++) \
	    /* void */; \
    } while (0)

#define TRIM(s) do { \
	char *p; \
	for (p = (s) + strlen(s); p > (s) && ISSPACE(p[-1]); p--) \
	    /* void */; \
	*p = 0; \
    } while (0)

    SKIP(buf, np, ISSPACE(*np));		/* find name begin */
    if (*np == 0)
	return ("missing attribute name");
    SKIP(np, ep, !ISSPACE(*ep) && *ep != '=');	/* find name end */
    SKIP(ep, cp, ISSPACE(*cp));			/* skip blanks before '=' */
    if (*cp != '=')				/* need '=' */
	return ("missing '=' after attribute name");
    *ep = 0;					/* terminate name */
    cp++;					/* skip over '=' */
    SKIP(cp, vp, ISSPACE(*vp));			/* skip leading blanks */
    TRIM(vp);					/* trim trailing blanks */
    *name = np;
    *value = vp;
    return (0);
}