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