trstr.c - neatvi - [fork] simple vi-type editor with UTF-8 support
 (HTM) git clone git://src.adamsgaard.dk/neatvi
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
       ---
       trstr.c (2419B)
       ---
            1 #include <ctype.h>
            2 #include <stdlib.h>
            3 #include <stdio.h>
            4 #include <string.h>
            5 #include "vi.h"
            6 
            7 struct rstr {
            8         struct rset *rs;        /* only for regex patterns */
            9         char *str;                /* for simple, non-regex patterns  */
           10         int icase;                /* ignore case */
           11         int lbeg, lend;                /* match line beg/end */
           12         int wbeg, wend;                /* match word beg/end */
           13 };
           14 
           15 /* return zero if a simple pattern is given */
           16 static int rstr_simple(struct rstr *rs, char *re)
           17 {
           18         char *beg;
           19         char *end;
           20         rs->lbeg = re[0] == '^';
           21         if (rs->lbeg)
           22                 re++;
           23         rs->wbeg = re[0] == '\\' && re[1] == '<';
           24         if (rs->wbeg)
           25                 re += 2;
           26         beg = re;
           27         while (re[0] && !strchr("\\.*+?[]{}()$", (unsigned char) re[0]))
           28                 re++;
           29         end = re;
           30         rs->wend = re[0] == '\\' && re[1] == '>';
           31         if (rs->wend)
           32                 re += 2;
           33         rs->lend = re[0] == '$';
           34         if (rs->lend)
           35                 re++;
           36         if (!re[0]) {
           37                 int len = end - beg;
           38                 rs->str = malloc(len + 1);
           39                 memcpy(rs->str, beg, len);
           40                 rs->str[len] = '\0';
           41                 return 0;
           42         }
           43         return 1;
           44 }
           45 
           46 struct rstr *rstr_make(char *re, int flg)
           47 {
           48         struct rstr *rs = malloc(sizeof(*rs));
           49         memset(rs, 0, sizeof(*rs));
           50         rs->icase = flg & RE_ICASE;
           51         if (rstr_simple(rs, re))
           52                 rs->rs = rset_make(1, &re, flg);
           53         if (!rs->rs && !rs->str) {
           54                 free(rs);
           55                 return NULL;
           56         }
           57         return rs;
           58 }
           59 
           60 static int isword(char *s)
           61 {
           62         int c = (unsigned char) s[0];
           63         return isalnum(c) || c == '_' || c > 127;
           64 }
           65 
           66 static int match_case(char *s, char *r, int icase)
           67 {
           68         for (; *r && *s; s++, r++) {
           69                 if (!icase && *s != *r)
           70                         return 1;
           71                 if (icase && tolower((unsigned char) *s) != tolower((unsigned char) *r))
           72                         return 1;
           73         }
           74         return *r;
           75 }
           76 
           77 /* return zero if an occurrence is found */
           78 int rstr_find(struct rstr *rs, char *s, int n, int *grps, int flg)
           79 {
           80         int len;
           81         char *beg, *end;
           82         char *r;
           83         if (rs->rs)
           84                 return rset_find(rs->rs, s, n, grps, flg);
           85         if ((rs->lbeg && (flg & RE_NOTBOL)) || (rs->lend && (flg & RE_NOTEOL)))
           86                 return -1;
           87         len = strlen(rs->str);
           88         beg = s;
           89         end = s + strlen(s) - len - 1;
           90         if (end < beg)
           91                 return -1;
           92         if (rs->lend)
           93                 beg = end;
           94         if (rs->lbeg)
           95                 end = s;
           96         for (r = beg; r <= end; r++) {
           97                 if (rs->wbeg && r > s && (isword(r - 1) || !isword(r)))
           98                         continue;
           99                 if (rs->wend && r[len] && (!isword(r + len - 1) || isword(r + len)))
          100                         continue;
          101                 if (!match_case(r, rs->str, rs->icase)) {
          102                         if (n >= 1) {
          103                                 grps[0] = r - s;
          104                                 grps[1] = r - s + len;
          105                         }
          106                         return 0;
          107                 }
          108         }
          109         return -1;
          110 }
          111 
          112 void rstr_free(struct rstr *rs)
          113 {
          114         if (rs->rs)
          115                 rset_free(rs->rs);
          116         free(rs->str);
          117         free(rs);
          118 }