| 1 |  |  | /*	$OpenBSD: re.c,v 1.17 2016/03/22 17:58:28 mmcc Exp $	*/ | 
    
    | 2 |  |  | /*	$NetBSD: re.c,v 1.14 1995/03/21 09:04:48 cgd Exp $	*/ | 
    
    | 3 |  |  |  | 
    
    | 4 |  |  | /* re.c: This file contains the regular expression interface routines for | 
    
    | 5 |  |  |    the ed line editor. */ | 
    
    | 6 |  |  | /*- | 
    
    | 7 |  |  |  * Copyright (c) 1993 Andrew Moore, Talke Studio. | 
    
    | 8 |  |  |  * All rights reserved. | 
    
    | 9 |  |  |  * | 
    
    | 10 |  |  |  * Redistribution and use in source and binary forms, with or without | 
    
    | 11 |  |  |  * modification, are permitted provided that the following conditions | 
    
    | 12 |  |  |  * are met: | 
    
    | 13 |  |  |  * 1. Redistributions of source code must retain the above copyright | 
    
    | 14 |  |  |  *    notice, this list of conditions and the following disclaimer. | 
    
    | 15 |  |  |  * 2. Redistributions in binary form must reproduce the above copyright | 
    
    | 16 |  |  |  *    notice, this list of conditions and the following disclaimer in the | 
    
    | 17 |  |  |  *    documentation and/or other materials provided with the distribution. | 
    
    | 18 |  |  |  * | 
    
    | 19 |  |  |  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | 
    
    | 20 |  |  |  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 
    
    | 21 |  |  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 
    
    | 22 |  |  |  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | 
    
    | 23 |  |  |  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 
    
    | 24 |  |  |  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 
    
    | 25 |  |  |  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 
    
    | 26 |  |  |  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 
    
    | 27 |  |  |  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 
    
    | 28 |  |  |  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 
    
    | 29 |  |  |  * SUCH DAMAGE. | 
    
    | 30 |  |  |  */ | 
    
    | 31 |  |  |  | 
    
    | 32 |  |  | #include <regex.h> | 
    
    | 33 |  |  | #include <signal.h> | 
    
    | 34 |  |  | #include <stdio.h> | 
    
    | 35 |  |  | #include <stdlib.h> | 
    
    | 36 |  |  | #include <string.h> | 
    
    | 37 |  |  |  | 
    
    | 38 |  |  | #include "ed.h" | 
    
    | 39 |  |  |  | 
    
    | 40 |  |  | static char *extract_pattern(int); | 
    
    | 41 |  |  | static char *parse_char_class(char *); | 
    
    | 42 |  |  |  | 
    
    | 43 |  |  | extern int patlock; | 
    
    | 44 |  |  |  | 
    
    | 45 |  |  |  | 
    
    | 46 |  |  | /* get_compiled_pattern: return pointer to compiled pattern from command | 
    
    | 47 |  |  |    buffer */ | 
    
    | 48 |  |  | regex_t * | 
    
    | 49 |  |  | get_compiled_pattern(void) | 
    
    | 50 |  |  | { | 
    
    | 51 |  |  | 	static regex_t *exp = NULL; | 
    
    | 52 |  |  | 	char errbuf[128] = ""; | 
    
    | 53 |  |  |  | 
    
    | 54 |  |  | 	char *exps; | 
    
    | 55 |  |  | 	char delimiter; | 
    
    | 56 |  |  | 	int n; | 
    
    | 57 |  |  |  | 
    
    | 58 |  |  | 	if ((delimiter = *ibufp) == ' ') { | 
    
    | 59 |  |  | 		seterrmsg("invalid pattern delimiter"); | 
    
    | 60 |  |  | 		return NULL; | 
    
    | 61 |  |  | 	} else if (delimiter == '\n' || *++ibufp == '\n' || *ibufp == delimiter) { | 
    
    | 62 |  |  | 		if (!exp) | 
    
    | 63 |  |  | 			seterrmsg("no previous pattern"); | 
    
    | 64 |  |  | 		return exp; | 
    
    | 65 |  |  | 	} else if ((exps = extract_pattern(delimiter)) == NULL) | 
    
    | 66 |  |  | 		return NULL; | 
    
    | 67 |  |  | 	/* buffer alloc'd && not reserved */ | 
    
    | 68 |  |  | 	if (exp && !patlock) | 
    
    | 69 |  |  | 		regfree(exp); | 
    
    | 70 |  |  | 	else if ((exp = malloc(sizeof(regex_t))) == NULL) { | 
    
    | 71 |  |  | 		perror(NULL); | 
    
    | 72 |  |  | 		seterrmsg("out of memory"); | 
    
    | 73 |  |  | 		return NULL; | 
    
    | 74 |  |  | 	} | 
    
    | 75 |  |  | 	patlock = 0; | 
    
    | 76 |  |  | 	if ((n = regcomp(exp, exps, 0)) != 0) { | 
    
    | 77 |  |  | 		regerror(n, exp, errbuf, sizeof errbuf); | 
    
    | 78 |  |  | 		seterrmsg(errbuf); | 
    
    | 79 |  |  | 		free(exp); | 
    
    | 80 |  |  | 		return exp = NULL; | 
    
    | 81 |  |  | 	} | 
    
    | 82 |  |  | 	return exp; | 
    
    | 83 |  |  | } | 
    
    | 84 |  |  |  | 
    
    | 85 |  |  |  | 
    
    | 86 |  |  | /* extract_pattern: copy a pattern string from the command buffer; return | 
    
    | 87 |  |  |    pointer to the copy */ | 
    
    | 88 |  |  | static char * | 
    
    | 89 |  |  | extract_pattern(int delimiter) | 
    
    | 90 |  |  | { | 
    
    | 91 |  |  | 	static char *lhbuf = NULL;	/* buffer */ | 
    
    | 92 |  |  | 	static int lhbufsz = 0;		/* buffer size */ | 
    
    | 93 |  |  |  | 
    
    | 94 |  |  | 	char *nd; | 
    
    | 95 |  |  | 	int len; | 
    
    | 96 |  |  |  | 
    
    | 97 |  |  | 	for (nd = ibufp; *nd != delimiter && *nd != '\n'; nd++) | 
    
    | 98 |  |  | 		switch (*nd) { | 
    
    | 99 |  |  | 		default: | 
    
    | 100 |  |  | 			break; | 
    
    | 101 |  |  | 		case '[': | 
    
    | 102 |  |  | 			if ((nd = parse_char_class(++nd)) == NULL) { | 
    
    | 103 |  |  | 				seterrmsg("unbalanced brackets ([])"); | 
    
    | 104 |  |  | 				return NULL; | 
    
    | 105 |  |  | 			} | 
    
    | 106 |  |  | 			break; | 
    
    | 107 |  |  | 		case '\\': | 
    
    | 108 |  |  | 			if (*++nd == '\n') { | 
    
    | 109 |  |  | 				seterrmsg("trailing backslash (\\)"); | 
    
    | 110 |  |  | 				return NULL; | 
    
    | 111 |  |  | 			} | 
    
    | 112 |  |  | 			break; | 
    
    | 113 |  |  | 		} | 
    
    | 114 |  |  | 	len = nd - ibufp; | 
    
    | 115 |  |  | 	REALLOC(lhbuf, lhbufsz, len + 1, NULL); | 
    
    | 116 |  |  | 	memcpy(lhbuf, ibufp, len); | 
    
    | 117 |  |  | 	lhbuf[len] = '\0'; | 
    
    | 118 |  |  | 	ibufp = nd; | 
    
    | 119 |  |  | 	return (isbinary) ? NUL_TO_NEWLINE(lhbuf, len) : lhbuf; | 
    
    | 120 |  |  | } | 
    
    | 121 |  |  |  | 
    
    | 122 |  |  |  | 
    
    | 123 |  |  | /* parse_char_class: expand a POSIX character class */ | 
    
    | 124 |  |  | static char * | 
    
    | 125 |  |  | parse_char_class(char *s) | 
    
    | 126 |  |  | { | 
    
    | 127 |  |  | 	int c, d; | 
    
    | 128 |  |  |  | 
    
    | 129 |  |  | 	if (*s == '^') | 
    
    | 130 |  |  | 		s++; | 
    
    | 131 |  |  | 	if (*s == ']') | 
    
    | 132 |  |  | 		s++; | 
    
    | 133 |  |  | 	for (; *s != ']' && *s != '\n'; s++) | 
    
    | 134 |  |  | 		if (*s == '[' && ((d = *(s+1)) == '.' || d == ':' || d == '=')) | 
    
    | 135 |  |  | 			for (s++, c = *++s; *s != ']' || c != d; s++) | 
    
    | 136 |  |  | 				if ((c = *s) == '\n') | 
    
    | 137 |  |  | 					return NULL; | 
    
    | 138 |  |  | 	return  (*s == ']') ? s : NULL; | 
    
    | 139 |  |  | } |