/* re.c: This file contains the regular expression interface routines for1the ed line editor. */2/*-3* Copyright (c) 1993 Andrew Moore, Talke Studio.4* All rights reserved.5*6* Redistribution and use in source and binary forms, with or without7* modification, are permitted provided that the following conditions8* are met:9* 1. Redistributions of source code must retain the above copyright10* notice, this list of conditions and the following disclaimer.11* 2. Redistributions in binary form must reproduce the above copyright12* notice, this list of conditions and the following disclaimer in the13* documentation and/or other materials provided with the distribution.14*15* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND16* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE17* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE18* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE19* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL20* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS21* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)22* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT23* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY24* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF25* SUCH DAMAGE.26*/2728#include <sys/cdefs.h>29#include "ed.h"3031const char *errmsg = "";3233/* get_compiled_pattern: return pointer to compiled pattern from command34buffer */35pattern_t *36get_compiled_pattern(void)37{38static pattern_t *expr = NULL;39static char error[1024];4041char *exprs;42char delimiter;43int n;4445if ((delimiter = *ibufp) == ' ') {46errmsg = "invalid pattern delimiter";47return NULL;48} else if (delimiter == '\n' || *++ibufp == '\n' || *ibufp == delimiter) {49if (!expr)50errmsg = "no previous pattern";51return expr;52} else if ((exprs = extract_pattern(delimiter)) == NULL)53return NULL;54/* buffer alloc'd && not reserved */55if (expr && !patlock)56regfree(expr);57else if ((expr = (pattern_t *) malloc(sizeof(pattern_t))) == NULL) {58fprintf(stderr, "%s\n", strerror(errno));59errmsg = "out of memory";60return NULL;61}62patlock = 0;63if ((n = regcomp(expr, exprs, 0))) {64regerror(n, expr, error, sizeof error);65errmsg = error;66free(expr);67return expr = NULL;68}69return expr;70}717273/* extract_pattern: copy a pattern string from the command buffer; return74pointer to the copy */75char *76extract_pattern(int delimiter)77{78static char *lhbuf = NULL; /* buffer */79static int lhbufsz = 0; /* buffer size */8081char *nd;82int len;8384for (nd = ibufp; *nd != delimiter && *nd != '\n'; nd++)85switch (*nd) {86default:87break;88case '[':89if ((nd = parse_char_class(nd + 1)) == NULL) {90errmsg = "unbalanced brackets ([])";91return NULL;92}93break;94case '\\':95if (*++nd == '\n') {96errmsg = "trailing backslash (\\)";97return NULL;98}99break;100}101len = nd - ibufp;102REALLOC(lhbuf, lhbufsz, len + 1, NULL);103memcpy(lhbuf, ibufp, len);104lhbuf[len] = '\0';105ibufp = nd;106return (isbinary) ? NUL_TO_NEWLINE(lhbuf, len) : lhbuf;107}108109110/* parse_char_class: expand a POSIX character class */111char *112parse_char_class(char *s)113{114int c, d;115116if (*s == '^')117s++;118if (*s == ']')119s++;120for (; *s != ']' && *s != '\n'; s++)121if (*s == '[' && ((d = *(s+1)) == '.' || d == ':' || d == '='))122for (s++, c = *++s; *s != ']' || c != d; s++)123if ((c = *s) == '\n')124return NULL;125return (*s == ']') ? s : NULL;126}127128129