Home | History | Annotate | Line # | Download | only in util
      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 
     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 || *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