1*67b9b338Schristos /* $NetBSD: extpar.c,v 1.4 2022/10/08 16:12:50 christos Exp $ */
2e262b48eSchristos
3e262b48eSchristos /*++
4e262b48eSchristos /* NAME
5e262b48eSchristos /* extpar 3
6e262b48eSchristos /* SUMMARY
7e262b48eSchristos /* extract text from parentheses
8e262b48eSchristos /* SYNOPSIS
9e262b48eSchristos /* #include <stringops.h>
10e262b48eSchristos /*
11e262b48eSchristos /* char *extpar(bp, parens, flags)
12e262b48eSchristos /* char **bp;
13e262b48eSchristos /* const char *parens;
14e262b48eSchristos /* int flags;
15e262b48eSchristos /* DESCRIPTION
16e262b48eSchristos /* extpar() extracts text from an input string that is enclosed
17e262b48eSchristos /* in the specified parentheses, and updates the buffer pointer
18e262b48eSchristos /* to point to that text.
19e262b48eSchristos /*
20e262b48eSchristos /* Arguments:
21e262b48eSchristos /* .IP bp
22e262b48eSchristos /* Pointer to buffer pointer. Both the buffer and the buffer
23e262b48eSchristos /* pointer are modified.
24e262b48eSchristos /* .IP parens
25e262b48eSchristos /* One matching pair of parentheses, opening parenthesis first.
26e262b48eSchristos /* .IP flags
27e262b48eSchristos /* EXTPAR_FLAG_NONE, or the bitwise OR of one or more flags:
28e262b48eSchristos /* .RS
29e262b48eSchristos /* .IP EXTPAR_FLAG_EXTRACT
30*67b9b338Schristos /* This flag is intended to instruct extpar() callers that
31*67b9b338Schristos /* extpar() should be invoked. It has no effect on expar()
32e262b48eSchristos /* itself.
33e262b48eSchristos /* .IP EXTPAR_FLAG_STRIP
34e262b48eSchristos /* Skip whitespace after the opening parenthesis, and trim
35e262b48eSchristos /* whitespace before the closing parenthesis.
36e262b48eSchristos /* .RE
37e262b48eSchristos /* DIAGNOSTICS
38e262b48eSchristos /* In case of error the result value is a dynamically-allocated
39e262b48eSchristos /* string with a description of the problem that includes a
40e262b48eSchristos /* copy of the offending input. A non-null result value should
4133881f77Schristos /* be destroyed with myfree(). The following describes the errors
42e262b48eSchristos /* and the state of the buffer and buffer pointer.
43*67b9b338Schristos /* .IP "no opening parenthesis at start of text"
44*67b9b338Schristos /* The buffer pointer points to the input text.
45e262b48eSchristos /* .IP "missing closing parenthesis"
46e262b48eSchristos /* The buffer pointer points to text as if a closing parenthesis
47e262b48eSchristos /* were present at the end of the input.
48e262b48eSchristos /* .IP "text after closing parenthesis"
49e262b48eSchristos /* The buffer pointer points to text as if the offending text
50e262b48eSchristos /* were not present.
51e262b48eSchristos /* SEE ALSO
52e262b48eSchristos /* balpar(3) determine length of string in parentheses
53e262b48eSchristos /* LICENSE
54e262b48eSchristos /* .ad
55e262b48eSchristos /* .fi
56e262b48eSchristos /* The Secure Mailer license must be distributed with this software.
57e262b48eSchristos /* AUTHOR(S)
58e262b48eSchristos /* Wietse Venema
59e262b48eSchristos /* IBM T.J. Watson Research
60e262b48eSchristos /* P.O. Box 704
61e262b48eSchristos /* Yorktown Heights, NY 10598, USA
62*67b9b338Schristos /*
63*67b9b338Schristos /* Wietse Venema
64*67b9b338Schristos /* Google, Inc.
65*67b9b338Schristos /* 111 8th Avenue
66*67b9b338Schristos /* New York, NY 10011, USA
67e262b48eSchristos /*--*/
68e262b48eSchristos
69e262b48eSchristos /*
70e262b48eSchristos * System library.
71e262b48eSchristos */
72e262b48eSchristos #include <sys_defs.h>
73e262b48eSchristos #include <ctype.h>
74e262b48eSchristos
75e262b48eSchristos /*
76e262b48eSchristos * Utility library.
77e262b48eSchristos */
78*67b9b338Schristos #include <vstring.h>
79e262b48eSchristos #include <stringops.h>
80e262b48eSchristos
81e262b48eSchristos /* extpar - extract text from parentheses */
82e262b48eSchristos
extpar(char ** bp,const char * parens,int flags)83e262b48eSchristos char *extpar(char **bp, const char *parens, int flags)
84e262b48eSchristos {
85e262b48eSchristos char *cp = *bp;
86e262b48eSchristos char *err = 0;
87e262b48eSchristos size_t len;
88e262b48eSchristos
89*67b9b338Schristos if (cp[0] != parens[0]) {
90*67b9b338Schristos err = vstring_export(vstring_sprintf(vstring_alloc(100),
91*67b9b338Schristos "no '%c' at start of text in \"%s\"", parens[0], cp));
92*67b9b338Schristos len = 0;
93*67b9b338Schristos } else if ((len = balpar(cp, parens)) == 0) {
94e262b48eSchristos err = concatenate("missing '", parens + 1, "' in \"",
95e262b48eSchristos cp, "\"", (char *) 0);
96e262b48eSchristos cp += 1;
97e262b48eSchristos } else {
98e262b48eSchristos if (cp[len] != 0)
99e262b48eSchristos err = concatenate("syntax error after '", parens + 1, "' in \"",
100e262b48eSchristos cp, "\"", (char *) 0);
101e262b48eSchristos cp += 1;
102e262b48eSchristos cp[len -= 2] = 0;
103e262b48eSchristos }
104e262b48eSchristos if (flags & EXTPAR_FLAG_STRIP) {
105e262b48eSchristos trimblanks(cp, len)[0] = 0;
106e262b48eSchristos while (ISSPACE(*cp))
107e262b48eSchristos cp++;
108e262b48eSchristos }
109e262b48eSchristos *bp = cp;
110e262b48eSchristos return (err);
111e262b48eSchristos }
112