1 /* $OpenBSD: re.c,v 1.11 2009/10/27 23:59:21 deraadt 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 "ed.h" 33 34 35 extern int patlock; 36 37 char errmsg[MAXPATHLEN + 40] = ""; 38 39 /* get_compiled_pattern: return pointer to compiled pattern from command 40 buffer */ 41 pattern_t * 42 get_compiled_pattern(void) 43 { 44 static pattern_t *exp = NULL; 45 46 char *exps; 47 char delimiter; 48 int n; 49 50 if ((delimiter = *ibufp) == ' ') { 51 seterrmsg("invalid pattern delimiter"); 52 return NULL; 53 } else if (delimiter == '\n' || *++ibufp == '\n' || *ibufp == delimiter) { 54 if (!exp) 55 seterrmsg("no previous pattern"); 56 return exp; 57 } else if ((exps = extract_pattern(delimiter)) == NULL) 58 return NULL; 59 /* buffer alloc'd && not reserved */ 60 if (exp && !patlock) 61 regfree(exp); 62 else if ((exp = (pattern_t *) malloc(sizeof(pattern_t))) == NULL) { 63 perror(NULL); 64 seterrmsg("out of memory"); 65 return NULL; 66 } 67 patlock = 0; 68 if ((n = regcomp(exp, exps, 0)) != 0) { 69 regerror(n, exp, errmsg, sizeof errmsg); 70 free(exp); 71 return exp = NULL; 72 } 73 return exp; 74 } 75 76 77 /* extract_pattern: copy a pattern string from the command buffer; return 78 pointer to the copy */ 79 char * 80 extract_pattern(int delimiter) 81 { 82 static char *lhbuf = NULL; /* buffer */ 83 static int lhbufsz = 0; /* buffer size */ 84 85 char *nd; 86 int len; 87 88 for (nd = ibufp; *nd != delimiter && *nd != '\n'; nd++) 89 switch (*nd) { 90 default: 91 break; 92 case '[': 93 if ((nd = parse_char_class(++nd)) == NULL) { 94 seterrmsg("unbalanced brackets ([])"); 95 return NULL; 96 } 97 break; 98 case '\\': 99 if (*++nd == '\n') { 100 seterrmsg("trailing backslash (\\)"); 101 return NULL; 102 } 103 break; 104 } 105 len = nd - ibufp; 106 REALLOC(lhbuf, lhbufsz, len + 1, NULL); 107 memcpy(lhbuf, ibufp, len); 108 lhbuf[len] = '\0'; 109 ibufp = nd; 110 return (isbinary) ? NUL_TO_NEWLINE(lhbuf, len) : lhbuf; 111 } 112 113 114 /* parse_char_class: expand a POSIX character class */ 115 char * 116 parse_char_class(char *s) 117 { 118 int c, d; 119 120 if (*s == '^') 121 s++; 122 if (*s == ']') 123 s++; 124 for (; *s != ']' && *s != '\n'; s++) 125 if (*s == '[' && ((d = *(s+1)) == '.' || d == ':' || d == '=')) 126 for (s++, c = *++s; *s != ']' || c != d; s++) 127 if ((c = *s) == '\n') 128 return NULL; 129 return (*s == ']') ? s : NULL; 130 } 131