xref: /freebsd/bin/ed/re.c (revision 1d386b48a555f61cb7325543adbbb5c3f3407a66)
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