[BACK]Return to pattern.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / less

Annotation of src/usr.bin/less/pattern.c, Revision 1.1.1.1

1.1       shadchin    1: /*
                      2:  * Copyright (C) 1984-2011  Mark Nudelman
                      3:  *
                      4:  * You may distribute under the terms of either the GNU General Public
                      5:  * License or the Less License, as specified in the README file.
                      6:  *
                      7:  * For more information about less, or for information on how to
                      8:  * contact the author, see the README file.
                      9:  */
                     10:
                     11: /*
                     12:  * Routines to do pattern matching.
                     13:  */
                     14:
                     15: #include "less.h"
                     16: #include "pattern.h"
                     17:
                     18: extern int caseless;
                     19:
                     20: /*
                     21:  * Compile a search pattern, for future use by match_pattern.
                     22:  */
                     23:        static int
                     24: compile_pattern2(pattern, search_type, comp_pattern)
                     25:        char *pattern;
                     26:        int search_type;
                     27:        void **comp_pattern;
                     28: {
                     29:        if ((search_type & SRCH_NO_REGEX) == 0)
                     30:        {
                     31: #if HAVE_POSIX_REGCOMP
                     32:                regex_t *comp = (regex_t *) ecalloc(1, sizeof(regex_t));
                     33:                regex_t **pcomp = (regex_t **) comp_pattern;
                     34:                if (regcomp(comp, pattern, REGCOMP_FLAG))
                     35:                {
                     36:                        free(comp);
                     37:                        error("Invalid pattern", NULL_PARG);
                     38:                        return (-1);
                     39:                }
                     40:                if (*pcomp != NULL)
                     41:                        regfree(*pcomp);
                     42:                *pcomp = comp;
                     43: #endif
                     44: #if HAVE_PCRE
                     45:                pcre *comp;
                     46:                pcre **pcomp = (pcre **) comp_pattern;
                     47:                const char *errstring;
                     48:                int erroffset;
                     49:                PARG parg;
                     50:                comp = pcre_compile(pattern, 0,
                     51:                                &errstring, &erroffset, NULL);
                     52:                if (comp == NULL)
                     53:                {
                     54:                        parg.p_string = (char *) errstring;
                     55:                        error("%s", &parg);
                     56:                        return (-1);
                     57:                }
                     58:                *pcomp = comp;
                     59: #endif
                     60: #if HAVE_RE_COMP
                     61:                PARG parg;
                     62:                int *pcomp = (int *) comp_pattern;
                     63:                if ((parg.p_string = re_comp(pattern)) != NULL)
                     64:                {
                     65:                        error("%s", &parg);
                     66:                        return (-1);
                     67:                }
                     68:                *pcomp = 1;
                     69: #endif
                     70: #if HAVE_REGCMP
                     71:                char *comp;
                     72:                char **pcomp = (char **) comp_pattern;
                     73:                if ((comp = regcmp(pattern, 0)) == NULL)
                     74:                {
                     75:                        error("Invalid pattern", NULL_PARG);
                     76:                        return (-1);
                     77:                }
                     78:                if (pcomp != NULL)
                     79:                        free(*pcomp);
                     80:                *pcomp = comp;
                     81: #endif
                     82: #if HAVE_V8_REGCOMP
                     83:                struct regexp *comp;
                     84:                struct regexp **pcomp = (struct regexp **) comp_pattern;
                     85:                if ((comp = regcomp(pattern)) == NULL)
                     86:                {
                     87:                        /*
                     88:                         * regcomp has already printed an error message
                     89:                         * via regerror().
                     90:                         */
                     91:                        return (-1);
                     92:                }
                     93:                if (*pcomp != NULL)
                     94:                        free(*pcomp);
                     95:                *pcomp = comp;
                     96: #endif
                     97:        }
                     98:        return (0);
                     99: }
                    100:
                    101: /*
                    102:  * Like compile_pattern2, but convert the pattern to lowercase if necessary.
                    103:  */
                    104:        public int
                    105: compile_pattern(pattern, search_type, comp_pattern)
                    106:        char *pattern;
                    107:        int search_type;
                    108:        void **comp_pattern;
                    109: {
                    110:        char *cvt_pattern;
                    111:        int result;
                    112:
                    113:        if (caseless != OPT_ONPLUS)
                    114:                cvt_pattern = pattern;
                    115:        else
                    116:        {
                    117:                cvt_pattern = (char*) ecalloc(1, cvt_length(strlen(pattern), CVT_TO_LC));
                    118:                cvt_text(cvt_pattern, pattern, (int *)NULL, (int *)NULL, CVT_TO_LC);
                    119:        }
                    120:        result = compile_pattern2(cvt_pattern, search_type, comp_pattern);
                    121:        if (cvt_pattern != pattern)
                    122:                free(cvt_pattern);
                    123:        return (result);
                    124: }
                    125:
                    126: /*
                    127:  * Forget that we have a compiled pattern.
                    128:  */
                    129:        public void
                    130: uncompile_pattern(pattern)
                    131:        void **pattern;
                    132: {
                    133: #if HAVE_POSIX_REGCOMP
                    134:        regex_t **pcomp = (regex_t **) pattern;
                    135:        if (*pcomp != NULL)
                    136:                regfree(*pcomp);
                    137:        *pcomp = NULL;
                    138: #endif
                    139: #if HAVE_PCRE
                    140:        pcre **pcomp = (pcre **) pattern;
                    141:        if (*pcomp != NULL)
                    142:                pcre_free(*pcomp);
                    143:        *pcomp = NULL;
                    144: #endif
                    145: #if HAVE_RE_COMP
                    146:        int *pcomp = (int *) pattern;
                    147:        *pcomp = 0;
                    148: #endif
                    149: #if HAVE_REGCMP
                    150:        char **pcomp = (char **) pattern;
                    151:        if (*pcomp != NULL)
                    152:                free(*pcomp);
                    153:        *pcomp = NULL;
                    154: #endif
                    155: #if HAVE_V8_REGCOMP
                    156:        struct regexp **pcomp = (struct regexp **) pattern;
                    157:        if (*pcomp != NULL)
                    158:                free(*pcomp);
                    159:        *pcomp = NULL;
                    160: #endif
                    161: }
                    162:
                    163: /*
                    164:  * Is a compiled pattern null?
                    165:  */
                    166:        public int
                    167: is_null_pattern(pattern)
                    168:        void *pattern;
                    169: {
                    170: #if HAVE_POSIX_REGCOMP
                    171:        return (pattern == NULL);
                    172: #endif
                    173: #if HAVE_PCRE
                    174:        return (pattern == NULL);
                    175: #endif
                    176: #if HAVE_RE_COMP
                    177:        return (pattern == 0);
                    178: #endif
                    179: #if HAVE_REGCMP
                    180:        return (pattern == NULL);
                    181: #endif
                    182: #if HAVE_V8_REGCOMP
                    183:        return (pattern == NULL);
                    184: #endif
                    185: #if NO_REGEX
                    186:        return (search_pattern != NULL);
                    187: #endif
                    188: }
                    189:
                    190: /*
                    191:  * Simple pattern matching function.
                    192:  * It supports no metacharacters like *, etc.
                    193:  */
                    194:        static int
                    195: match(pattern, pattern_len, buf, buf_len, pfound, pend)
                    196:        char *pattern;
                    197:        int pattern_len;
                    198:        char *buf;
                    199:        int buf_len;
                    200:        char **pfound, **pend;
                    201: {
                    202:        register char *pp, *lp;
                    203:        register char *pattern_end = pattern + pattern_len;
                    204:        register char *buf_end = buf + buf_len;
                    205:
                    206:        for ( ;  buf < buf_end;  buf++)
                    207:        {
                    208:                for (pp = pattern, lp = buf;  *pp == *lp;  pp++, lp++)
                    209:                        if (pp == pattern_end || lp == buf_end)
                    210:                                break;
                    211:                if (pp == pattern_end)
                    212:                {
                    213:                        if (pfound != NULL)
                    214:                                *pfound = buf;
                    215:                        if (pend != NULL)
                    216:                                *pend = lp;
                    217:                        return (1);
                    218:                }
                    219:        }
                    220:        return (0);
                    221: }
                    222:
                    223: /*
                    224:  * Perform a pattern match with the previously compiled pattern.
                    225:  * Set sp and ep to the start and end of the matched string.
                    226:  */
                    227:        public int
                    228: match_pattern(pattern, tpattern, line, line_len, sp, ep, notbol, search_type)
                    229:        void *pattern;
                    230:        char *tpattern;
                    231:        char *line;
                    232:        int line_len;
                    233:        char **sp;
                    234:        char **ep;
                    235:        int notbol;
                    236:        int search_type;
                    237: {
                    238:        int matched;
                    239: #if HAVE_POSIX_REGCOMP
                    240:        regex_t *spattern = (regex_t *) pattern;
                    241: #endif
                    242: #if HAVE_PCRE
                    243:        pcre *spattern = (pcre *) pattern;
                    244: #endif
                    245: #if HAVE_RE_COMP
                    246:        int spattern = (int) pattern;
                    247: #endif
                    248: #if HAVE_REGCMP
                    249:        char *spattern = (char *) pattern;
                    250: #endif
                    251: #if HAVE_V8_REGCOMP
                    252:        struct regexp *spattern = (struct regexp *) pattern;
                    253: #endif
                    254:
                    255:        if (search_type & SRCH_NO_REGEX)
                    256:                matched = match(tpattern, strlen(tpattern), line, line_len, sp, ep);
                    257:        else
                    258:        {
                    259: #if HAVE_POSIX_REGCOMP
                    260:        {
                    261:                regmatch_t rm;
                    262:                int flags = (notbol) ? REG_NOTBOL : 0;
                    263:                matched = !regexec(spattern, line, 1, &rm, flags);
                    264:                if (matched)
                    265:                {
                    266: #ifndef __WATCOMC__
                    267:                        *sp = line + rm.rm_so;
                    268:                        *ep = line + rm.rm_eo;
                    269: #else
                    270:                        *sp = rm.rm_sp;
                    271:                        *ep = rm.rm_ep;
                    272: #endif
                    273:                }
                    274:        }
                    275: #endif
                    276: #if HAVE_PCRE
                    277:        {
                    278:                int flags = (notbol) ? PCRE_NOTBOL : 0;
                    279:                int ovector[3];
                    280:                matched = pcre_exec(spattern, NULL, line, line_len,
                    281:                        0, flags, ovector, 3) >= 0;
                    282:                if (matched)
                    283:                {
                    284:                        *sp = line + ovector[0];
                    285:                        *ep = line + ovector[1];
                    286:                }
                    287:        }
                    288: #endif
                    289: #if HAVE_RE_COMP
                    290:        matched = (re_exec(line) == 1);
                    291:        /*
                    292:         * re_exec doesn't seem to provide a way to get the matched string.
                    293:         */
                    294:        *sp = *ep = NULL;
                    295: #endif
                    296: #if HAVE_REGCMP
                    297:        *ep = regex(spattern, line);
                    298:        matched = (*ep != NULL);
                    299:        if (matched)
                    300:                *sp = __loc1;
                    301: #endif
                    302: #if HAVE_V8_REGCOMP
                    303: #if HAVE_REGEXEC2
                    304:        matched = regexec2(spattern, line, notbol);
                    305: #else
                    306:        matched = regexec(spattern, line);
                    307: #endif
                    308:        if (matched)
                    309:        {
                    310:                *sp = spattern->startp[0];
                    311:                *ep = spattern->endp[0];
                    312:        }
                    313: #endif
                    314: #if NO_REGEX
                    315:        matched = match(tpattern, strlen(tpattern), line, line_len, sp, ep);
                    316: #endif
                    317:        }
                    318:        matched = (!(search_type & SRCH_NO_MATCH) && matched) ||
                    319:                        ((search_type & SRCH_NO_MATCH) && !matched);
                    320:        return (matched);
                    321: }
                    322: