home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1994 #1 / monster.zip / monster / PROG_C / GAWKNT.ZIP / SRC.ZIP / RE.C < prev    next >
C/C++ Source or Header  |  1994-03-07  |  4KB  |  213 lines

  1. /*
  2.  * re.c - compile regular expressions.
  3.  */
  4.  
  5. /* 
  6.  * Copyright (C) 1991, 1992, 1993 the Free Software Foundation, Inc.
  7.  * 
  8.  * This file is part of GAWK, the GNU implementation of the
  9.  * AWK Progamming Language.
  10.  * 
  11.  * GAWK is free software; you can redistribute it and/or modify
  12.  * it under the terms of the GNU General Public License as published by
  13.  * the Free Software Foundation; either version 2 of the License, or
  14.  * (at your option) any later version.
  15.  * 
  16.  * GAWK is distributed in the hope that it will be useful,
  17.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.  * GNU General Public License for more details.
  20.  * 
  21.  * You should have received a copy of the GNU General Public License
  22.  * along with GAWK; see the file COPYING.  If not, write to
  23.  * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  24.  */
  25.  
  26. #include "awk.h"
  27.  
  28. /* Generate compiled regular expressions */
  29.  
  30. Regexp *
  31. make_regexp(s, len, ignorecase, dfa)
  32. char *s;
  33. size_t len;
  34. int ignorecase;
  35. int dfa;
  36. {
  37.     Regexp *rp;
  38.     const char *rerr;
  39.     char *src = s;
  40.     char *temp;
  41.     char *end = s + len;
  42.     register char *dest;
  43.     register int c;
  44.  
  45.     /* Handle escaped characters first. */
  46.  
  47.     /* Build a copy of the string (in dest) with the
  48.        escaped characters translated,  and generate the regex
  49.        from that.  
  50.     */
  51.     emalloc(dest, char *, len + 2, "make_regexp");
  52.     temp = dest;
  53.  
  54.     while (src < end) {
  55.         if (*src == '\\') {
  56.             c = *++src;
  57.             switch (c) {
  58.             case 'a':
  59.             case 'b':
  60.             case 'f':
  61.             case 'n':
  62.             case 'r':
  63.             case 't':
  64.             case 'v':
  65.             case 'x':
  66.             case '0':
  67.             case '1':
  68.             case '2':
  69.             case '3':
  70.             case '4':
  71.             case '5':
  72.             case '6':
  73.             case '7':
  74.                 c = parse_escape(&src);
  75.                 if (c < 0)
  76.                     cant_happen();
  77.                 *dest++ = (char)c;
  78.                 break;
  79.             default:
  80.                 *dest++ = '\\';
  81.                 *dest++ = (char)c;
  82.                 src++;
  83.                 break;
  84.             } /* switch */
  85.         } else {
  86.             *dest++ = *src++;    /* not '\\' */
  87.         }
  88.     } /* for */
  89.  
  90.     *dest = '\0' ;    /* Only necessary if we print dest ? */
  91.     emalloc(rp, Regexp *, sizeof(*rp), "make_regexp");
  92.     memset((char *) rp, 0, sizeof(*rp));
  93.     emalloc(rp->pat.buffer, unsigned char *, 16, "make_regexp");
  94.     rp->pat.allocated = 16;
  95.     emalloc(rp->pat.fastmap, char *, 256, "make_regexp");
  96.  
  97.     if (ignorecase)
  98.         rp->pat.translate = casetable;
  99.     else
  100.         rp->pat.translate = NULL;
  101.     len = dest - temp;
  102.     if ((rerr = re_compile_pattern(temp, len, &(rp->pat))) != NULL)
  103.         fatal("%s: /%s/", rerr, temp);
  104.     if (dfa && !ignorecase) {
  105.         dfacomp(temp, len, &(rp->dfareg), 1);
  106.         rp->dfa = 1;
  107.     } else
  108.         rp->dfa = 0;
  109.  
  110.     free(temp);
  111.     return rp;
  112. }
  113.  
  114. int
  115. research(rp, str, start, len, need_start)
  116. Regexp *rp;
  117. register char *str;
  118. int start;
  119. register size_t len;
  120. int need_start;
  121. {
  122.     char *ret = str;
  123.  
  124.     if (rp->dfa) {
  125.         char save;
  126.         int count = 0;
  127.         int try_backref;
  128.  
  129.         /*
  130.          * dfa likes to stick a '\n' right after the matched
  131.          * text.  So we just save and restore the character.
  132.          */
  133.         save = str[start+len];
  134.         ret = dfaexec(&(rp->dfareg), str+start, str+start+len, 1,
  135.                     &count, &try_backref);
  136.         str[start+len] = save;
  137.     }
  138.     if (ret) {
  139.         if (need_start || rp->dfa == 0)
  140.             return re_search(&(rp->pat), str, start+len, start,
  141.                     len, &(rp->regs));
  142.         else
  143.             return 1;
  144.      } else
  145.         return -1;
  146. }
  147.  
  148. void
  149. refree(rp)
  150. Regexp *rp;
  151. {
  152.     free(rp->pat.buffer);
  153.     free(rp->pat.fastmap);
  154.     if (rp->dfa)
  155.         dfafree(&(rp->dfareg));
  156.     free(rp);
  157. }
  158.  
  159. void
  160. dfaerror(s)
  161. const char *s;
  162. {
  163.     fatal(s);
  164. }
  165.  
  166. Regexp *
  167. re_update(t)
  168. NODE *t;
  169. {
  170.     NODE *t1;
  171.  
  172. #    define    CASE    1
  173.     if ((t->re_flags & CASE) == IGNORECASE) {
  174.         if (t->re_flags & CONST)
  175.             return t->re_reg;
  176.         t1 = force_string(tree_eval(t->re_exp));
  177.         if (t->re_text) {
  178.             if (cmp_nodes(t->re_text, t1) == 0) {
  179.                 free_temp(t1);
  180.                 return t->re_reg;
  181.             }
  182.             unref(t->re_text);
  183.         }
  184.         t->re_text = dupnode(t1);
  185.         free_temp(t1);
  186.     }
  187.     if (t->re_reg)
  188.         refree(t->re_reg);
  189.     if (t->re_cnt)
  190.         t->re_cnt++;
  191.     if (t->re_cnt > 10)
  192.         t->re_cnt = 0;
  193.     if (!t->re_text) {
  194.         t1 = force_string(tree_eval(t->re_exp));
  195.         t->re_text = dupnode(t1);
  196.         free_temp(t1);
  197.     }
  198.     t->re_reg = make_regexp(t->re_text->stptr, t->re_text->stlen,
  199.                 IGNORECASE, t->re_cnt);
  200.     t->re_flags &= ~CASE;
  201.     t->re_flags |= IGNORECASE;
  202.     return t->re_reg;
  203. }
  204.  
  205. void
  206. resetup()
  207. {
  208.     reg_syntax_t syn = RE_SYNTAX_AWK;
  209.  
  210.     (void) re_set_syntax(syn);
  211.     dfasyntax(syn, 0);
  212. }
  213.