1 /* $NetBSD: split_nameval.c,v 1.1.1.1 2009/06/23 10:09:01 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) \ 74 for (var = start; *var && (cond); var++); 75 76 #define TRIM(s) { \ 77 char *p; \ 78 for (p = (s) + strlen(s); p > (s) && ISSPACE(p[-1]); p--); \ 79 *p = 0; \ 80 } 81 82 SKIP(buf, np, ISSPACE(*np)); /* find name begin */ 83 if (*np == 0) 84 return ("missing attribute name"); 85 SKIP(np, ep, !ISSPACE(*ep) && *ep != '='); /* find name end */ 86 SKIP(ep, cp, ISSPACE(*cp)); /* skip blanks before '=' */ 87 if (*cp != '=') /* need '=' */ 88 return ("missing '=' after attribute name"); 89 *ep = 0; /* terminate name */ 90 cp++; /* skip over '=' */ 91 SKIP(cp, vp, ISSPACE(*vp)); /* skip leading blanks */ 92 TRIM(vp); /* trim trailing blanks */ 93 *name = np; 94 *value = vp; 95 return (0); 96 } 97