[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.3

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