130154ac8SAndrew Moore /* re.c: This file contains the regular expression interface routines for
230154ac8SAndrew Moore the ed line editor. */
330154ac8SAndrew Moore /*-
495e6217eSAndrew Moore * Copyright (c) 1993 Andrew Moore, Talke Studio.
530154ac8SAndrew Moore * All rights reserved.
630154ac8SAndrew Moore *
730154ac8SAndrew Moore * Redistribution and use in source and binary forms, with or without
830154ac8SAndrew Moore * modification, are permitted provided that the following conditions
930154ac8SAndrew Moore * are met:
1030154ac8SAndrew Moore * 1. Redistributions of source code must retain the above copyright
1130154ac8SAndrew Moore * notice, this list of conditions and the following disclaimer.
1230154ac8SAndrew Moore * 2. Redistributions in binary form must reproduce the above copyright
1330154ac8SAndrew Moore * notice, this list of conditions and the following disclaimer in the
1430154ac8SAndrew Moore * documentation and/or other materials provided with the distribution.
1530154ac8SAndrew Moore *
1695e6217eSAndrew Moore * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1730154ac8SAndrew Moore * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1830154ac8SAndrew Moore * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1995e6217eSAndrew Moore * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2030154ac8SAndrew Moore * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2130154ac8SAndrew Moore * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2230154ac8SAndrew Moore * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2330154ac8SAndrew Moore * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2430154ac8SAndrew Moore * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2530154ac8SAndrew Moore * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2630154ac8SAndrew Moore * SUCH DAMAGE.
2730154ac8SAndrew Moore */
2830154ac8SAndrew Moore
295eb43ac2SDavid E. O'Brien #include <sys/cdefs.h>
3030154ac8SAndrew Moore #include "ed.h"
3130154ac8SAndrew Moore
32a4616748SMike Barcroft const char *errmsg = "";
3330154ac8SAndrew Moore
3495e6217eSAndrew Moore /* get_compiled_pattern: return pointer to compiled pattern from command
3595e6217eSAndrew Moore buffer */
3630154ac8SAndrew Moore pattern_t *
get_compiled_pattern(void)377669d0fcSWarner Losh get_compiled_pattern(void)
3830154ac8SAndrew Moore {
39ff572a5eSRuslan Ermilov static pattern_t *expr = NULL;
40a4616748SMike Barcroft static char error[1024];
4130154ac8SAndrew Moore
42ff572a5eSRuslan Ermilov char *exprs;
4395e6217eSAndrew Moore char delimiter;
4430154ac8SAndrew Moore int n;
4530154ac8SAndrew Moore
4695e6217eSAndrew Moore if ((delimiter = *ibufp) == ' ') {
47a4616748SMike Barcroft errmsg = "invalid pattern delimiter";
4830154ac8SAndrew Moore return NULL;
4995e6217eSAndrew Moore } else if (delimiter == '\n' || *++ibufp == '\n' || *ibufp == delimiter) {
50ff572a5eSRuslan Ermilov if (!expr)
51a4616748SMike Barcroft errmsg = "no previous pattern";
52ff572a5eSRuslan Ermilov return expr;
53ff572a5eSRuslan Ermilov } else if ((exprs = extract_pattern(delimiter)) == NULL)
5430154ac8SAndrew Moore return NULL;
5530154ac8SAndrew Moore /* buffer alloc'd && not reserved */
56ff572a5eSRuslan Ermilov if (expr && !patlock)
57ff572a5eSRuslan Ermilov regfree(expr);
58ff572a5eSRuslan Ermilov else if ((expr = (pattern_t *) malloc(sizeof(pattern_t))) == NULL) {
5930154ac8SAndrew Moore fprintf(stderr, "%s\n", strerror(errno));
60a4616748SMike Barcroft errmsg = "out of memory";
6130154ac8SAndrew Moore return NULL;
6230154ac8SAndrew Moore }
6330154ac8SAndrew Moore patlock = 0;
64ff572a5eSRuslan Ermilov if ((n = regcomp(expr, exprs, 0))) {
65ff572a5eSRuslan Ermilov regerror(n, expr, error, sizeof error);
66a4616748SMike Barcroft errmsg = error;
67ff572a5eSRuslan Ermilov free(expr);
68ff572a5eSRuslan Ermilov return expr = NULL;
6930154ac8SAndrew Moore }
70ff572a5eSRuslan Ermilov return expr;
7130154ac8SAndrew Moore }
7230154ac8SAndrew Moore
7330154ac8SAndrew Moore
7495e6217eSAndrew Moore /* extract_pattern: copy a pattern string from the command buffer; return
7595e6217eSAndrew Moore pointer to the copy */
7630154ac8SAndrew Moore char *
extract_pattern(int delimiter)777669d0fcSWarner Losh extract_pattern(int delimiter)
7830154ac8SAndrew Moore {
7995e6217eSAndrew Moore static char *lhbuf = NULL; /* buffer */
8095e6217eSAndrew Moore static int lhbufsz = 0; /* buffer size */
8195e6217eSAndrew Moore
8230154ac8SAndrew Moore char *nd;
8330154ac8SAndrew Moore int len;
8430154ac8SAndrew Moore
8595e6217eSAndrew Moore for (nd = ibufp; *nd != delimiter && *nd != '\n'; nd++)
8630154ac8SAndrew Moore switch (*nd) {
8730154ac8SAndrew Moore default:
8830154ac8SAndrew Moore break;
8930154ac8SAndrew Moore case '[':
90*9d40e340STim Kientzle if ((nd = parse_char_class(nd + 1)) == NULL) {
91a4616748SMike Barcroft errmsg = "unbalanced brackets ([])";
9230154ac8SAndrew Moore return NULL;
9330154ac8SAndrew Moore }
9430154ac8SAndrew Moore break;
9530154ac8SAndrew Moore case '\\':
9630154ac8SAndrew Moore if (*++nd == '\n') {
97a4616748SMike Barcroft errmsg = "trailing backslash (\\)";
9830154ac8SAndrew Moore return NULL;
9930154ac8SAndrew Moore }
10030154ac8SAndrew Moore break;
10130154ac8SAndrew Moore }
10230154ac8SAndrew Moore len = nd - ibufp;
10395e6217eSAndrew Moore REALLOC(lhbuf, lhbufsz, len + 1, NULL);
10430154ac8SAndrew Moore memcpy(lhbuf, ibufp, len);
10530154ac8SAndrew Moore lhbuf[len] = '\0';
10630154ac8SAndrew Moore ibufp = nd;
10795e6217eSAndrew Moore return (isbinary) ? NUL_TO_NEWLINE(lhbuf, len) : lhbuf;
10830154ac8SAndrew Moore }
10930154ac8SAndrew Moore
11030154ac8SAndrew Moore
11195e6217eSAndrew Moore /* parse_char_class: expand a POSIX character class */
11230154ac8SAndrew Moore char *
parse_char_class(char * s)1137669d0fcSWarner Losh parse_char_class(char *s)
11430154ac8SAndrew Moore {
11530154ac8SAndrew Moore int c, d;
11630154ac8SAndrew Moore
11730154ac8SAndrew Moore if (*s == '^')
11830154ac8SAndrew Moore s++;
11930154ac8SAndrew Moore if (*s == ']')
12030154ac8SAndrew Moore s++;
12130154ac8SAndrew Moore for (; *s != ']' && *s != '\n'; s++)
12230154ac8SAndrew Moore if (*s == '[' && ((d = *(s+1)) == '.' || d == ':' || d == '='))
12330154ac8SAndrew Moore for (s++, c = *++s; *s != ']' || c != d; s++)
12430154ac8SAndrew Moore if ((c = *s) == '\n')
12530154ac8SAndrew Moore return NULL;
12630154ac8SAndrew Moore return (*s == ']') ? s : NULL;
12730154ac8SAndrew Moore }
128