split_nameval.c revision 1.2
1/* $NetBSD: split_nameval.c,v 1.2 2023/12/23 20:30:46 christos 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 63const 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 || *np == '=') 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