1/* 2 * Copyright (c) 2002 by The XFree86 Project, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 * SOFTWARE. 21 * 22 * Except as contained in this notice, the name of the XFree86 Project shall 23 * not be used in advertising or otherwise to promote the sale, use or other 24 * dealings in this Software without prior written authorization from the 25 * XFree86 Project. 26 * 27 * Author: Paulo César Pereira de Andrade 28 */ 29 30/* $XFree86: xc/programs/xedit/lisp/regex.c,v 1.10tsi Exp $ */ 31 32#include "lisp/regex.h" 33#include "lisp/private.h" 34#include "lisp/helper.h" 35 36/* 37 * Prototypes 38 */ 39static re_cod *LispRecomp(LispBuiltin*, char*, int); 40 41/* 42 * Initialization 43 */ 44LispObj *Knomatch; 45 46/* 47 * Implementation 48 */ 49static re_cod * 50LispRecomp(LispBuiltin *builtin, char *pattern, int cflags) 51{ 52 int code; 53 re_cod *regex = LispMalloc(sizeof(re_cod)); 54 55 if ((code = recomp(regex, pattern, cflags)) != 0) { 56 char buffer[256]; 57 58 reerror(code, regex, buffer, sizeof(buffer)); 59 refree(regex); 60 LispFree(regex); 61 LispDestroy("%s: recomp(\"%s\"): %s", STRFUN(builtin), pattern, buffer); 62 } 63 64 return (regex); 65} 66 67void 68LispRegexInit(void) 69{ 70 Knomatch = KEYWORD("NOMATCH"); 71} 72 73LispObj * 74Lisp_Recomp(LispBuiltin *builtin) 75/* 76 re-comp pattern &key nospec icase nosub newline 77 */ 78{ 79 re_cod *regex; 80 int cflags = 0; 81 82 LispObj *result; 83 84 LispObj *pattern, *nospec, *icase, *nosub, *newline; 85 86 newline = ARGUMENT(4); 87 nosub = ARGUMENT(3); 88 icase = ARGUMENT(2); 89 nospec = ARGUMENT(1); 90 pattern = ARGUMENT(0); 91 92 /* Don't generate an error if it is already a compiled regex. */ 93 if (REGEXP(pattern)) 94 return (pattern); 95 96 CHECK_STRING(pattern); 97 98 if (nospec != UNSPEC && nospec != NIL) 99 cflags |= RE_NOSPEC; 100 if (icase != UNSPEC && icase != NIL) 101 cflags |= RE_ICASE; 102 if (nosub != UNSPEC && nosub != NIL) 103 cflags |= RE_NOSUB; 104 if (newline != UNSPEC && newline != NIL) 105 cflags |= RE_NEWLINE; 106 107 regex = LispRecomp(builtin, THESTR(pattern), cflags); 108 result = LispNew(pattern, NIL); 109 result->type = LispRegex_t; 110 result->data.regex.regex = regex; 111 result->data.regex.pattern = pattern; 112 result->data.regex.options = cflags; 113 LispMused(regex); 114 115 return (result); 116} 117 118LispObj * 119Lisp_Reexec(LispBuiltin *builtin) 120/* 121 re-exec regex string &key count start end notbol noteol 122 */ 123{ 124 size_t nmatch; 125 re_mat match[10]; 126 long start, end, length; 127 int code, cflags, eflags; 128 char *string; 129 LispObj *result; 130 re_cod *regexp; 131 132 LispObj *regex, *ostring, *count, *ostart, *oend, *notbol, *noteol; 133 134 noteol = ARGUMENT(6); 135 notbol = ARGUMENT(5); 136 oend = ARGUMENT(4); 137 ostart = ARGUMENT(3); 138 count = ARGUMENT(2); 139 ostring = ARGUMENT(1); 140 regex = ARGUMENT(0); 141 142 if (STRINGP(regex)) 143 regexp = LispRecomp(builtin, THESTR(regex), cflags = 0); 144 else { 145 CHECK_REGEX(regex); 146 regexp = regex->data.regex.regex; 147 cflags = regex->data.regex.options; 148 } 149 150 CHECK_STRING(ostring); 151 152 if (count == UNSPEC) 153 nmatch = 1; 154 else { 155 CHECK_INDEX(count); 156 nmatch = FIXNUM_VALUE(count); 157 if (nmatch > 10) 158 LispDestroy("%s: COUNT cannot be larger than 10", STRFUN(builtin)); 159 } 160 if (nmatch && (cflags & RE_NOSUB)) 161 nmatch = 1; 162 163 eflags = RE_STARTEND; 164 if (notbol != UNSPEC && notbol != NIL) 165 eflags |= RE_NOTBOL; 166 if (noteol != UNSPEC && noteol != NIL) 167 eflags |= RE_NOTEOL; 168 169 string = THESTR(ostring); 170 LispCheckSequenceStartEnd(builtin, ostring, ostart, oend, 171 &start, &end, &length); 172 173 match[0].rm_so = start; 174 match[0].rm_eo = end; 175 code = reexec(regexp, string, nmatch, &match[0], eflags); 176 177 if (code == 0) { 178 if (nmatch && match[0].rm_eo >= match[0].rm_so) { 179 result = CONS(CONS(FIXNUM(match[0].rm_so), 180 FIXNUM(match[0].rm_eo)), NIL); 181 if (nmatch > 1 && match[1].rm_eo >= match[1].rm_so) { 182 int i; 183 GC_ENTER(); 184 LispObj *cons = result; 185 186 GC_PROTECT(result); 187 for (i = 1; 188 i < nmatch && match[i].rm_eo >= match[i].rm_so; 189 i++) { 190 RPLACD(cons, CONS(CONS(FIXNUM(match[i].rm_so), 191 FIXNUM(match[i].rm_eo)), NIL)); 192 cons = CDR(cons); 193 } 194 GC_LEAVE(); 195 } 196 } 197 else 198 result = NIL; 199 } 200 else 201 result = Knomatch; 202 203 /* Maybe shoud cache compiled regex, but better the caller do it */ 204 if (!XREGEXP(regex)) { 205 refree(regexp); 206 LispFree(regexp); 207 } 208 209 return (result); 210} 211 212LispObj * 213Lisp_Rep(LispBuiltin *builtin) 214/* 215 re-p object 216 */ 217{ 218 LispObj *object; 219 220 object = ARGUMENT(0); 221 222 return (REGEXP(object) ? T : NIL); 223} 224