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/re/rec.c,v 1.3 2002/11/15 07:01:33 paulo Exp $ */ 315dfecf96Smrg 325dfecf96Smrg#include "rep.h" 335dfecf96Smrg 345dfecf96Smrg/* 355dfecf96Smrg * Types 365dfecf96Smrg */ 375dfecf96Smrg 385dfecf96Smrg/* Information used while compiling the intermediate format of the re. */ 395dfecf96Smrgtypedef struct _irec_info { 405dfecf96Smrg unsigned char *ptr; /* Pointer in the given regex pattern */ 415dfecf96Smrg unsigned char *end; /* End of regex pattern */ 425dfecf96Smrg int flags; /* Compile flags */ 435dfecf96Smrg rec_alt *alt; /* Toplevel first/single alternative */ 445dfecf96Smrg 455dfecf96Smrg rec_alt *palt; /* Current alternative being compiled */ 465dfecf96Smrg rec_grp *pgrp; /* Current group, if any */ 475dfecf96Smrg rec_pat *ppat; /* Current pattern, if any */ 485dfecf96Smrg 495dfecf96Smrg /* Number of open parenthesis, for error checking */ 505dfecf96Smrg int nparens; 515dfecf96Smrg 525dfecf96Smrg int ngrps; /* Number of groups, for backreference */ 535dfecf96Smrg 545dfecf96Smrg int ecode; 555dfecf96Smrg} irec_info; 565dfecf96Smrg 575dfecf96Smrg 585dfecf96Smrg/* 595dfecf96Smrg * Prototypes 605dfecf96Smrg */ 615dfecf96Smrg 625dfecf96Smrg /* (i)ntermediate (r)egular (e)xpression (c)ompile 635dfecf96Smrg * Generates an intermediate stage compiled regex from 645dfecf96Smrg * the specified pattern argument. Basically builds an 655dfecf96Smrg * intermediate data structure to analyse and do syntax 665dfecf96Smrg * error checking. 675dfecf96Smrg */ 685dfecf96Smrgstatic void irec_simple_pattern(irec_info*, rec_pat_t); 695dfecf96Smrgstatic void irec_literal_pattern(irec_info*, int); 705dfecf96Smrgstatic void irec_case_literal_pattern(irec_info*, int); 715dfecf96Smrgstatic void irec_open_group(irec_info*); 725dfecf96Smrgstatic void irec_close_group(irec_info*); 735dfecf96Smrgstatic void irec_range(irec_info*); 745dfecf96Smrgstatic void irec_range_single(irec_info*, int); 755dfecf96Smrgstatic void irec_range_complex(irec_info*, int, int); 765dfecf96Smrgstatic void irec_escape(irec_info*); 775dfecf96Smrgstatic void irec_simple_repetition(irec_info*, rec_rep_t); 785dfecf96Smrgstatic void irec_complex_repetition(irec_info*); 795dfecf96Smrgstatic void irec_add_repetition(irec_info*, rec_rep*); 805dfecf96Smrgstatic void irec_free(irec_info*); 815dfecf96Smrgstatic void irec_free_grp(rec_grp*); 825dfecf96Smrgstatic void irec_free_pats(rec_pat*); 835dfecf96Smrg 845dfecf96Smrg 855dfecf96Smrg/* 865dfecf96Smrg * Implementation 875dfecf96Smrg */ 885dfecf96Smrgrec_alt * 895dfecf96Smrgirec_comp(const char *pattern, const char *endp, int flags, int *ecode) 905dfecf96Smrg{ 915dfecf96Smrg unsigned char *ptr; 925dfecf96Smrg rec_alt *alt; 935dfecf96Smrg irec_info inf; 945dfecf96Smrg 955dfecf96Smrg if (pattern == NULL || endp < pattern) { 965dfecf96Smrg *ecode = RE_INVARG; 975dfecf96Smrg return (NULL); 985dfecf96Smrg } 995dfecf96Smrg 1005dfecf96Smrg if (endp == pattern) { 1015dfecf96Smrg *ecode = RE_EMPTY; 1025dfecf96Smrg return (NULL); 1035dfecf96Smrg } 1045dfecf96Smrg 1055dfecf96Smrg alt = calloc(1, sizeof(rec_alt)); 1065dfecf96Smrg if (alt == NULL) { 1075dfecf96Smrg *ecode = RE_ESPACE; 1085dfecf96Smrg return (NULL); 1095dfecf96Smrg } 1105dfecf96Smrg 1115dfecf96Smrg inf.ptr = (unsigned char*)pattern; 1125dfecf96Smrg inf.end = (unsigned char*)endp; 1135dfecf96Smrg inf.flags = flags; 1145dfecf96Smrg inf.alt = inf.palt = alt; 1155dfecf96Smrg inf.pgrp = NULL; 1165dfecf96Smrg inf.ppat = NULL; 1175dfecf96Smrg inf.nparens = inf.ngrps = 0; 1185dfecf96Smrg inf.ecode = 0; 1195dfecf96Smrg 1205dfecf96Smrg if (flags & RE_NOSPEC) { 1215dfecf96Smrg /* Just searching for a character or substring */ 1225dfecf96Smrg for (; inf.ecode == 0 && inf.ptr < inf.end; inf.ptr++) { 1235dfecf96Smrg if (!(flags & RE_ICASE) || 1245dfecf96Smrg (!isupper(*inf.ptr) && !islower(*inf.ptr))) 1255dfecf96Smrg irec_literal_pattern(&inf, *inf.ptr); 1265dfecf96Smrg else 1275dfecf96Smrg irec_case_literal_pattern(&inf, *inf.ptr); 1285dfecf96Smrg } 1295dfecf96Smrg } 1305dfecf96Smrg /* inf.ptr = inf.end is nul if flags & RE_NOSPEC */ 1315dfecf96Smrg for (; inf.ecode == 0 && inf.ptr < inf.end;) { 1325dfecf96Smrg switch (*inf.ptr++) { 1335dfecf96Smrg case '*': 1345dfecf96Smrg irec_simple_repetition(&inf, Rer_AnyTimes); 1355dfecf96Smrg break; 1365dfecf96Smrg case '+': 1375dfecf96Smrg irec_simple_repetition(&inf, Rer_AtLeast); 1385dfecf96Smrg break; 1395dfecf96Smrg case '?': 1405dfecf96Smrg irec_simple_repetition(&inf, Rer_Maybe); 1415dfecf96Smrg break; 1425dfecf96Smrg case '.': 1435dfecf96Smrg irec_simple_pattern(&inf, Rep_Any); 1445dfecf96Smrg break; 1455dfecf96Smrg case '^': 1465dfecf96Smrg if (flags & RE_NEWLINE) 1475dfecf96Smrg /* It is up to the user decide if this can match */ 1485dfecf96Smrg irec_simple_pattern(&inf, Rep_Bol); 1495dfecf96Smrg else { 1505dfecf96Smrg for (ptr = inf.ptr - 1; 1515dfecf96Smrg ptr > (unsigned char*)pattern && *ptr == '('; ptr--) 1525dfecf96Smrg ; 1535dfecf96Smrg /* If at the start of a pattern */ 1545dfecf96Smrg if (ptr == (unsigned char*)pattern || *ptr == '|') 1555dfecf96Smrg irec_simple_pattern(&inf, Rep_Bol); 1565dfecf96Smrg else 1575dfecf96Smrg /* In the middle of a pattern, treat as literal */ 1585dfecf96Smrg irec_literal_pattern(&inf, '^'); 1595dfecf96Smrg } 1605dfecf96Smrg break; 1615dfecf96Smrg case '$': 1625dfecf96Smrg if (flags & RE_NEWLINE) 1635dfecf96Smrg irec_simple_pattern(&inf, Rep_Eol); 1645dfecf96Smrg else { 1655dfecf96Smrg /* Look ahead to check if is the last char of a group */ 1665dfecf96Smrg for (ptr = inf.ptr; ptr < inf.end && *ptr == ')'; ptr++) 1675dfecf96Smrg ; 1685dfecf96Smrg if (*ptr == '\0' || *ptr == '|') 1695dfecf96Smrg /* Last character of pattern, an EOL match */ 1705dfecf96Smrg irec_simple_pattern(&inf, Rep_Eol); 1715dfecf96Smrg else 1725dfecf96Smrg /* Normal character */ 1735dfecf96Smrg irec_literal_pattern(&inf, '$'); 1745dfecf96Smrg } 1755dfecf96Smrg break; 1765dfecf96Smrg case '(': 1775dfecf96Smrg irec_open_group(&inf); 1785dfecf96Smrg break; 1795dfecf96Smrg case ')': 1805dfecf96Smrg /* Look ahead to check if need to close the group now */ 1815dfecf96Smrg ptr = inf.ptr; 1825dfecf96Smrg if (*ptr != '*' && *ptr != '+' && *ptr != '?' && *ptr != '{') 1835dfecf96Smrg /* If a repetition does not follow */ 1845dfecf96Smrg irec_close_group(&inf); 1855dfecf96Smrg else if (inf.pgrp == NULL) 1865dfecf96Smrg /* A repetition follows, but current group is implicit */ 1875dfecf96Smrg inf.ecode = RE_EPAREN; 1885dfecf96Smrg else 1895dfecf96Smrg /* Can do this as next character is known */ 1905dfecf96Smrg inf.ppat = NULL; 1915dfecf96Smrg break; 1925dfecf96Smrg case '[': 1935dfecf96Smrg irec_range(&inf); 1945dfecf96Smrg break; 1955dfecf96Smrg case ']': 1965dfecf96Smrg irec_literal_pattern(&inf, ']'); 1975dfecf96Smrg break; 1985dfecf96Smrg case '{': 1995dfecf96Smrg irec_complex_repetition(&inf); 2005dfecf96Smrg break; 2015dfecf96Smrg case '}': 2025dfecf96Smrg irec_literal_pattern(&inf, '}'); 2035dfecf96Smrg break; 2045dfecf96Smrg case '|': 2055dfecf96Smrg /* If first character in the pattern */ 2065dfecf96Smrg if (inf.ptr - 1 == (unsigned char*)pattern || 2075dfecf96Smrg /* If last character in the pattern */ 2085dfecf96Smrg inf.ptr >= inf.end || 2095dfecf96Smrg /* If empty pattern */ 2105dfecf96Smrg inf.ptr[0] == '|' || 2115dfecf96Smrg inf.ptr[0] == ')') 2125dfecf96Smrg inf.ecode = RE_EMPTY; 2135dfecf96Smrg else { 2145dfecf96Smrg rec_alt *alt = calloc(1, sizeof(rec_alt)); 2155dfecf96Smrg 2165dfecf96Smrg if (alt) { 2175dfecf96Smrg alt->prev = inf.palt; 2185dfecf96Smrg inf.palt->next = alt; 2195dfecf96Smrg inf.palt = alt; 2205dfecf96Smrg inf.ppat = NULL; 2215dfecf96Smrg } 2225dfecf96Smrg else 2235dfecf96Smrg inf.ecode = RE_ESPACE; 2245dfecf96Smrg } 2255dfecf96Smrg break; 2265dfecf96Smrg case '\\': 2275dfecf96Smrg irec_escape(&inf); 2285dfecf96Smrg break; 2295dfecf96Smrg default: 2305dfecf96Smrg if (!(flags & RE_ICASE) || 2315dfecf96Smrg (!isupper(inf.ptr[-1]) && !islower(inf.ptr[-1]))) 2325dfecf96Smrg irec_literal_pattern(&inf, inf.ptr[-1]); 2335dfecf96Smrg else 2345dfecf96Smrg irec_case_literal_pattern(&inf, inf.ptr[-1]); 2355dfecf96Smrg break; 2365dfecf96Smrg } 2375dfecf96Smrg } 2385dfecf96Smrg 2395dfecf96Smrg /* Check if not all groups closed */ 2405dfecf96Smrg if (inf.ecode == 0 && inf.nparens) 2415dfecf96Smrg inf.ecode = RE_EPAREN; 2425dfecf96Smrg 2435dfecf96Smrg if (inf.ecode == 0) 2445dfecf96Smrg inf.ecode = orec_comp(inf.alt, flags); 2455dfecf96Smrg 2465dfecf96Smrg /* If an error generated */ 2475dfecf96Smrg if (inf.ecode) { 2485dfecf96Smrg irec_free(&inf); 2495dfecf96Smrg alt = NULL; 2505dfecf96Smrg } 2515dfecf96Smrg 2525dfecf96Smrg *ecode = inf.ecode; 2535dfecf96Smrg 2545dfecf96Smrg return (alt); 2555dfecf96Smrg} 2565dfecf96Smrg 2575dfecf96Smrgvoid 2585dfecf96Smrgirec_free_alt(rec_alt *alt) 2595dfecf96Smrg{ 2605dfecf96Smrg rec_alt *next; 2615dfecf96Smrg 2625dfecf96Smrg while (alt) { 2635dfecf96Smrg next = alt->next; 2645dfecf96Smrg irec_free_pats(alt->pat); 2655dfecf96Smrg free(alt); 2665dfecf96Smrg alt = next; 2675dfecf96Smrg } 2685dfecf96Smrg} 2695dfecf96Smrg 2705dfecf96Smrg 2715dfecf96Smrg 2725dfecf96Smrgstatic void 2735dfecf96Smrgirec_simple_pattern(irec_info *inf, rec_pat_t type) 2745dfecf96Smrg{ 2755dfecf96Smrg rec_pat *pat; 2765dfecf96Smrg 2775dfecf96Smrg /* Always add a new pattern to list */ 2785dfecf96Smrg if ((pat = calloc(1, sizeof(rec_pat))) == NULL) { 2795dfecf96Smrg inf->ecode = RE_ESPACE; 2805dfecf96Smrg return; 2815dfecf96Smrg } 2825dfecf96Smrg 2835dfecf96Smrg pat->type = type; 2845dfecf96Smrg if ((pat->prev = inf->ppat) != NULL) 2855dfecf96Smrg inf->ppat->next = pat; 2865dfecf96Smrg else 2875dfecf96Smrg inf->palt->pat = pat; 2885dfecf96Smrg inf->ppat = pat; 2895dfecf96Smrg} 2905dfecf96Smrg 2915dfecf96Smrgstatic void 2925dfecf96Smrgirec_literal_pattern(irec_info *inf, int value) 2935dfecf96Smrg{ 2945dfecf96Smrg int length; 2955dfecf96Smrg rec_pat *pat; 2965dfecf96Smrg unsigned char chr, *str; 2975dfecf96Smrg 2985dfecf96Smrg /* If there is a current pattern */ 2995dfecf96Smrg if (inf->ppat && inf->ppat->rep == NULL) { 3005dfecf96Smrg switch (inf->ppat->type) { 3015dfecf96Smrg case Rep_Literal: 3025dfecf96Smrg /* Start literal string */ 3035dfecf96Smrg chr = inf->ppat->data.chr; 3045dfecf96Smrg if ((str = malloc(16)) == NULL) { 3055dfecf96Smrg inf->ecode = RE_ESPACE; 3065dfecf96Smrg return; 3075dfecf96Smrg } 3085dfecf96Smrg inf->ppat->type = Rep_String; 3095dfecf96Smrg inf->ppat->data.str = str; 3105dfecf96Smrg str[0] = chr; 3115dfecf96Smrg str[1] = value; 3125dfecf96Smrg str[2] = '\0'; 3135dfecf96Smrg return; 3145dfecf96Smrg 3155dfecf96Smrg case Rep_String: 3165dfecf96Smrg /* Augments literal string */ 3175dfecf96Smrg length = strlen((char*)inf->ppat->data.str); 3185dfecf96Smrg if ((length % 16) >= 14) { 3195dfecf96Smrg if ((str = realloc(inf->ppat->data.str, 3205dfecf96Smrg length + 18)) == NULL) { 3215dfecf96Smrg inf->ecode = RE_ESPACE; 3225dfecf96Smrg return; 3235dfecf96Smrg } 3245dfecf96Smrg inf->ppat->data.str = str; 3255dfecf96Smrg } 3265dfecf96Smrg inf->ppat->data.str[length] = value; 3275dfecf96Smrg inf->ppat->data.str[length + 1] = '\0'; 3285dfecf96Smrg return; 3295dfecf96Smrg 3305dfecf96Smrg default: 3315dfecf96Smrg /* Anything else is added as a new pattern list element */ 3325dfecf96Smrg break; 3335dfecf96Smrg } 3345dfecf96Smrg } 3355dfecf96Smrg 3365dfecf96Smrg if ((pat = calloc(1, sizeof(rec_pat))) == NULL) { 3375dfecf96Smrg inf->ecode = RE_ESPACE; 3385dfecf96Smrg return; 3395dfecf96Smrg } 3405dfecf96Smrg 3415dfecf96Smrg pat->type = Rep_Literal; 3425dfecf96Smrg pat->data.chr = value; 3435dfecf96Smrg if ((pat->prev = inf->ppat) != NULL) 3445dfecf96Smrg inf->ppat->next = pat; 3455dfecf96Smrg else 3465dfecf96Smrg inf->palt->pat = pat; 3475dfecf96Smrg inf->ppat = pat; 3485dfecf96Smrg} 3495dfecf96Smrg 3505dfecf96Smrgstatic void 3515dfecf96Smrgirec_case_literal_pattern(irec_info *inf, int value) 3525dfecf96Smrg{ 3535dfecf96Smrg int length; 3545dfecf96Smrg rec_pat *pat; 3555dfecf96Smrg unsigned char plower, pupper, lower, upper, *str; 3565dfecf96Smrg 3575dfecf96Smrg lower = tolower(value); 3585dfecf96Smrg upper = toupper(value); 3595dfecf96Smrg 3605dfecf96Smrg /* If there is a current pattern */ 3615dfecf96Smrg if (inf->ppat && inf->ppat->rep == NULL) { 3625dfecf96Smrg switch (inf->ppat->type) { 3635dfecf96Smrg case Rep_CaseLiteral: 3645dfecf96Smrg /* Start case literal string */ 3655dfecf96Smrg plower = inf->ppat->data.cse.lower; 3665dfecf96Smrg pupper = inf->ppat->data.cse.upper; 3675dfecf96Smrg if ((str = malloc(32)) == NULL) { 3685dfecf96Smrg inf->ecode = RE_ESPACE; 3695dfecf96Smrg return; 3705dfecf96Smrg } 3715dfecf96Smrg inf->ppat->type = Rep_CaseString; 3725dfecf96Smrg inf->ppat->data.str = str; 3735dfecf96Smrg str[0] = plower; 3745dfecf96Smrg str[1] = pupper; 3755dfecf96Smrg str[2] = lower; 3765dfecf96Smrg str[3] = upper; 3775dfecf96Smrg str[4] = '\0'; 3785dfecf96Smrg return; 3795dfecf96Smrg 3805dfecf96Smrg case Rep_CaseString: 3815dfecf96Smrg /* Augments case literal string */ 3825dfecf96Smrg length = strlen((char*)inf->ppat->data.str); 3835dfecf96Smrg if (((length) % 32) >= 28) { 3845dfecf96Smrg if ((str = realloc(inf->ppat->data.str, 3855dfecf96Smrg length + 36)) == NULL) { 3865dfecf96Smrg inf->ecode = RE_ESPACE; 3875dfecf96Smrg return; 3885dfecf96Smrg } 3895dfecf96Smrg inf->ppat->data.str = str; 3905dfecf96Smrg } 3915dfecf96Smrg inf->ppat->data.str[length] = lower; 3925dfecf96Smrg inf->ppat->data.str[length + 1] = upper; 3935dfecf96Smrg inf->ppat->data.str[length + 2] = '\0'; 3945dfecf96Smrg return; 3955dfecf96Smrg 3965dfecf96Smrg default: 3975dfecf96Smrg /* Anything else is added as a new pattern list element */ 3985dfecf96Smrg break; 3995dfecf96Smrg } 4005dfecf96Smrg } 4015dfecf96Smrg 4025dfecf96Smrg if ((pat = calloc(1, sizeof(rec_pat))) == NULL) { 4035dfecf96Smrg inf->ecode = RE_ESPACE; 4045dfecf96Smrg return; 4055dfecf96Smrg } 4065dfecf96Smrg 4075dfecf96Smrg pat->type = Rep_CaseLiteral; 4085dfecf96Smrg pat->data.cse.lower = lower; 4095dfecf96Smrg pat->data.cse.upper = upper; 4105dfecf96Smrg pat->prev = inf->ppat; 4115dfecf96Smrg if ((pat->prev = inf->ppat) != NULL) 4125dfecf96Smrg inf->ppat->next = pat; 4135dfecf96Smrg else 4145dfecf96Smrg inf->palt->pat = pat; 4155dfecf96Smrg inf->ppat = pat; 4165dfecf96Smrg} 4175dfecf96Smrg 4185dfecf96Smrgstatic void 4195dfecf96Smrgirec_open_group(irec_info *inf) 4205dfecf96Smrg{ 4215dfecf96Smrg rec_pat *pat; 4225dfecf96Smrg rec_alt *alt; 4235dfecf96Smrg rec_grp *grp; 4245dfecf96Smrg 4255dfecf96Smrg if ((grp = calloc(1, sizeof(rec_grp))) == NULL) { 4265dfecf96Smrg inf->ecode = RE_ESPACE; 4275dfecf96Smrg return; 4285dfecf96Smrg } 4295dfecf96Smrg 4305dfecf96Smrg if ((pat = calloc(1, sizeof(rec_pat))) == NULL) { 4315dfecf96Smrg free(grp); 4325dfecf96Smrg inf->ecode = RE_ESPACE; 4335dfecf96Smrg return; 4345dfecf96Smrg } 4355dfecf96Smrg 4365dfecf96Smrg if ((alt = calloc(1, sizeof(rec_alt))) == NULL) { 4375dfecf96Smrg free(grp); 4385dfecf96Smrg free(pat); 4395dfecf96Smrg inf->ecode = RE_ESPACE; 4405dfecf96Smrg return; 4415dfecf96Smrg } 4425dfecf96Smrg 4435dfecf96Smrg pat->type = Rep_Group; 4445dfecf96Smrg pat->data.grp = grp; 4455dfecf96Smrg grp->parent = pat; 4465dfecf96Smrg grp->palt = inf->palt; 4475dfecf96Smrg grp->pgrp = inf->pgrp; 4485dfecf96Smrg grp->alt = alt; 4495dfecf96Smrg grp->comp = 0; 4505dfecf96Smrg if ((pat->prev = inf->ppat) != NULL) 4515dfecf96Smrg inf->ppat->next = pat; 4525dfecf96Smrg else 4535dfecf96Smrg inf->palt->pat = pat; 4545dfecf96Smrg inf->palt = alt; 4555dfecf96Smrg inf->ppat = NULL; 4565dfecf96Smrg 4575dfecf96Smrg /* Only toplevel parenthesis supported */ 4585dfecf96Smrg if (++inf->nparens == 1) 4595dfecf96Smrg ++inf->ngrps; 4605dfecf96Smrg 4615dfecf96Smrg inf->pgrp = grp; 4625dfecf96Smrg} 4635dfecf96Smrg 4645dfecf96Smrgstatic void 4655dfecf96Smrgirec_close_group(irec_info *inf) 4665dfecf96Smrg{ 4675dfecf96Smrg if (inf->pgrp == NULL) { 4685dfecf96Smrg inf->ecode = RE_EPAREN; 4695dfecf96Smrg return; 4705dfecf96Smrg } 4715dfecf96Smrg 4725dfecf96Smrg inf->palt = inf->pgrp->palt; 4735dfecf96Smrg inf->ppat = inf->pgrp->parent; 4745dfecf96Smrg inf->pgrp = inf->pgrp->pgrp; 4755dfecf96Smrg 4765dfecf96Smrg --inf->nparens; 4775dfecf96Smrg} 4785dfecf96Smrg 4795dfecf96Smrgstatic void 4805dfecf96Smrgirec_range(irec_info *inf) 4815dfecf96Smrg{ 4825dfecf96Smrg int count; 4835dfecf96Smrg rec_pat *pat; 4845dfecf96Smrg rec_rng *rng; 4855dfecf96Smrg int not = inf->ptr[0] == '^'; 4865dfecf96Smrg 4875dfecf96Smrg if (not) 4885dfecf96Smrg ++inf->ptr; 4895dfecf96Smrg 4905dfecf96Smrg pat = calloc(1, sizeof(rec_pat)); 4915dfecf96Smrg if (pat == NULL) { 4925dfecf96Smrg inf->ecode = RE_ESPACE; 4935dfecf96Smrg return; 4945dfecf96Smrg } 4955dfecf96Smrg 4965dfecf96Smrg rng = calloc(1, sizeof(rec_rng)); 4975dfecf96Smrg if (pat == NULL) { 4985dfecf96Smrg free(pat); 4995dfecf96Smrg inf->ecode = RE_ESPACE; 5005dfecf96Smrg return; 5015dfecf96Smrg } 5025dfecf96Smrg 5035dfecf96Smrg pat->data.rng = rng; 5045dfecf96Smrg pat->type = not ? Rep_RangeNot : Rep_Range; 5055dfecf96Smrg if ((pat->prev = inf->ppat) != NULL) 5065dfecf96Smrg inf->ppat->next = pat; 5075dfecf96Smrg else 5085dfecf96Smrg inf->palt->pat = pat; 5095dfecf96Smrg inf->ppat = pat; 5105dfecf96Smrg 5115dfecf96Smrg /* First pass, add everything seen */ 5125dfecf96Smrg for (count = 0; inf->ecode == 0; count++) { 5135dfecf96Smrg /* If bracket not closed */ 5145dfecf96Smrg if (inf->ptr == inf->end) { 5155dfecf96Smrg inf->ecode = RE_EBRACK; 5165dfecf96Smrg return; 5175dfecf96Smrg } 5185dfecf96Smrg /* If not the first character */ 5195dfecf96Smrg else if (inf->ptr[0] == ']' && count) 5205dfecf96Smrg break; 5215dfecf96Smrg else { 5225dfecf96Smrg /* If not a range of characters */ 5235dfecf96Smrg if (inf->ptr[1] != '-' || inf->ptr[2] == ']') { 5245dfecf96Smrg irec_range_single(inf, inf->ptr[0]); 5255dfecf96Smrg ++inf->ptr; 5265dfecf96Smrg } 5275dfecf96Smrg else { 5285dfecf96Smrg if ((inf->flags & RE_NEWLINE) && 5295dfecf96Smrg inf->ptr[0] < '\n' && inf->ptr[2] > '\n') { 5305dfecf96Smrg /* Unless it is forced to be a delimiter, don't allow 5315dfecf96Smrg * a newline in a character range */ 5325dfecf96Smrg if (inf->ptr[0] == '\n' - 1) 5335dfecf96Smrg irec_range_single(inf, inf->ptr[0]); 5345dfecf96Smrg else 5355dfecf96Smrg irec_range_complex(inf, inf->ptr[0], '\n' - 1); 5365dfecf96Smrg if (inf->ptr[2] == '\n' + 1) 5375dfecf96Smrg irec_range_single(inf, inf->ptr[2]); 5385dfecf96Smrg else 5395dfecf96Smrg irec_range_complex(inf, '\n' + 1, inf->ptr[2]); 5405dfecf96Smrg } 5415dfecf96Smrg else 5425dfecf96Smrg irec_range_complex(inf, inf->ptr[0], inf->ptr[2]); 5435dfecf96Smrg inf->ptr += 3; 5445dfecf96Smrg } 5455dfecf96Smrg } 5465dfecf96Smrg } 5475dfecf96Smrg 5485dfecf96Smrg /* Skip ] */ 5495dfecf96Smrg ++inf->ptr; 5505dfecf96Smrg} 5515dfecf96Smrg 5525dfecf96Smrgstatic void 5535dfecf96Smrgirec_range_single(irec_info *inf, int value) 5545dfecf96Smrg{ 5555dfecf96Smrg if (value >= 0 && value <= 255) 5565dfecf96Smrg inf->ppat->data.rng->range[value] = 1; 5575dfecf96Smrg 5585dfecf96Smrg if (inf->flags & RE_ICASE) { 5595dfecf96Smrg if (islower(value)) { 5605dfecf96Smrg value = toupper(value); 5615dfecf96Smrg if (value >= 0 && value <= 255) 5625dfecf96Smrg inf->ppat->data.rng->range[value] = 1; 5635dfecf96Smrg } 5645dfecf96Smrg else if (isupper(value)) { 5655dfecf96Smrg value = tolower(value); 5665dfecf96Smrg if (value >= 0 && value <= 255) 5675dfecf96Smrg inf->ppat->data.rng->range[value] = 1; 5685dfecf96Smrg } 5695dfecf96Smrg } 5705dfecf96Smrg} 5715dfecf96Smrg 5725dfecf96Smrgstatic void 5735dfecf96Smrgirec_range_complex(irec_info *inf, int chrf, int chrt) 5745dfecf96Smrg{ 5755dfecf96Smrg if (chrf > chrt) { 5765dfecf96Smrg inf->ecode = RE_ERANGE; 5775dfecf96Smrg return; 5785dfecf96Smrg } 5795dfecf96Smrg 5805dfecf96Smrg for (; chrf <= chrt; chrf++) 5815dfecf96Smrg irec_range_single(inf, chrf); 5825dfecf96Smrg} 5835dfecf96Smrg 5845dfecf96Smrgstatic void 5855dfecf96Smrgirec_escape(irec_info *inf) 5865dfecf96Smrg{ 5875dfecf96Smrg rec_pat *pat; 5885dfecf96Smrg unsigned char chr = inf->ptr[0]; 5895dfecf96Smrg 5905dfecf96Smrg if (chr == 0) { 5915dfecf96Smrg inf->ecode = RE_EESCAPE; 5925dfecf96Smrg return; 5935dfecf96Smrg } 5945dfecf96Smrg ++inf->ptr; 5955dfecf96Smrg switch (chr) { 5965dfecf96Smrg case 'o': 5975dfecf96Smrg irec_simple_pattern(inf, Rep_Odigit); 5985dfecf96Smrg break; 5995dfecf96Smrg case 'O': 6005dfecf96Smrg irec_simple_pattern(inf, Rep_OdigitNot); 6015dfecf96Smrg break; 6025dfecf96Smrg case 'd': 6035dfecf96Smrg irec_simple_pattern(inf, Rep_Digit); 6045dfecf96Smrg break; 6055dfecf96Smrg case 'D': 6065dfecf96Smrg irec_simple_pattern(inf, Rep_DigitNot); 6075dfecf96Smrg break; 6085dfecf96Smrg case 'x': 6095dfecf96Smrg irec_simple_pattern(inf, Rep_Xdigit); 6105dfecf96Smrg break; 6115dfecf96Smrg case 'X': 6125dfecf96Smrg irec_simple_pattern(inf, Rep_XdigitNot); 6135dfecf96Smrg break; 6145dfecf96Smrg case 's': 6155dfecf96Smrg irec_simple_pattern(inf, Rep_Space); 6165dfecf96Smrg break; 6175dfecf96Smrg case 'S': 6185dfecf96Smrg irec_simple_pattern(inf, Rep_SpaceNot); 6195dfecf96Smrg break; 6205dfecf96Smrg case 't': 6215dfecf96Smrg irec_simple_pattern(inf, Rep_Tab); 6225dfecf96Smrg break; 6235dfecf96Smrg case 'n': 6245dfecf96Smrg irec_simple_pattern(inf, Rep_Newline); 6255dfecf96Smrg break; 6265dfecf96Smrg case 'l': 6275dfecf96Smrg irec_simple_pattern(inf, Rep_Lower); 6285dfecf96Smrg break; 6295dfecf96Smrg case 'u': 6305dfecf96Smrg irec_simple_pattern(inf, Rep_Upper); 6315dfecf96Smrg break; 6325dfecf96Smrg case 'w': 6335dfecf96Smrg irec_simple_pattern(inf, Rep_Alnum); 6345dfecf96Smrg break; 6355dfecf96Smrg case 'W': 6365dfecf96Smrg irec_simple_pattern(inf, Rep_AlnumNot); 6375dfecf96Smrg break; 6385dfecf96Smrg case 'c': 6395dfecf96Smrg irec_simple_pattern(inf, Rep_Control); 6405dfecf96Smrg break; 6415dfecf96Smrg case 'C': 6425dfecf96Smrg irec_simple_pattern(inf, Rep_ControlNot); 6435dfecf96Smrg break; 6445dfecf96Smrg case '<': 6455dfecf96Smrg irec_simple_pattern(inf, Rep_Bow); 6465dfecf96Smrg break; 6475dfecf96Smrg case '>': 6485dfecf96Smrg irec_simple_pattern(inf, Rep_Eow); 6495dfecf96Smrg break; 6505dfecf96Smrg case '1': case '2': case '3': 6515dfecf96Smrg case '4': case '5': case '6': 6525dfecf96Smrg case '7': case '8': case '9': 6535dfecf96Smrg if ((inf->flags & RE_NOSUB) || (chr -= '1') >= inf->ngrps) { 6545dfecf96Smrg inf->ecode = RE_ESUBREG; 6555dfecf96Smrg return; 6565dfecf96Smrg } 6575dfecf96Smrg if ((pat = calloc(1, sizeof(rec_pat))) == NULL) { 6585dfecf96Smrg inf->ecode = RE_ESPACE; 6595dfecf96Smrg return; 6605dfecf96Smrg } 6615dfecf96Smrg pat->type = Rep_Backref; 6625dfecf96Smrg pat->data.chr = chr; 6635dfecf96Smrg pat->prev = inf->ppat; 6645dfecf96Smrg if (inf->ppat) 6655dfecf96Smrg inf->ppat->next = pat; 6665dfecf96Smrg else 6675dfecf96Smrg inf->palt->pat = pat; 6685dfecf96Smrg inf->ppat = pat; 6695dfecf96Smrg break; 6705dfecf96Smrg 6715dfecf96Smrg /* True literals */ 6725dfecf96Smrg case '0': 6735dfecf96Smrg irec_literal_pattern(inf, '\0'); 6745dfecf96Smrg break; 6755dfecf96Smrg case 'a': 6765dfecf96Smrg irec_literal_pattern(inf, '\a'); 6775dfecf96Smrg break; 6785dfecf96Smrg case 'b': 6795dfecf96Smrg irec_literal_pattern(inf, '\b'); 6805dfecf96Smrg break; 6815dfecf96Smrg case 'f': 6825dfecf96Smrg irec_literal_pattern(inf, '\f'); 6835dfecf96Smrg break; 6845dfecf96Smrg case 'r': 6855dfecf96Smrg irec_literal_pattern(inf, '\r'); 6865dfecf96Smrg break; 6875dfecf96Smrg case 'v': 6885dfecf96Smrg irec_literal_pattern(inf, '\v'); 6895dfecf96Smrg break; 6905dfecf96Smrg 6915dfecf96Smrg default: 6925dfecf96Smrg /* Don't check if case insensitive regular expression */ 6935dfecf96Smrg irec_literal_pattern(inf, chr); 6945dfecf96Smrg break; 6955dfecf96Smrg } 6965dfecf96Smrg} 6975dfecf96Smrg 6985dfecf96Smrgstatic void 6995dfecf96Smrgirec_simple_repetition(irec_info *inf, rec_rep_t type) 7005dfecf96Smrg{ 7015dfecf96Smrg rec_rep *rep; 7025dfecf96Smrg 7035dfecf96Smrg /* If nowhere to add repetition */ 7045dfecf96Smrg if ((inf->pgrp == NULL && inf->ppat == NULL) || 7055dfecf96Smrg /* If repetition already added to last/current pattern */ 7065dfecf96Smrg (inf->pgrp == NULL && inf->ppat->rep != NULL) || 7075dfecf96Smrg /* If repetition already added to last/current group */ 7085dfecf96Smrg (inf->ppat == NULL && inf->pgrp->parent->rep != NULL)) { 7095dfecf96Smrg inf->ecode = RE_BADRPT; 7105dfecf96Smrg return; 7115dfecf96Smrg } 7125dfecf96Smrg 7135dfecf96Smrg if ((rep = calloc(1, sizeof(rec_rep))) == NULL) { 7145dfecf96Smrg inf->ecode = RE_ESPACE; 7155dfecf96Smrg return; 7165dfecf96Smrg } 7175dfecf96Smrg 7185dfecf96Smrg rep->type = type; 7195dfecf96Smrg irec_add_repetition(inf, rep); 7205dfecf96Smrg} 7215dfecf96Smrg 7225dfecf96Smrgstatic void 7235dfecf96Smrgirec_complex_repetition(irec_info *inf) 7245dfecf96Smrg{ 7255dfecf96Smrg int exact; 7265dfecf96Smrg rec_rep *rep; 7275dfecf96Smrg long mine, maxc; 7285dfecf96Smrg unsigned char *end; 7295dfecf96Smrg 7305dfecf96Smrg /* If nowhere to add repetition */ 7315dfecf96Smrg if ((inf->pgrp == NULL && inf->ppat == NULL) || 7325dfecf96Smrg /* If repetition already added to last/current pattern */ 7335dfecf96Smrg (inf->pgrp == NULL && inf->ppat->rep != NULL) || 7345dfecf96Smrg /* If repetition already added to last/current group */ 7355dfecf96Smrg (inf->ppat == NULL && inf->pgrp->parent->rep != NULL)) { 7365dfecf96Smrg inf->ecode = RE_EBADBR; 7375dfecf96Smrg return; 7385dfecf96Smrg } 7395dfecf96Smrg 7405dfecf96Smrg exact = 0; 7415dfecf96Smrg mine = maxc = -1; 7425dfecf96Smrg if (inf->ptr[0] == ',') 7435dfecf96Smrg /* Specify max number of ocurrences only */ 7445dfecf96Smrg goto domax; 7455dfecf96Smrg else if (!isdigit(inf->ptr[0])) 7465dfecf96Smrg goto badbr; 7475dfecf96Smrg 7485dfecf96Smrg mine = strtol((char*)inf->ptr, (char**)&end, 10); 7495dfecf96Smrg inf->ptr = end; 7505dfecf96Smrg if (inf->ptr[0] == '}') { 7515dfecf96Smrg exact = 1; 7525dfecf96Smrg ++inf->ptr; 7535dfecf96Smrg goto redone; 7545dfecf96Smrg } 7555dfecf96Smrg else if (inf->ptr[0] != ',') 7565dfecf96Smrg goto badbr; 7575dfecf96Smrg 7585dfecf96Smrgdomax: 7595dfecf96Smrg /* Add one to skip comma */ 7605dfecf96Smrg ++inf->ptr; 7615dfecf96Smrg if (inf->ptr[0] == '}') { 7625dfecf96Smrg ++inf->ptr; 7635dfecf96Smrg goto redone; 7645dfecf96Smrg } 7655dfecf96Smrg else if (!isdigit(inf->ptr[0])) 7665dfecf96Smrg goto badbr; 7675dfecf96Smrg maxc = strtol((char*)inf->ptr, (char**)&end, 10); 7685dfecf96Smrg inf->ptr = end; 7695dfecf96Smrg if (inf->ptr[0] != '}') 7705dfecf96Smrg goto badbr; 7715dfecf96Smrg ++inf->ptr; 7725dfecf96Smrg 7735dfecf96Smrgredone: 7745dfecf96Smrg if (mine == maxc) { 7755dfecf96Smrg maxc = -1; 7765dfecf96Smrg exact = 1; 7775dfecf96Smrg } 7785dfecf96Smrg 7795dfecf96Smrg /* Check range and if min-max parameters are valid */ 7805dfecf96Smrg if (mine >= 255 || maxc >= 255 || 7815dfecf96Smrg (mine >= 0 && maxc >= 0 && mine > maxc)) 7825dfecf96Smrg goto badbr; 7835dfecf96Smrg 7845dfecf96Smrg /* Check for noop */ 7855dfecf96Smrg if (exact && mine == 1) 7865dfecf96Smrg return; 7875dfecf96Smrg 7885dfecf96Smrg if ((rep = calloc(1, sizeof(rec_rep))) == NULL) { 7895dfecf96Smrg inf->ecode = RE_ESPACE; 7905dfecf96Smrg return; 7915dfecf96Smrg } 7925dfecf96Smrg 7935dfecf96Smrg /* Convert {0,1} to ? */ 7945dfecf96Smrg if (mine == 0 && maxc == 1) 7955dfecf96Smrg rep->type = Rer_Maybe; 7965dfecf96Smrg else if (exact) { 7975dfecf96Smrg rep->type = Rer_Exact; 7985dfecf96Smrg rep->mine = mine; 7995dfecf96Smrg } 8005dfecf96Smrg /* Convert {0,} to * */ 8015dfecf96Smrg else if (mine == 0 && maxc == -1) 8025dfecf96Smrg rep->type = Rer_AnyTimes; 8035dfecf96Smrg /* Convert {1,} to + */ 8045dfecf96Smrg else if (mine == 1 && maxc == -1) 8055dfecf96Smrg rep->type = Rer_AtLeast; 8065dfecf96Smrg else if (maxc == -1) { 8075dfecf96Smrg rep->type = Rer_Min; 8085dfecf96Smrg rep->mine = mine; 8095dfecf96Smrg } 8105dfecf96Smrg else if (mine < 1) { 8115dfecf96Smrg rep->type = Rer_Max; 8125dfecf96Smrg rep->maxc = maxc; 8135dfecf96Smrg } 8145dfecf96Smrg else { 8155dfecf96Smrg rep->type = Rer_MinMax; 8165dfecf96Smrg rep->mine = mine; 8175dfecf96Smrg rep->maxc = maxc; 8185dfecf96Smrg } 8195dfecf96Smrg 8205dfecf96Smrg irec_add_repetition(inf, rep); 8215dfecf96Smrg 8225dfecf96Smrg return; 8235dfecf96Smrg 8245dfecf96Smrgbadbr: 8255dfecf96Smrg inf->ecode = RE_EBADBR; 8265dfecf96Smrg} 8275dfecf96Smrg 8285dfecf96Smrg/* The rep argument is allocated and has no reference yet, 8295dfecf96Smrg * if something fails it must be freed before returning. 8305dfecf96Smrg */ 8315dfecf96Smrgstatic void 8325dfecf96Smrgirec_add_repetition(irec_info *inf, rec_rep *rep) 8335dfecf96Smrg{ 8345dfecf96Smrg int length; 8355dfecf96Smrg rec_pat *pat; 8365dfecf96Smrg rec_grp *grp; 8375dfecf96Smrg rec_rep_t rept; 8385dfecf96Smrg unsigned char value, upper; 8395dfecf96Smrg 8405dfecf96Smrg rept = rep->type; 8415dfecf96Smrg 8425dfecf96Smrg if (inf->ppat == NULL) { 8435dfecf96Smrg rec_pat *any; 8445dfecf96Smrg rec_grp *grp = inf->pgrp; 8455dfecf96Smrg 8465dfecf96Smrg if (rept == Rer_AnyTimes || rept == Rer_Maybe || rept == Re_AtLeast) { 8475dfecf96Smrg /* Convert (.)* to (.*), ((.))* not handled and may not match */ 8485dfecf96Smrg any = NULL; 8495dfecf96Smrg 8505dfecf96Smrg if (grp->alt && grp->alt->pat) { 8515dfecf96Smrg for (any = grp->alt->pat; any->next; any = any->next) 8525dfecf96Smrg ; 8535dfecf96Smrg switch (any->type) { 8545dfecf96Smrg case Rep_Any: 8555dfecf96Smrg break; 8565dfecf96Smrg case Rep_AnyAnyTimes: 8575dfecf96Smrg case Rep_AnyMaybe: 8585dfecf96Smrg case Rep_AnyAtLeast: 8595dfecf96Smrg free(rep); 8605dfecf96Smrg inf->ecode = RE_BADRPT; 8615dfecf96Smrg return; 8625dfecf96Smrg default: 8635dfecf96Smrg any = NULL; 8645dfecf96Smrg break; 8655dfecf96Smrg } 8665dfecf96Smrg } 8675dfecf96Smrg if (any) { 8685dfecf96Smrg free(rep); 8695dfecf96Smrg rep = NULL; 8705dfecf96Smrg any->type = (rept == Rer_AnyTimes) ? Rep_AnyAnyTimes : 8715dfecf96Smrg (rept == Rer_AtLeast) ? Rep_AnyAtLeast : 8725dfecf96Smrg Rep_AnyMaybe; 8735dfecf96Smrg while (grp) { 8745dfecf96Smrg ++grp->comp; 8755dfecf96Smrg grp = grp->pgrp; 8765dfecf96Smrg } 8775dfecf96Smrg } 8785dfecf96Smrg } 8795dfecf96Smrg inf->pgrp->parent->rep = rep; 8805dfecf96Smrg irec_close_group(inf); 8815dfecf96Smrg return; 8825dfecf96Smrg } 8835dfecf96Smrg 8845dfecf96Smrg switch (inf->ppat->type) { 8855dfecf96Smrg case Rep_Bol: 8865dfecf96Smrg case Rep_Eol: 8875dfecf96Smrg case Rep_Bow: 8885dfecf96Smrg case Rep_Eow: 8895dfecf96Smrg case Rep_AnyAnyTimes: 8905dfecf96Smrg case Rep_AnyMaybe: 8915dfecf96Smrg case Rep_AnyAtLeast: 8925dfecf96Smrg /* Markers that cannot repeat */ 8935dfecf96Smrg free(rep); 8945dfecf96Smrg inf->ecode = RE_BADRPT; 8955dfecf96Smrg return; 8965dfecf96Smrg 8975dfecf96Smrg case Rep_Any: 8985dfecf96Smrg grp = inf->pgrp; 8995dfecf96Smrg free(rep); 9005dfecf96Smrg if (rept == Rer_AnyTimes || 9015dfecf96Smrg rept == Rer_Maybe || 9025dfecf96Smrg rept == Rer_AtLeast) { 9035dfecf96Smrg inf->ppat->type = (rept == Rer_AnyTimes) ? 9045dfecf96Smrg Rep_AnyAnyTimes : 9055dfecf96Smrg (rept == Rer_Maybe) ? 9065dfecf96Smrg Rep_AnyMaybe : 9075dfecf96Smrg Rep_AnyAtLeast; 9085dfecf96Smrg while (grp) { 9095dfecf96Smrg ++grp->comp; 9105dfecf96Smrg grp = grp->pgrp; 9115dfecf96Smrg } 9125dfecf96Smrg } 9135dfecf96Smrg else 9145dfecf96Smrg /* XXX Not (yet) implemented */ 9155dfecf96Smrg inf->ecode = RE_BADRPT; 9165dfecf96Smrg rep = NULL; 9175dfecf96Smrg break; 9185dfecf96Smrg 9195dfecf96Smrg case Rep_String: 9205dfecf96Smrg if ((pat = calloc(1, sizeof(rec_pat))) == NULL) { 9215dfecf96Smrg free(rep); 9225dfecf96Smrg inf->ecode = RE_ESPACE; 9235dfecf96Smrg return; 9245dfecf96Smrg } 9255dfecf96Smrg 9265dfecf96Smrg length = strlen((char*)inf->ppat->data.str); 9275dfecf96Smrg pat->type = Rep_Literal; 9285dfecf96Smrg pat->prev = inf->ppat; 9295dfecf96Smrg pat->data.chr = inf->ppat->data.str[length - 1]; 9305dfecf96Smrg if (length == 2) { 9315dfecf96Smrg /* Must convert to two Rep_Literals */ 9325dfecf96Smrg value = inf->ppat->data.str[0]; 9335dfecf96Smrg free(inf->ppat->data.str); 9345dfecf96Smrg inf->ppat->data.chr = value; 9355dfecf96Smrg inf->ppat->type = Rep_Literal; 9365dfecf96Smrg } 9375dfecf96Smrg else 9385dfecf96Smrg /* Must remove last character from string */ 9395dfecf96Smrg inf->ppat->data.str[length - 1] = '\0'; 9405dfecf96Smrg inf->ppat->next = pat; 9415dfecf96Smrg inf->ppat = pat; 9425dfecf96Smrg break; 9435dfecf96Smrg 9445dfecf96Smrg case Rep_CaseString: 9455dfecf96Smrg if ((pat = calloc(1, sizeof(rec_pat))) == NULL) { 9465dfecf96Smrg free(rep); 9475dfecf96Smrg inf->ecode = RE_ESPACE; 9485dfecf96Smrg return; 9495dfecf96Smrg } 9505dfecf96Smrg 9515dfecf96Smrg length = strlen((char*)inf->ppat->data.str); 9525dfecf96Smrg pat->type = Rep_CaseLiteral; 9535dfecf96Smrg pat->prev = inf->ppat; 9545dfecf96Smrg pat->data.cse.lower = inf->ppat->data.str[length - 2]; 9555dfecf96Smrg pat->data.cse.upper = inf->ppat->data.str[length - 1]; 9565dfecf96Smrg if (length == 4) { 9575dfecf96Smrg /* Must convert to two Rep_CaseLiterals */ 9585dfecf96Smrg value = inf->ppat->data.str[0]; 9595dfecf96Smrg upper = inf->ppat->data.str[1]; 9605dfecf96Smrg free(inf->ppat->data.str); 9615dfecf96Smrg inf->ppat->data.cse.lower = value; 9625dfecf96Smrg inf->ppat->data.cse.upper = upper; 9635dfecf96Smrg inf->ppat->next = pat; 9645dfecf96Smrg inf->ppat->type = Rep_CaseLiteral; 9655dfecf96Smrg } 9665dfecf96Smrg else 9675dfecf96Smrg /* Must remove last character pair from string */ 9685dfecf96Smrg inf->ppat->data.str[length - 2] = '\0'; 9695dfecf96Smrg inf->ppat->next = pat; 9705dfecf96Smrg inf->ppat = pat; 9715dfecf96Smrg break; 9725dfecf96Smrg 9735dfecf96Smrg default: 9745dfecf96Smrg /* Anything else does not need special handling */ 9755dfecf96Smrg break; 9765dfecf96Smrg } 9775dfecf96Smrg 9785dfecf96Smrg inf->ppat->rep = rep; 9795dfecf96Smrg} 9805dfecf96Smrg 9815dfecf96Smrgstatic void 9825dfecf96Smrgirec_free(irec_info *inf) 9835dfecf96Smrg{ 9845dfecf96Smrg irec_free_alt(inf->alt); 9855dfecf96Smrg} 9865dfecf96Smrg 9875dfecf96Smrgstatic void 9885dfecf96Smrgirec_free_grp(rec_grp *grp) 9895dfecf96Smrg{ 9905dfecf96Smrg if (grp->alt) 9915dfecf96Smrg irec_free_alt(grp->alt); 9925dfecf96Smrg free(grp); 9935dfecf96Smrg} 9945dfecf96Smrg 9955dfecf96Smrgstatic void 9965dfecf96Smrgirec_free_pats(rec_pat *pat) 9975dfecf96Smrg{ 9985dfecf96Smrg rec_pat *next; 9995dfecf96Smrg rec_pat_t rect; 10005dfecf96Smrg 10015dfecf96Smrg while (pat) { 10025dfecf96Smrg next = pat->next; 10035dfecf96Smrg if (pat->rep) 10045dfecf96Smrg free(pat->rep); 10055dfecf96Smrg rect = pat->type; 10065dfecf96Smrg if (rect == Rep_Range || rect == Rep_RangeNot) 10075dfecf96Smrg free(pat->data.rng); 10085dfecf96Smrg else if (rect == Rep_Group) 10095dfecf96Smrg irec_free_grp(pat->data.grp); 10105dfecf96Smrg else if (rect == Rep_StringList) 10115dfecf96Smrg orec_free_stl(pat->data.stl); 10125dfecf96Smrg free(pat); 10135dfecf96Smrg pat = next; 10145dfecf96Smrg } 10155dfecf96Smrg} 1016