home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / glimpse-2.1 / agrep / mgrep.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-16  |  17.3 KB  |  641 lines

  1. /* Copyright (c) 1994 Sun Wu, Udi Manber, Burra Gopal.  All Rights Reserved. */
  2. /* multipattern matcher */
  3. #include <stdio.h>
  4. #include <ctype.h>
  5. #include "agrep.h"
  6.  
  7. #undef    MAXPAT
  8. #define MAXPAT  256
  9.  
  10. #define MAXLINE 1024
  11. #define MAXSYM  256
  12. #define MAXMEMBER1 4096
  13. #define MAXPATFILE 260000
  14. #define BLOCKSIZE  16384
  15. #define MAXHASH    8192
  16. #define mm        8191
  17. #define max_num    30000
  18. #define W_DELIM       128
  19. #define L_DELIM    10 
  20.  
  21. extern int LIMITOUTPUT;
  22. extern int MULTI_OUTPUT;
  23. extern COUNT, FNAME, SILENT, FILENAMEONLY, prev_num_of_matched, num_of_matched;
  24. extern INVERSE;
  25. extern WORDBOUND, WHOLELINE, NOUPPER;
  26. extern unsigned char  CurrentFileName[], Progname[]; 
  27. extern total_line;
  28. extern agrep_initialfd;
  29. extern int EXITONERROR;
  30. extern int PRINTPATTERN;
  31. extern int agrep_inlen;
  32. extern CHAR *agrep_inbuffer;
  33. extern FILE *agrep_finalfp;
  34. extern int agrep_outpointer;
  35. extern int agrep_outlen;
  36. extern CHAR * agrep_outbuffer;
  37. extern int errno;
  38.  
  39. extern int NEW_FILE, POST_FILTER;
  40.  
  41. int LONG  = 0;
  42. int SHORT = 0;
  43. int p_size=0;
  44. unsigned char SHIFT1[MAXMEMBER1];
  45. unsigned char tr[MAXSYM];
  46. unsigned char tr1[MAXSYM];
  47. struct pat_list {
  48.     int  index;
  49.     struct pat_list *next;
  50. *HASH[MAXHASH];
  51. struct pat_list  *pt, *qt;
  52. unsigned char pat_spool[MAXPATFILE+2*max_num+MAXPAT];
  53. unsigned char *patt[max_num];
  54. unsigned char pat_len[max_num];
  55. int num_pat;
  56.  
  57.  
  58. prepf(mfp, mbuf, mlen)
  59. int mfp, mlen;
  60. unsigned char *mbuf;
  61. {
  62.     int length=0, i, p=1, pdx=0;
  63.     unsigned char *pat_ptr=pat_spool;
  64.     unsigned Mask = 15;
  65.     int num_read;
  66.     unsigned char *buf;
  67.  
  68.     if ((mfp == -1) && ((mbuf == NULL) || (mlen <= 0))) return -1;
  69.  
  70.     if (mfp != -1) {
  71.         alloc_buf(mfp, &buf, MAXPATFILE+2*BLOCKSIZE);
  72.         while((num_read = fill_buf(mfp, buf+length, 2*BLOCKSIZE)) > 0) {
  73.             length = length + num_read;
  74.             if(length > MAXPATFILE) {
  75.                 fprintf(stderr, "%s: maximum pattern file size is %d\n", Progname, MAXPATFILE);
  76.                 if (!EXITONERROR) {
  77.                     errno = 2;
  78.                     free_buf(mfp, buf);
  79.                     return -1;
  80.                 }
  81.                 else exit(2);
  82.             }
  83.         }
  84.     }
  85.     else {
  86.         buf = mbuf;
  87.         length = mlen;
  88.     }
  89.  
  90.     buf[length] = '\n';
  91.  
  92.     i = 0; 
  93.     p=1;
  94.     while(i<length) {
  95.         patt[p] = pat_ptr;
  96.         if(WORDBOUND) *pat_ptr++ = W_DELIM;
  97.         if(WHOLELINE) *pat_ptr++ = L_DELIM;
  98.         while((*pat_ptr = buf[i++]) != '\n') pat_ptr++;
  99.         if(WORDBOUND) *pat_ptr++ = W_DELIM;
  100.         if(WHOLELINE) *pat_ptr++ = L_DELIM;           /* Can't be both on */
  101.         *pat_ptr++ = 0;
  102.         p++;  
  103.     }
  104.     if(p>max_num) {
  105.         fprintf(stderr, "%s: maximum number of patterns is %d\n", Progname, max_num); 
  106.         if (!EXITONERROR) {
  107.             errno = 2;
  108.             free_buf(mfp, buf);
  109.             return -1;
  110.         }
  111.         else exit(2);
  112.     }
  113.     for(i=1; i<20; i++) *pat_ptr = i;  /* boundary safety zone */
  114.     for(i=0; i< MAXSYM; i++) tr[i] = i;
  115.     if(NOUPPER) {
  116.         for (i=0; i<MAXSYM; i++)
  117.             if (isupper(i)) tr[i] = tr[tolower(i)];
  118.         /* for(i='A'; i<= 'Z'; i++) tr[i] = i + 'a' - 'A'; */
  119.     }
  120.     if(WORDBOUND) {
  121.         for(i=0; i<128; i++) if(!isalnum(i)) tr[i] = W_DELIM;
  122.     }
  123.     for(i=0; i< MAXSYM; i++) tr1[i] = tr[i]&Mask;
  124.     num_pat = p-1;
  125.     p_size = MAXPAT;
  126.     for(i=1 ; i <= num_pat; i++) {
  127.         p = strlen(patt[i]);
  128.         pat_len[i] = p;
  129.         if(p!=0 && p < p_size) p_size = p;
  130.     }
  131.     if(p_size == 0) {
  132.         fprintf(stderr, "%s: the pattern file is empty\n");
  133.         if (!EXITONERROR) {
  134.             errno = 2;
  135.             free_buf(mfp, buf);
  136.             return -1;
  137.         }
  138.         else exit(2);
  139.     }
  140.     if(length > 400 && p_size > 2) LONG = 1;
  141.     if(p_size == 1) SHORT = 1;
  142.     for(i=0; i<MAXMEMBER1; i++) SHIFT1[i] = p_size - 2;
  143.     for(i=0; i<MAXHASH; i++) {
  144.         HASH[i] = 0;
  145.     }
  146.     for(i=1; i<= num_pat; i++) f_prep(i, patt[i]);
  147.  
  148.     free_buf(mfp, buf);
  149.     return 0;
  150. }
  151.  
  152.  
  153. mgrep(fd)
  154. int fd;
  155.     register char r_newline = '\n';
  156.     unsigned char *text;
  157.     register int buf_end, num_read, i=0, j, start, end, residue = 0;
  158.  
  159. #if    AGREP_POINTER
  160.     if (fd != -1) {
  161. #endif    /*AGREP_POINTER*/
  162.         alloc_buf(fd, &text, 2*BLOCKSIZE+MAXLINE); 
  163.         text[MAXLINE-1] = '\n';  /* initial case */
  164.         start = MAXLINE-1;
  165.  
  166.         while( (num_read = fill_buf(fd, text+MAXLINE, 2*BLOCKSIZE)) > 0) 
  167.         {
  168.             if(INVERSE && COUNT) countline(text+MAXLINE, num_read);
  169.             buf_end = end = MAXLINE + num_read -1 ;
  170.             while(text[end]  != r_newline && end > MAXLINE) end--;
  171.             residue = buf_end - end  + 1 ;
  172.             text[start-1] = r_newline;
  173.  
  174.             /* MGREP_PROCESS */
  175.             if(SHORT) { if (-1 == m_short(text, start, end)) {free_buf(fd, text); return -1;}}
  176.             else      { if (-1 == monkey1(text, start, end)) {free_buf(fd, text); return -1;}}
  177.             if(FILENAMEONLY && (num_of_matched - prev_num_of_matched) && (NEW_FILE || !POST_FILTER)) {
  178.                 if (agrep_finalfp != NULL)
  179.                     fprintf(agrep_finalfp, "%s\n", CurrentFileName);
  180.                 else {
  181.                     int outindex;
  182.                     for(outindex=0; (outindex+agrep_outpointer<agrep_outlen) &&
  183.                             (CurrentFileName[outindex] != '\0'); outindex++) {
  184.                         agrep_outbuffer[agrep_outpointer+outindex] = CurrentFileName[outindex];
  185.                     }
  186.                     if ((CurrentFileName[outindex] != '\0') || (outindex+agrep_outpointer+1>=agrep_outlen)) {
  187.                         OUTPUT_OVERFLOW;
  188.                         free_buf(fd, text);
  189.                         return -1;
  190.                     }
  191.                     else {
  192.                         agrep_outbuffer[agrep_outpointer+outindex++] = '\n';
  193.                     }
  194.                     agrep_outpointer += outindex;
  195.                 }
  196.                 free_buf(fd, text);
  197.                 NEW_FILE = OFF;
  198.                 return 0;
  199.             }
  200.  
  201.             start = MAXLINE - residue;
  202.             if(start < 0) {
  203.                 start = 1; 
  204.             }
  205.             strncpy(text+start, text+end, residue);
  206.         } /* end of while(num_read = ...) */
  207.         text[MAXLINE] = '\n';
  208.         text[start-1] = '\n';
  209.         if(residue > 1) {
  210.             if(SHORT) m_short(text, start, end);
  211.             else      monkey1(text, start, end);
  212.         }
  213.         free_buf(fd, text);
  214.         return 0;
  215. #if    AGREP_POINTER
  216.     }
  217.     else {
  218.         text = (unsigned char *)agrep_inbuffer;
  219.         num_read = agrep_inlen;
  220.         buf_end = end = num_read - 1;
  221.         text[0] = text[end] = r_newline;
  222.         start = 1;
  223.         if (INVERSE && COUNT) countline(text, num_read);
  224.  
  225.             /* An exact copy of the above MGREP_PROCESS */
  226.             if(SHORT) { if (-1 == m_short(text, start, end)) {free_buf(fd, text); return -1;}}
  227.             else      { if (-1 == monkey1(text, start, end)) {free_buf(fd, text); return -1;}}
  228.             if(FILENAMEONLY && (num_of_matched - prev_num_of_matched) && (NEW_FILE || !POST_FILTER)) {
  229.                 if (agrep_finalfp != NULL)
  230.                     fprintf(agrep_finalfp, "%s\n", CurrentFileName);
  231.                 else {
  232.                     int outindex;
  233.                     for(outindex=0; (outindex+agrep_outpointer<agrep_outlen) &&
  234.                             (CurrentFileName[outindex] != '\0'); outindex++) {
  235.                         agrep_outbuffer[agrep_outpointer+outindex] = CurrentFileName[outindex];
  236.                     }
  237.                     if ((CurrentFileName[outindex] != '\0') || (outindex+agrep_outpointer+1>=agrep_outlen)) {
  238.                         OUTPUT_OVERFLOW;
  239.                         free_buf(fd, text);
  240.                         return -1;
  241.                     }
  242.                     else {
  243.                         agrep_outbuffer[agrep_outpointer+outindex++] = '\n';
  244.                     }
  245.                     agrep_outpointer += outindex;
  246.                 }
  247.                 free_buf(fd, text);
  248.                 NEW_FILE = OFF;
  249.                 return 0;
  250.             }
  251.  
  252.         return 0;
  253.     }
  254. #endif    /*AGREP_POINTER*/
  255. } /* end mgrep */
  256.  
  257. countline(text, len)
  258. unsigned char *text; 
  259. int len;
  260. {
  261.     int i;
  262.     for (i=0; i<len; i++) if(text[i] == '\n') total_line++;
  263. }
  264.  
  265.  
  266. monkey1( text, start, end  ) 
  267. int start, end; 
  268. register unsigned char *text;
  269. {
  270.     unsigned char *oldtext;
  271.     register unsigned char *textend;
  272.     register unsigned hash, i;
  273.     register unsigned char shift; 
  274.     register int  m1, j, Long=LONG; 
  275.     int pat_index, m=p_size; 
  276.     int MATCHED=0;
  277.     register unsigned char *qx;
  278.     register struct pat_list *p;
  279.     unsigned char *lastout;
  280.     int OUT=0;
  281.  
  282.     textend = text + end;
  283.     m1 = m - 1;
  284.     lastout = text+start+1;
  285.     text = text + start + m1 ;
  286.     while (text <= textend) {
  287.         hash=tr1[*text];
  288.         hash=(hash<<4)+(tr1[*(text-1)]);
  289.         if(Long) hash=(hash<<4)+(tr1[*(text-2)]);
  290.         shift = SHIFT1[hash];
  291.         if(shift == 0) {
  292.             for(i=2+Long;i<=m1;i++)  {
  293.                 hash=(hash<<4)+(tr1[*(text-i)]);
  294.             }
  295.             hash=hash&mm;
  296.             p = HASH[hash];
  297.             while(p != 0) {
  298.                 pat_index = p->index;
  299.                 p = p->next;
  300.                 qx = text-m1;
  301.                 j = 0;
  302.                 while(tr[patt[pat_index][j]] == tr[*(qx++)]) j++;
  303.                 if (j > m1 ) { 
  304.                     if((int)(pat_len[pat_index]) <= j) {
  305.                         if(text > textend) return 0;
  306.                         /* Udi: if -P (output the pattern # as well as the matched line) ->
  307.                             print(pat_index:) ========= bg: DONE, see below */
  308.                         num_of_matched ++;
  309.                         if(FILENAMEONLY || SILENT)  return 0;
  310.                         MATCHED=1;
  311.                         oldtext = text;    /* only for MULTI_OUTPUT */
  312.  
  313.                         if(COUNT) {
  314.                             while (*text != '\n') text++;
  315.                         }
  316.                         else {
  317.                             if(FNAME && (NEW_FILE || !POST_FILTER)) {
  318.                                 char    nextchar = (POST_FILTER == ON)?'\n':' ';
  319.                                 char    *prevstring = (POST_FILTER == ON)?"\n":"";
  320.                                 if (agrep_finalfp != NULL)
  321.                                     fprintf(agrep_finalfp, "%s%s:%c", prevstring, CurrentFileName, nextchar);
  322.                                 else {
  323.                                     int outindex;
  324.                                     if (prevstring[0] != '\0') {
  325.                                         if(agrep_outpointer + 1 >= agrep_outlen) {
  326.                                             OUTPUT_OVERFLOW;
  327.                                             return -1;
  328.                                         }
  329.                                         else agrep_outbuffer[agrep_outpointer ++] = prevstring[0];
  330.                                     }
  331.                                     for(outindex=0; (outindex+agrep_outpointer<agrep_outlen) &&
  332.                                             (CurrentFileName[outindex] != '\0'); outindex++) {
  333.                                         agrep_outbuffer[agrep_outpointer+outindex] = CurrentFileName[outindex];
  334.                                     }
  335.                                     if ((CurrentFileName[outindex] != '\0') || (outindex+agrep_outpointer+2>=agrep_outlen)) {
  336.                                         OUTPUT_OVERFLOW;
  337.                                         return -1;
  338.                                     }
  339.                                     else {
  340.                                         agrep_outbuffer[agrep_outpointer+outindex++] = ':';
  341.                                         agrep_outbuffer[agrep_outpointer+outindex++] = nextchar;
  342.                                     }
  343.                                     agrep_outpointer += outindex;
  344.                                 }
  345.                                 NEW_FILE = OFF;
  346.                             }
  347.  
  348.                             if (PRINTPATTERN) {
  349.                                 if (agrep_finalfp != NULL)
  350.                                     fprintf(agrep_finalfp, "%d- ", pat_index);
  351.                                 else {
  352.                                     char s[32];
  353.                                     int outindex;
  354.                                     sprintf(s, "%d- ", pat_index);
  355.                                     for(outindex=0; (outindex+agrep_outpointer<agrep_outlen) &&
  356.                                             (s[outindex] != '\0'); outindex++) {
  357.                                         agrep_outbuffer[agrep_outpointer+outindex] = s[outindex];
  358.                                     }
  359.                                     if (s[outindex] != '\0') {
  360.                                         OUTPUT_OVERFLOW;
  361.                                         return -1;
  362.                                     }
  363.                                     agrep_outpointer += outindex;
  364.                                 }
  365.                             }
  366.  
  367.                             if(!INVERSE) {
  368.                                 while(*(--text) != '\n');
  369.  
  370.                                 if (agrep_finalfp != NULL) {
  371.                                     while((text < textend) && (*(++text) != '\n')) fputc(*text, agrep_finalfp);
  372.                                     fputc('\n', agrep_finalfp);
  373.                                 }
  374.                                 else {
  375.                                     while ((text < textend) && (*(++text) != '\n') && (agrep_outpointer < agrep_outlen))
  376.                                         agrep_outbuffer[agrep_outpointer ++] = *text;
  377.                                     if ((*text != '\n') || (agrep_outpointer + 1 >= agrep_outlen)) {
  378.                                         OUTPUT_OVERFLOW;
  379.                                         return -1;
  380.                                     }
  381.                                     else agrep_outbuffer[agrep_outpointer ++] = '\n';
  382.                                 }
  383.  
  384.                                 if (MULTI_OUTPUT) {    /* next match starting from end of current */
  385.                                     text = oldtext + pat_len[pat_index] - 1;
  386.                                     MATCHED = 0;
  387.                                 }
  388.                             }
  389.                             else {
  390.                                 while(*(--text) != '\n');
  391.                                 if(lastout < text) OUT=1;
  392.                                 if (agrep_finalfp != NULL) {
  393.                                     while(lastout < text) fputc(*lastout++, agrep_finalfp);
  394.                                 }
  395.                                 else {
  396.                                     if (text - lastout + agrep_outpointer >= agrep_outlen) {
  397.                                         OUTPUT_OVERFLOW;
  398.                                         return -1;
  399.                                     }
  400.                                     memcpy(agrep_outbuffer+agrep_outpointer, lastout, text-lastout);
  401.                                     agrep_outpointer += (text-lastout);
  402.                                     lastout = text;
  403.                                 }
  404.                                 if(OUT) {
  405.                                     if (agrep_finalfp != NULL) fputc('\n', agrep_finalfp);
  406.                                     else if (agrep_outpointer >= agrep_outlen) {
  407.                                         OUTPUT_OVERFLOW;
  408.                                         return -1;
  409.                                     }
  410.                                     else agrep_outbuffer[agrep_outpointer ++] = '\n';
  411.                                     OUT=0;
  412.                                 }
  413.                                 while((text < textend) && (*(++text) != '\n'));
  414.                                 lastout=text+1;
  415.                             } /* INVERSE */
  416.                         } /* COUNT */
  417.                         if ((LIMITOUTPUT > 0) && (LIMITOUTPUT <= num_of_matched)) return 0;    /* done */
  418.                     } /* pat_len[pat_index] <= j */
  419.                 } /* j > m1 */
  420.                 if (MATCHED && !MULTI_OUTPUT) break;    /* else look for more possible matches since we never know how many will match */
  421.             }
  422.             /* Udi: I think this should always be shift = 1 */
  423.             if(!MATCHED) shift = 1;
  424.             else {
  425.                 MATCHED = 0;
  426.                 shift = m1;
  427.             }
  428.         }
  429.         text = text + shift;
  430.     }
  431.     if(INVERSE && !COUNT) {
  432.         if (agrep_finalfp != NULL) {
  433.             while(lastout <= textend) fputc(*lastout++, agrep_finalfp);
  434.         }
  435.         else {
  436.             if (textend - lastout + 1 + agrep_outpointer >= agrep_outlen) {
  437.                 OUTPUT_OVERFLOW;
  438.                 return -1;
  439.             }
  440.             memcpy(agrep_outbuffer+agrep_outpointer, lastout, textend-lastout+1);
  441.             agrep_outpointer += (textend-lastout+1);
  442.             lastout = textend;
  443.         }
  444.     }
  445.  
  446.     return 0;
  447. }
  448.  
  449. m_short( text, start, end  ) 
  450. int start, end; 
  451. register unsigned char *text;
  452. {
  453.     unsigned char *oldtext;
  454.     register unsigned char *textend;
  455.     register unsigned i; 
  456.     register int  j; 
  457.     register struct pat_list *p, *q;
  458.     register int pat_index; 
  459.     int MATCHED=0;
  460.     int OUT=0;
  461.     unsigned char *lastout;
  462.     unsigned char *qx;
  463.  
  464.     textend = text + end;
  465.     lastout = text + start + 1;
  466.     text = text + start - 1 ;
  467.     while (++text <= textend) {
  468.         p = HASH[*text];
  469.         while(p != 0) {
  470.             pat_index = p->index;
  471.             p = p->next;
  472.             qx = text;
  473.             j = 0;
  474.             while(tr[patt[pat_index][j]] == tr[*(qx++)]) j++;
  475.             if((int)(pat_len[pat_index]) <= j) {
  476.                 if(text >= textend) return 0;
  477.                 num_of_matched++;
  478.                 if(FILENAMEONLY || SILENT)  return 0;
  479.  
  480.                 if(COUNT) {
  481.                     while (*text != '\n') text++;
  482.                 }
  483.                 else {
  484.                     MATCHED = 1;
  485.                     oldtext = text;    /* used only if MULTI_OUTPUT */
  486.                     if(FNAME && (NEW_FILE || !POST_FILTER)) {
  487.                         char    nextchar = (POST_FILTER == ON)?'\n':' ';
  488.                         char    *prevstring = (POST_FILTER == ON)?"\n":"";
  489.                         if (agrep_finalfp != NULL)
  490.                             fprintf(agrep_finalfp, "%s%s:%c", prevstring, CurrentFileName, nextchar);
  491.                         else {
  492.                             int outindex;
  493.                             if (prevstring[0] != '\0') {
  494.                                 if(agrep_outpointer + 1 >= agrep_outlen) {
  495.                                     OUTPUT_OVERFLOW;
  496.                                     return -1;
  497.                                 }
  498.                                 else agrep_outbuffer[agrep_outpointer ++] = prevstring[0];
  499.                             }
  500.                             for(outindex=0; (outindex+agrep_outpointer<agrep_outlen) &&
  501.                                     (CurrentFileName[outindex] != '\0'); outindex++) {
  502.                                 agrep_outbuffer[agrep_outpointer+outindex] = CurrentFileName[outindex];
  503.                             }
  504.                             if ((CurrentFileName[outindex] != '\0') || (outindex+agrep_outpointer+2>=agrep_outlen)) {
  505.                                 OUTPUT_OVERFLOW;
  506.                                 return -1;
  507.                             }
  508.                             else {
  509.                                 agrep_outbuffer[agrep_outpointer+outindex++] = ':';
  510.                                 agrep_outbuffer[agrep_outpointer+outindex++] = nextchar;
  511.                             }
  512.                             agrep_outpointer += outindex;
  513.                         }
  514.                         NEW_FILE = OFF;
  515.                     }
  516.  
  517.                     if (PRINTPATTERN) {
  518.                         if (agrep_finalfp != NULL)
  519.                             fprintf(agrep_finalfp, "%d- ", pat_index);
  520.                         else {
  521.                             char s[32];
  522.                             int outindex;
  523.                             sprintf(s, "%d- ", pat_index);
  524.                             for(outindex=0; (outindex+agrep_outpointer<agrep_outlen) &&
  525.                                     (s[outindex] != '\0'); outindex++) {
  526.                                 agrep_outbuffer[agrep_outpointer+outindex] = s[outindex];
  527.                             }
  528.                             if (s[outindex] != '\0') {
  529.                                 OUTPUT_OVERFLOW;
  530.                                 return -1;
  531.                             }
  532.                             agrep_outpointer += outindex;
  533.                         }
  534.                     }
  535.  
  536.                     if(!INVERSE) {
  537.                         while(*(--text) != '\n');
  538.                         if (agrep_finalfp != NULL) {
  539.                             while((text < textend) && (*(++text) != '\n')) fputc(*text, agrep_finalfp);
  540.                             fputc('\n', agrep_finalfp);
  541.                         }
  542.                         else {
  543.                             while ((text < textend) && (*(++text) != '\n') && (agrep_outpointer < agrep_outlen))
  544.                                 agrep_outbuffer[agrep_outpointer ++] = *text;
  545.                             if ((*text != '\n') || (agrep_outpointer + 1 >= agrep_outlen)) {
  546.                                 OUTPUT_OVERFLOW;
  547.                                 return -1;
  548.                             }
  549.                             else agrep_outbuffer[agrep_outpointer ++] = '\n';
  550.                         }
  551.                         if (MULTI_OUTPUT) {    /* next match starting from end of current */
  552.                             text = oldtext + pat_len[pat_index] - 1;
  553.                             MATCHED = 0;
  554.                         }
  555.                     }
  556.                     else {
  557.                         while(*(--text) != '\n');
  558.                         if(lastout < text) OUT=1;
  559.  
  560.                         if (agrep_finalfp != NULL) {
  561.                             while(lastout < text) fputc(*lastout++, agrep_finalfp);
  562.                         }
  563.                         else {
  564.                             if (text - lastout + agrep_outpointer >= agrep_outlen) {
  565.                                 OUTPUT_OVERFLOW;
  566.                                 return -1;
  567.                             }
  568.                             memcpy(agrep_outbuffer+agrep_outpointer, lastout, text-lastout);
  569.                             agrep_outpointer += (text-lastout);
  570.                             lastout = text;
  571.                         }
  572.                         if(OUT) {
  573.                             if (agrep_finalfp != NULL) fputc('\n', agrep_finalfp);
  574.                             else if (agrep_outpointer >= agrep_outlen) {
  575.                                 OUTPUT_OVERFLOW;
  576.                                 return -1;
  577.                             }
  578.                             else agrep_outbuffer[agrep_outpointer ++] = '\n';
  579.                             OUT=0;
  580.                         }
  581.                         while((text < textend) && (*(++text) != '\n'));
  582.                         lastout=text+1;
  583.                     }
  584.                 } /* COUNT */
  585.                 if ((LIMITOUTPUT > 0) && (LIMITOUTPUT <= num_of_matched)) return 0;    /* done */
  586.             } /* pat_len[pat_index] <= j */
  587.             if(MATCHED && !MULTI_OUTPUT) break;    /* else look for more possible matches */
  588.         }
  589.         MATCHED = 0;
  590.     } /* while */
  591.     if(INVERSE && !COUNT) {
  592.         if (agrep_finalfp != NULL) {
  593.             while(lastout <= textend) fputc(*lastout++, agrep_finalfp);
  594.         }
  595.         else {
  596.             if (textend - lastout + 1 + agrep_outpointer >= agrep_outlen) {
  597.                 OUTPUT_OVERFLOW;
  598.                 return -1;
  599.             }
  600.             memcpy(agrep_outbuffer+agrep_outpointer, lastout, text-lastout+1);
  601.             agrep_outpointer += (text-lastout+1);
  602.             lastout = textend;
  603.         }
  604.     }
  605.  
  606.     return 0;
  607. }
  608.  
  609. f_prep(pat_index, Pattern)
  610. unsigned char *Pattern ; 
  611. int pat_index;
  612. {
  613.     int i, j, m;
  614.     register unsigned hash, Mask=15;
  615.     m = p_size;
  616.     for (i = m-1; i>=(1+LONG); i--) {
  617.         hash = (Pattern[i] & Mask);
  618.         hash = (hash << 4) + (Pattern[i-1]& Mask);
  619.         if(LONG) hash = (hash << 4) + (Pattern[i-2] & Mask);
  620.         if((int)(SHIFT1[hash]) > m-1-i) SHIFT1[hash] = m-1-i;
  621.     }
  622.     if(SHORT) Mask = 255;  /* 011111111 */
  623.     hash = 0;
  624.     for(i = m-1; i>=0; i--)  {
  625.         hash = (hash << 4) + (tr[Pattern[i]]&Mask);
  626.     }
  627.     /*
  628.         if(INVERSE) hash = Pattern[1];
  629.     */
  630.     hash=hash&mm;
  631.     qt = (struct pat_list *) malloc(sizeof(struct pat_list));
  632.     qt->index = pat_index;
  633.     pt = HASH[hash];
  634.     qt->next = pt;
  635.     HASH[hash] = qt;
  636. }
  637.  
  638.  
  639.