15dfecf96Smrg/* 25dfecf96Smrg * Copyright (c) 2002 by The XFree86 Project, Inc. 35dfecf96Smrg * 45dfecf96Smrg * Permission is hereby granted, free of charge, to any person obtaining a 55dfecf96Smrg * copy of this software and associated documentation files (the "Software"), 65dfecf96Smrg * to deal in the Software without restriction, including without limitation 75dfecf96Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 85dfecf96Smrg * and/or sell copies of the Software, and to permit persons to whom the 95dfecf96Smrg * Software is furnished to do so, subject to the following conditions: 105dfecf96Smrg * 115dfecf96Smrg * The above copyright notice and this permission notice shall be included in 125dfecf96Smrg * all copies or substantial portions of the Software. 135dfecf96Smrg * 145dfecf96Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 155dfecf96Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 165dfecf96Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 175dfecf96Smrg * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 185dfecf96Smrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 195dfecf96Smrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 205dfecf96Smrg * SOFTWARE. 215dfecf96Smrg * 225dfecf96Smrg * Except as contained in this notice, the name of the XFree86 Project shall 235dfecf96Smrg * not be used in advertising or otherwise to promote the sale, use or other 245dfecf96Smrg * dealings in this Software without prior written authorization from the 255dfecf96Smrg * XFree86 Project. 265dfecf96Smrg * 275dfecf96Smrg * Author: Paulo César Pereira de Andrade 285dfecf96Smrg */ 295dfecf96Smrg 305dfecf96Smrg/* $XFree86: xc/programs/xedit/lisp/regex.c,v 1.10tsi Exp $ */ 315dfecf96Smrg 325dfecf96Smrg#include "lisp/regex.h" 335dfecf96Smrg#include "lisp/private.h" 345dfecf96Smrg#include "lisp/helper.h" 355dfecf96Smrg 365dfecf96Smrg/* 375dfecf96Smrg * Prototypes 385dfecf96Smrg */ 395dfecf96Smrgstatic re_cod *LispRecomp(LispBuiltin*, char*, int); 405dfecf96Smrg 415dfecf96Smrg/* 425dfecf96Smrg * Initialization 435dfecf96Smrg */ 445dfecf96SmrgLispObj *Knomatch; 455dfecf96Smrg 465dfecf96Smrg/* 475dfecf96Smrg * Implementation 485dfecf96Smrg */ 495dfecf96Smrgstatic re_cod * 505dfecf96SmrgLispRecomp(LispBuiltin *builtin, char *pattern, int cflags) 515dfecf96Smrg{ 525dfecf96Smrg int code; 535dfecf96Smrg re_cod *regex = LispMalloc(sizeof(re_cod)); 545dfecf96Smrg 555dfecf96Smrg if ((code = recomp(regex, pattern, cflags)) != 0) { 565dfecf96Smrg char buffer[256]; 575dfecf96Smrg 585dfecf96Smrg reerror(code, regex, buffer, sizeof(buffer)); 595dfecf96Smrg refree(regex); 605dfecf96Smrg LispFree(regex); 615dfecf96Smrg LispDestroy("%s: recomp(\"%s\"): %s", STRFUN(builtin), pattern, buffer); 625dfecf96Smrg } 635dfecf96Smrg 645dfecf96Smrg return (regex); 655dfecf96Smrg} 665dfecf96Smrg 675dfecf96Smrgvoid 685dfecf96SmrgLispRegexInit(void) 695dfecf96Smrg{ 705dfecf96Smrg Knomatch = KEYWORD("NOMATCH"); 715dfecf96Smrg} 725dfecf96Smrg 735dfecf96SmrgLispObj * 745dfecf96SmrgLisp_Recomp(LispBuiltin *builtin) 755dfecf96Smrg/* 765dfecf96Smrg re-comp pattern &key nospec icase nosub newline 775dfecf96Smrg */ 785dfecf96Smrg{ 795dfecf96Smrg re_cod *regex; 805dfecf96Smrg int cflags = 0; 815dfecf96Smrg 825dfecf96Smrg LispObj *result; 835dfecf96Smrg 845dfecf96Smrg LispObj *pattern, *nospec, *icase, *nosub, *newline; 855dfecf96Smrg 865dfecf96Smrg newline = ARGUMENT(4); 875dfecf96Smrg nosub = ARGUMENT(3); 885dfecf96Smrg icase = ARGUMENT(2); 895dfecf96Smrg nospec = ARGUMENT(1); 905dfecf96Smrg pattern = ARGUMENT(0); 915dfecf96Smrg 925dfecf96Smrg /* Don't generate an error if it is already a compiled regex. */ 935dfecf96Smrg if (REGEXP(pattern)) 945dfecf96Smrg return (pattern); 955dfecf96Smrg 965dfecf96Smrg CHECK_STRING(pattern); 975dfecf96Smrg 985dfecf96Smrg if (nospec != UNSPEC && nospec != NIL) 995dfecf96Smrg cflags |= RE_NOSPEC; 1005dfecf96Smrg if (icase != UNSPEC && icase != NIL) 1015dfecf96Smrg cflags |= RE_ICASE; 1025dfecf96Smrg if (nosub != UNSPEC && nosub != NIL) 1035dfecf96Smrg cflags |= RE_NOSUB; 1045dfecf96Smrg if (newline != UNSPEC && newline != NIL) 1055dfecf96Smrg cflags |= RE_NEWLINE; 1065dfecf96Smrg 1075dfecf96Smrg regex = LispRecomp(builtin, THESTR(pattern), cflags); 1085dfecf96Smrg result = LispNew(pattern, NIL); 1095dfecf96Smrg result->type = LispRegex_t; 1105dfecf96Smrg result->data.regex.regex = regex; 1115dfecf96Smrg result->data.regex.pattern = pattern; 1125dfecf96Smrg result->data.regex.options = cflags; 1135dfecf96Smrg LispMused(regex); 1145dfecf96Smrg 1155dfecf96Smrg return (result); 1165dfecf96Smrg} 1175dfecf96Smrg 1185dfecf96SmrgLispObj * 1195dfecf96SmrgLisp_Reexec(LispBuiltin *builtin) 1205dfecf96Smrg/* 1215dfecf96Smrg re-exec regex string &key count start end notbol noteol 1225dfecf96Smrg */ 1235dfecf96Smrg{ 1245dfecf96Smrg size_t nmatch; 1255dfecf96Smrg re_mat match[10]; 1265dfecf96Smrg long start, end, length; 1275dfecf96Smrg int code, cflags, eflags; 1285dfecf96Smrg char *string; 1295dfecf96Smrg LispObj *result; 1305dfecf96Smrg re_cod *regexp; 1315dfecf96Smrg 1325dfecf96Smrg LispObj *regex, *ostring, *count, *ostart, *oend, *notbol, *noteol; 1335dfecf96Smrg 1345dfecf96Smrg noteol = ARGUMENT(6); 1355dfecf96Smrg notbol = ARGUMENT(5); 1365dfecf96Smrg oend = ARGUMENT(4); 1375dfecf96Smrg ostart = ARGUMENT(3); 1385dfecf96Smrg count = ARGUMENT(2); 1395dfecf96Smrg ostring = ARGUMENT(1); 1405dfecf96Smrg regex = ARGUMENT(0); 1415dfecf96Smrg 1425dfecf96Smrg if (STRINGP(regex)) 1435dfecf96Smrg regexp = LispRecomp(builtin, THESTR(regex), cflags = 0); 1445dfecf96Smrg else { 1455dfecf96Smrg CHECK_REGEX(regex); 1465dfecf96Smrg regexp = regex->data.regex.regex; 1475dfecf96Smrg cflags = regex->data.regex.options; 1485dfecf96Smrg } 1495dfecf96Smrg 1505dfecf96Smrg CHECK_STRING(ostring); 1515dfecf96Smrg 1525dfecf96Smrg if (count == UNSPEC) 1535dfecf96Smrg nmatch = 1; 1545dfecf96Smrg else { 1555dfecf96Smrg CHECK_INDEX(count); 1565dfecf96Smrg nmatch = FIXNUM_VALUE(count); 1575dfecf96Smrg if (nmatch > 10) 1585dfecf96Smrg LispDestroy("%s: COUNT cannot be larger than 10", STRFUN(builtin)); 1595dfecf96Smrg } 1605dfecf96Smrg if (nmatch && (cflags & RE_NOSUB)) 1615dfecf96Smrg nmatch = 1; 1625dfecf96Smrg 1635dfecf96Smrg eflags = RE_STARTEND; 1645dfecf96Smrg if (notbol != UNSPEC && notbol != NIL) 1655dfecf96Smrg eflags |= RE_NOTBOL; 1665dfecf96Smrg if (noteol != UNSPEC && noteol != NIL) 1675dfecf96Smrg eflags |= RE_NOTEOL; 1685dfecf96Smrg 1695dfecf96Smrg string = THESTR(ostring); 1705dfecf96Smrg LispCheckSequenceStartEnd(builtin, ostring, ostart, oend, 1715dfecf96Smrg &start, &end, &length); 1725dfecf96Smrg 1735dfecf96Smrg match[0].rm_so = start; 1745dfecf96Smrg match[0].rm_eo = end; 1755dfecf96Smrg code = reexec(regexp, string, nmatch, &match[0], eflags); 1765dfecf96Smrg 1775dfecf96Smrg if (code == 0) { 1785dfecf96Smrg if (nmatch && match[0].rm_eo >= match[0].rm_so) { 1795dfecf96Smrg result = CONS(CONS(FIXNUM(match[0].rm_so), 1805dfecf96Smrg FIXNUM(match[0].rm_eo)), NIL); 1815dfecf96Smrg if (nmatch > 1 && match[1].rm_eo >= match[1].rm_so) { 1825dfecf96Smrg int i; 1835dfecf96Smrg GC_ENTER(); 1845dfecf96Smrg LispObj *cons = result; 1855dfecf96Smrg 1865dfecf96Smrg GC_PROTECT(result); 1875dfecf96Smrg for (i = 1; 1885dfecf96Smrg i < nmatch && match[i].rm_eo >= match[i].rm_so; 1895dfecf96Smrg i++) { 1905dfecf96Smrg RPLACD(cons, CONS(CONS(FIXNUM(match[i].rm_so), 1915dfecf96Smrg FIXNUM(match[i].rm_eo)), NIL)); 1925dfecf96Smrg cons = CDR(cons); 1935dfecf96Smrg } 1945dfecf96Smrg GC_LEAVE(); 1955dfecf96Smrg } 1965dfecf96Smrg } 1975dfecf96Smrg else 1985dfecf96Smrg result = NIL; 1995dfecf96Smrg } 2005dfecf96Smrg else 2015dfecf96Smrg result = Knomatch; 2025dfecf96Smrg 2035dfecf96Smrg /* Maybe shoud cache compiled regex, but better the caller do it */ 2045dfecf96Smrg if (!XREGEXP(regex)) { 2055dfecf96Smrg refree(regexp); 2065dfecf96Smrg LispFree(regexp); 2075dfecf96Smrg } 2085dfecf96Smrg 2095dfecf96Smrg return (result); 2105dfecf96Smrg} 2115dfecf96Smrg 2125dfecf96SmrgLispObj * 2135dfecf96SmrgLisp_Rep(LispBuiltin *builtin) 2145dfecf96Smrg/* 2155dfecf96Smrg re-p object 2165dfecf96Smrg */ 2175dfecf96Smrg{ 2185dfecf96Smrg LispObj *object; 2195dfecf96Smrg 2205dfecf96Smrg object = ARGUMENT(0); 2215dfecf96Smrg 2225dfecf96Smrg return (REGEXP(object) ? T : NIL); 2235dfecf96Smrg} 224