xref: /netbsd-src/bin/ed/re.c (revision a3542600fb90a091eaaa565870223a5fc9ee33e4)
1*a3542600Sdholland /*	$NetBSD: re.c,v 1.21 2014/03/23 05:06:42 dholland Exp $	*/
249f0ad86Scgd 
39b082a69Scgd /* re.c: This file contains the regular expression interface routines for
49b082a69Scgd    the ed line editor. */
59b082a69Scgd /*-
6ba4d688dSalm  * Copyright (c) 1993 Andrew Moore, Talke Studio.
79b082a69Scgd  * All rights reserved.
89b082a69Scgd  *
99b082a69Scgd  * Redistribution and use in source and binary forms, with or without
109b082a69Scgd  * modification, are permitted provided that the following conditions
119b082a69Scgd  * are met:
129b082a69Scgd  * 1. Redistributions of source code must retain the above copyright
139b082a69Scgd  *    notice, this list of conditions and the following disclaimer.
149b082a69Scgd  * 2. Redistributions in binary form must reproduce the above copyright
159b082a69Scgd  *    notice, this list of conditions and the following disclaimer in the
169b082a69Scgd  *    documentation and/or other materials provided with the distribution.
179b082a69Scgd  *
18ba4d688dSalm  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
199b082a69Scgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
209b082a69Scgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21ba4d688dSalm  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
229b082a69Scgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
239b082a69Scgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
249b082a69Scgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
259b082a69Scgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
269b082a69Scgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
279b082a69Scgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
289b082a69Scgd  * SUCH DAMAGE.
299b082a69Scgd  */
309b082a69Scgd 
318b7ade1aSthorpej #include <sys/cdefs.h>
329b082a69Scgd #ifndef lint
3349f0ad86Scgd #if 0
341357f155Salm static char *rcsid = "@(#)re.c,v 1.6 1994/02/01 00:34:43 alm Exp";
3549f0ad86Scgd #else
36*a3542600Sdholland __RCSID("$NetBSD: re.c,v 1.21 2014/03/23 05:06:42 dholland Exp $");
3749f0ad86Scgd #endif
389b082a69Scgd #endif /* not lint */
399b082a69Scgd 
40*a3542600Sdholland #include <stdarg.h>
419b082a69Scgd #include "ed.h"
429b082a69Scgd 
431357f155Salm 
441357f155Salm char errmsg[MAXPATHLEN + 40] = "";
459b082a69Scgd 
46*a3542600Sdholland void
seterrmsg(const char * fmt,...)47*a3542600Sdholland seterrmsg(const char *fmt, ...)
48*a3542600Sdholland {
49*a3542600Sdholland 	va_list ap;
50*a3542600Sdholland 
51*a3542600Sdholland 	va_start(ap, fmt);
52*a3542600Sdholland 	vsnprintf(errmsg, sizeof(errmsg), fmt, ap);
53*a3542600Sdholland 	va_end(ap);
54*a3542600Sdholland }
55*a3542600Sdholland 
569380925bSalm /* get_compiled_pattern: return pointer to compiled pattern from command
579380925bSalm    buffer */
589b082a69Scgd pattern_t *
get_compiled_pattern(void)59d33a7206Sxtraeme get_compiled_pattern(void)
609b082a69Scgd {
61c87e2cf5Sthorpej 	static pattern_t *expr = NULL;
629b082a69Scgd 
639b082a69Scgd 	char *exps;
649380925bSalm 	char delimiter;
659b082a69Scgd 	int n;
669b082a69Scgd 
679380925bSalm 	if ((delimiter = *ibufp) == ' ') {
68*a3542600Sdholland 		seterrmsg("invalid pattern delimiter");
699b082a69Scgd 		return NULL;
709380925bSalm 	} else if (delimiter == '\n' || *++ibufp == '\n' || *ibufp == delimiter) {
71*a3542600Sdholland 		if (!expr) seterrmsg("no previous pattern");
72c87e2cf5Sthorpej 		return expr;
739380925bSalm 	} else if ((exps = extract_pattern(delimiter)) == NULL)
749b082a69Scgd 		return NULL;
759b082a69Scgd 	/* buffer alloc'd && not reserved */
76c87e2cf5Sthorpej 	if (expr && !patlock)
77c87e2cf5Sthorpej 		regfree(expr);
78c87e2cf5Sthorpej 	else if ((expr = (pattern_t *) malloc(sizeof(pattern_t))) == NULL) {
79b9b97259Salm 		fprintf(stderr, "%s\n", strerror(errno));
80*a3542600Sdholland 		seterrmsg("out of memory");
819b082a69Scgd 		return NULL;
829b082a69Scgd 	}
839b082a69Scgd 	patlock = 0;
84c87e2cf5Sthorpej 	if ((n = regcomp(expr, exps, ere)) != 0) {
85c87e2cf5Sthorpej 		regerror(n, expr, errmsg, sizeof errmsg);
86c87e2cf5Sthorpej 		free(expr);
87c87e2cf5Sthorpej 		return expr = NULL;
889b082a69Scgd 	}
89c87e2cf5Sthorpej 	return expr;
909b082a69Scgd }
919b082a69Scgd 
929b082a69Scgd 
939380925bSalm /* extract_pattern: copy a pattern string from the command buffer; return
949380925bSalm    pointer to the copy */
959b082a69Scgd char *
extract_pattern(int delimiter)96d33a7206Sxtraeme extract_pattern(int delimiter)
979b082a69Scgd {
981357f155Salm 	static char *lhbuf = NULL;	/* buffer */
991357f155Salm 	static int lhbufsz = 0;		/* buffer size */
1001357f155Salm 
1019b082a69Scgd 	char *nd;
1022621a68cSalm 	int len;
1039b082a69Scgd 
1049380925bSalm 	for (nd = ibufp; *nd != delimiter && *nd != '\n'; nd++)
1059b082a69Scgd 		switch (*nd) {
1069b082a69Scgd 		default:
1079b082a69Scgd 			break;
1082621a68cSalm 		case '[':
1099e697204Sjoerg 			if ((nd = parse_char_class(nd + 1)) == NULL) {
110*a3542600Sdholland 				seterrmsg("unbalanced brackets ([])");
1119b082a69Scgd 				return NULL;
1129b082a69Scgd 			}
1139b082a69Scgd 			break;
1142621a68cSalm 		case '\\':
1159b082a69Scgd 			if (*++nd == '\n') {
116*a3542600Sdholland 				seterrmsg("trailing backslash (\\)");
1179b082a69Scgd 				return NULL;
1189b082a69Scgd 			}
1199b082a69Scgd 			break;
1209b082a69Scgd 		}
1212621a68cSalm 	len = nd - ibufp;
1221357f155Salm 	REALLOC(lhbuf, lhbufsz, len + 1, NULL);
1232621a68cSalm 	memcpy(lhbuf, ibufp, len);
1242621a68cSalm 	lhbuf[len] = '\0';
1259b082a69Scgd 	ibufp = nd;
1269380925bSalm 	return (isbinary) ? NUL_TO_NEWLINE(lhbuf, len) : lhbuf;
1279b082a69Scgd }
1289b082a69Scgd 
1299b082a69Scgd 
1309380925bSalm /* parse_char_class: expand a POSIX character class */
1319b082a69Scgd char *
parse_char_class(char * s)132d33a7206Sxtraeme parse_char_class(char *s)
1339b082a69Scgd {
134fc782b3fSalm 	int c, d;
135fc782b3fSalm 
136fc782b3fSalm 	if (*s == '^')
137fc782b3fSalm 		s++;
138fc782b3fSalm 	if (*s == ']')
139fc782b3fSalm 		s++;
140fc782b3fSalm 	for (; *s != ']' && *s != '\n'; s++)
141fc782b3fSalm 		if (*s == '[' && ((d = *(s+1)) == '.' || d == ':' || d == '='))
142fc782b3fSalm 			for (s++, c = *++s; *s != ']' || c != d; s++)
143fc782b3fSalm 				if ((c = *s) == '\n')
144fc782b3fSalm 					return NULL;
145fc782b3fSalm 	return  (*s == ']') ? s : NULL;
1469b082a69Scgd }
147