"Fossies" - the Fresh Open Source Software Archive

Member "tin-2.4.4/src/regex.c" (20 Nov 2019, 5587 Bytes) of package /linux/misc/tin-2.4.4.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "regex.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.4.3_vs_2.4.4.

    1 /*
    2  *  Project   : tin - a Usenet reader
    3  *  Module    : regex.c
    4  *  Author    : Jason Faultless <jason@altarstone.com>
    5  *  Created   : 1997-02-21
    6  *  Updated   : 2017-02-17
    7  *  Notes     : Regular expression subroutines
    8  *  Credits   :
    9  *
   10  * Copyright (c) 1997-2020 Jason Faultless <jason@altarstone.com>
   11  * All rights reserved.
   12  *
   13  * Redistribution and use in source and binary forms, with or without
   14  * modification, are permitted provided that the following conditions
   15  * are met:
   16  *
   17  * 1. Redistributions of source code must retain the above copyright notice,
   18  *    this list of conditions and the following disclaimer.
   19  *
   20  * 2. Redistributions in binary form must reproduce the above copyright
   21  *    notice, this list of conditions and the following disclaimer in the
   22  *    documentation and/or other materials provided with the distribution.
   23  *
   24  * 3. Neither the name of the copyright holder nor the names of its
   25  *    contributors may be used to endorse or promote products derived from
   26  *    this software without specific prior written permission.
   27  *
   28  * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   29  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   30  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   31  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   32  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   33  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   34  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   35  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   36  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   37  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   38  * POSSIBILITY OF SUCH DAMAGE.
   39  */
   40 
   41 
   42 #ifndef TIN_H
   43 #   include "tin.h"
   44 #endif /* !TIN_H */
   45 #ifndef TCURSES_H
   46 #   include "tcurses.h"
   47 #endif /* !TCURSES_H */
   48 
   49 /*
   50  * See if pattern is matched in string. Return TRUE or FALSE
   51  * if icase=TRUE then ignore case in the compare
   52  * if a precompiled regex is provided it will be used instead of pattern
   53  *
   54  * If you use match_regex() with full regexes within a loop you should always
   55  * provide a precompiled error because if the compilation of the regex fails
   56  * an error message will be display on each execution of match_regex()
   57  */
   58 t_bool
   59 match_regex(
   60     const char *string,
   61     char *pattern,
   62     struct regex_cache *cache,
   63     t_bool icase)
   64 {
   65     int error;
   66     struct regex_cache tmp_cache = { NULL, NULL };
   67     struct regex_cache *ptr_cache;
   68 
   69     if (!tinrc.wildcard)    /* wildmat matching */
   70         return wildmat(string, pattern, icase);
   71 
   72     /* full regexes */
   73     if (cache != NULL && cache->re != NULL)
   74         ptr_cache = cache;  /* use the provided regex cache */
   75     else {
   76         /* compile the regex internally */
   77         if (!compile_regex(pattern, &tmp_cache, (icase ? PCRE_CASELESS : 0)))
   78             return FALSE;
   79         ptr_cache = &tmp_cache;
   80     }
   81 
   82     if ((error = pcre_exec(ptr_cache->re, ptr_cache->extra, string, strlen(string), 0, 0, NULL, 0)) >= 0) {
   83         if (ptr_cache == &tmp_cache) {
   84             FreeIfNeeded(tmp_cache.re);
   85             FreeIfNeeded(tmp_cache.extra);
   86         }
   87 
   88         return TRUE;
   89     }
   90 
   91 #if 0
   92     /*
   93      * match_regex() is mostly used within loops and we don't want to display
   94      * an error message on each call
   95      */
   96     if (error != PCRE_ERROR_NOMATCH)
   97         error_message(2, _(txt_pcre_error_num), error);
   98 #endif /* 0 */
   99 
  100     FreeIfNeeded(tmp_cache.re);
  101     FreeIfNeeded(tmp_cache.extra);
  102 
  103     return FALSE;
  104 }
  105 
  106 
  107 /*
  108  * Compile and optimise 'regex'. Return TRUE if all went well
  109  */
  110 t_bool
  111 compile_regex(
  112     const char *regex,
  113     struct regex_cache *cache,
  114     int options)
  115 {
  116     const char *regex_errmsg = NULL;
  117     int regex_errpos, my_options = options;
  118 
  119 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE) && (defined(PCRE_MAJOR) && PCRE_MAJOR >= 4)
  120     if (IS_LOCAL_CHARSET("UTF-8")) {
  121         int i;
  122 
  123         pcre_config(PCRE_CONFIG_UTF8, &i);
  124         if (i)
  125             my_options |= PCRE_UTF8;
  126     }
  127 #endif /* MULTIBYTE_ABLE && !NO_LOCALE && PCRE_MAJOR && PCRE_MAJOR >= 4 */
  128 
  129     if ((cache->re = pcre_compile(regex, my_options, &regex_errmsg, &regex_errpos, NULL)) == NULL)
  130         error_message(2, _(txt_pcre_error_at), regex_errmsg, regex_errpos, regex);
  131     else {
  132         cache->extra = pcre_study(cache->re, 0, &regex_errmsg);
  133         if (regex_errmsg != NULL) {
  134             /* we failed, clean up */
  135             FreeAndNull(cache->re);
  136             error_message(2, _(txt_pcre_error_text), regex_errmsg);
  137         } else
  138             return TRUE;
  139     }
  140     return FALSE;
  141 }
  142 
  143 
  144 /*
  145  * Highlight any string on 'row' that match 'regex'
  146  */
  147 void
  148 highlight_regexes(
  149     int row,
  150     struct regex_cache *regex,
  151     int color)
  152 {
  153     char *ptr;
  154     int offsets[6]; /* we are not interested in any subpatterns, so 6 is sufficient */
  155     int offsets_size = ARRAY_SIZE(offsets);
  156 #ifdef USE_CURSES
  157     char buf[LEN];
  158 #else
  159     char *buf;
  160 #endif /* USE_CURSES */
  161 
  162     /* Get contents of line from the screen */
  163 #ifdef USE_CURSES
  164     screen_contents(row, 0, buf);
  165 #else
  166     buf = screen[row].col;
  167 #endif /* USE_CURSES */
  168     ptr = buf;
  169 
  170     /* also check for 0 as offsets[] might be too small to hold all captured subpatterns */
  171     while (pcre_exec(regex->re, regex->extra, ptr, strlen(ptr), 0, 0, offsets, offsets_size) >= 0) {
  172         /* we have a match */
  173         if (color >= 0) /* color the matching text */
  174             word_highlight_string(row, (ptr - buf) + offsets[0], offsets[1] - offsets[0], color);
  175         else
  176             /* inverse the matching text */
  177             highlight_string(row, (ptr - buf) + offsets[0], offsets[1] - offsets[0]);
  178 
  179         if (!tinrc.word_h_display_marks) {
  180 #ifdef USE_CURSES
  181             screen_contents(row, 0, buf);
  182 #endif /* USE_CURSES */
  183             ptr += offsets[1] - 2;
  184         } else
  185             ptr += offsets[1];
  186     }
  187 }