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 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