home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 1 / ARM_CLUB_CD.iso / contents / apps / clib / progs / utilslib / Regex / C / Test < prev   
Encoding:
Text File  |  1991-09-18  |  12.3 KB  |  392 lines

  1. #include <stdlib.h>
  2. #include <string.h>
  3. #include <limits.h>
  4. #include <stdio.h>
  5. #include <ctype.h>
  6.  
  7. /* Get the interface, including the syntax bits.  */
  8. #include "regex.h"
  9.  
  10. /* Allow BSD version of memory functions */
  11. #define bcopy(s,d,n)    memcpy((d),(s),(n))
  12. #define bcmp(s1,s2,n)    memcmp((s1),(s2),(n))
  13. #define bzero(s,n)    memset((s),0,(n))
  14.  
  15. /* Implemetataion limits */
  16. #define CHAR_NUM (1 << CHAR_BIT)        /* Number of characters */
  17. #define CHAR_ARR (CHAR_NUM / CHAR_BIT)        /* Size of a char bit array */
  18.  
  19. /* Define the syntax stuff, so we can do the \w, \s, etc.  */
  20. #define Sword    1
  21. #define Sdigit    2
  22. #define Sspace    4
  23.  
  24. /* These are the command codes that appear in compiled regular
  25.    expressions, one per byte.  Some command codes are followed by
  26.    argument bytes.  A command code can specify any interpretation
  27.    whatsoever for its arguments.  Zero-bytes may appear in the compiled
  28.    regular expression.
  29.    
  30.    The value of `exactn' is needed in search.c (search_buffer) in emacs.
  31.    So regex.h defines a symbol `RE_EXACTN_VALUE' to be 1; the value of
  32.    `exactn' we use here must also be 1.  */
  33.  
  34. enum regexpcode
  35.   {
  36.     unused=0,
  37.     exactn=1, /* Followed by one byte giving n, then by n literal bytes.  */
  38.     begline,  /* Fail unless at beginning of line.  */
  39.     endline,  /* Fail unless at end of line.  */
  40.     jump,     /* Followed by two bytes giving relative address to jump to.  */
  41.     on_failure_jump,     /* Followed by two bytes giving relative address of 
  42.                 place to resume at in case of failure.  */
  43.     finalize_jump,     /* Throw away latest failure point and then jump to 
  44.                 address.  */
  45.     maybe_finalize_jump, /* Like jump but finalize if safe to do so.
  46.                 This is used to jump back to the beginning
  47.                 of a repeat.  If the command that follows
  48.                 this jump is clearly incompatible with the
  49.                 one at the beginning of the repeat, such that
  50.                 we can be sure that there is no use backtracking
  51.                 out of repetitions already completed,
  52.                 then we finalize.  */
  53.     dummy_failure_jump,  /* Jump, and push a dummy failure point. This 
  54.                 failure point will be thrown away if an attempt 
  55.                             is made to use it for a failure. A + construct 
  56.                             makes this before the first repeat.  Also
  57.                             use it as an intermediary kind of jump when
  58.                             compiling an or construct.  */
  59.     succeed_n,     /* Used like on_failure_jump except has to succeed n times;
  60.             then gets turned into an on_failure_jump. The relative
  61.                     address following it is useless until then.  The
  62.                     address is followed by two bytes containing n.  */
  63.     jump_n,     /* Similar to jump, but jump n times only; also the relative
  64.             address following is in turn followed by yet two more bytes
  65.                     containing n.  */
  66.     set_number_at,    /* Set the following relative location to the
  67.                subsequent number.  */
  68.     anychar,      /* Matches any (more or less) one character.  */
  69.     charset,      /* Matches any one char belonging to specified set.
  70.              First following byte is number of bitmap bytes.
  71.              Then come bytes for a bitmap saying which chars are in.
  72.              Bits in each byte are ordered low-bit-first.
  73.              A character is in the set if its bit is 1.
  74.              A character too large to have a bit in the map
  75.              is automatically not in the set.  */
  76.     charset_not,  /* Same parameters as charset, but match any character
  77.                      that is not one of those specified.  */
  78.     start_memory, /* Start remembering the text that is matched, for
  79.              storing in a memory register.  Followed by one
  80.                      byte containing the register number.  Register numbers
  81.                      must be in the range 0 through RE_NREGS.  */
  82.     stop_memory,  /* Stop remembering the text that is matched
  83.              and store it in a memory register.  Followed by
  84.                      one byte containing the register number. Register
  85.                      numbers must be in the range 0 through RE_NREGS.  */
  86.     duplicate,    /* Match a duplicate of something remembered.
  87.              Followed by one byte containing the index of the memory 
  88.                      register.  */
  89.     begbuf,       /* Succeeds if at beginning of buffer.  */
  90.     endbuf,       /* Succeeds if at end of buffer.  */
  91.     wordchar,     /* Matches any word-constituent character.  */
  92.     notwordchar,  /* Matches any char that is not a word-constituent.  */
  93.     spacechar,    /* Matches any whitespace character */
  94.     notspacechar, /* Matches any non-whitespace character */
  95.     digit,        /* Matches any digit character */
  96.     notdigit,     /* Matches any non-digit character */
  97.     begword,      /* Succeeds if at beginning of word.  */
  98.     endword,      /* Succeeds if at end of word.  */
  99.     wordbound,    /* Succeeds if at a word boundary */
  100.     notwordbound  /* Succeeds if not at a word boundary */
  101.   };
  102.  
  103.  
  104. #define SIGN_EXTEND_CHAR(x) ((signed char)(x))
  105.  
  106. /* Put into DESTINATION a number stored in two contingous bytes starting
  107.    at SOURCE.  */
  108. #define EXTRACT_NUMBER(destination, source)                \
  109.   { (destination) = *(source) & 0377;                    \
  110.     (destination) += SIGN_EXTEND_CHAR (*(char *)((source) + 1)) << 8; }
  111.  
  112. /* Same as EXTRACT_NUMBER, except increment the pointer for source to
  113.    point to second byte of SOURCE.  Note that SOURCE has to be a value
  114.    such as p, not, e.g., p + 1. */
  115. #define EXTRACT_NUMBER_AND_INCR(destination, source)            \
  116.   { EXTRACT_NUMBER (destination, source);                \
  117.     (source) += 2; }
  118.  
  119. /* Indexed by a character, gives the upper case equivalent of the
  120.    character.  */
  121.  
  122. char upcase[0400] = 
  123.   { 000, 001, 002, 003, 004, 005, 006, 007,
  124.     010, 011, 012, 013, 014, 015, 016, 017,
  125.     020, 021, 022, 023, 024, 025, 026, 027,
  126.     030, 031, 032, 033, 034, 035, 036, 037,
  127.     040, 041, 042, 043, 044, 045, 046, 047,
  128.     050, 051, 052, 053, 054, 055, 056, 057,
  129.     060, 061, 062, 063, 064, 065, 066, 067,
  130.     070, 071, 072, 073, 074, 075, 076, 077,
  131.     0100, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
  132.     0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117,
  133.     0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
  134.     0130, 0131, 0132, 0133, 0134, 0135, 0136, 0137,
  135.     0140, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
  136.     0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117,
  137.     0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
  138.     0130, 0131, 0132, 0173, 0174, 0175, 0176, 0177,
  139.     0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
  140.     0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217,
  141.     0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227,
  142.     0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237,
  143.     0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247,
  144.     0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
  145.     0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
  146.     0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
  147.     0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
  148.     0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317,
  149.     0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327,
  150.     0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,
  151.     0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347,
  152.     0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357,
  153.     0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
  154.     0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377
  155.   };
  156.  
  157. /* Routines for test program */
  158. static void printchar (char);
  159. static void dump_buffer (struct re_pattern_buffer *);
  160.  
  161. /* Use this to run interactive tests.  */
  162. int main (void)
  163. {
  164.   char pat[80];
  165.   struct re_pattern_buffer buf;
  166.   struct re_registers regs;
  167.   int i, j;
  168.   char *p;
  169.   char fastmap[CHAR_NUM];
  170.  
  171.   memset(&buf,0,sizeof(buf));
  172.  
  173.   while (1)
  174.     {
  175.       printf("Pat> ");
  176.       fflush(stdout);
  177.       gets (pat);
  178.  
  179.       if (*pat == 0)
  180.         break;
  181.  
  182.       p = re_compile_pattern (pat, strlen(pat), &buf);
  183.       if (p)
  184.     {
  185.       fprintf(stderr,"Error: %s\n",p);
  186.       continue;
  187.     }
  188.  
  189.       printf("\n--------------------------------------------------\n");
  190.       printf("Buffer: ");
  191.       for (i = 0; i < buf.used; ++i)
  192.         printchar(buf.buffer[i]);
  193.       printf ("\n%d allocated, %d used.\n", buf.allocated, buf.used);
  194.       printf("--------------------------------------------------\n");
  195.       re_compile_fastmap (&buf);
  196.       printf ("Allowed by fastmap: ");
  197.       for (i = 0; i < CHAR_NUM; i++)
  198.         if (fastmap[i]) printchar (i);
  199.       printf("\n--------------------------------------------------\n");
  200.       dump_buffer (&buf);
  201.       printf("--------------------------------------------------\n\n");
  202.  
  203.       while (1)
  204.     {
  205.       printf("Str> ");
  206.       fflush(stdout);
  207.       gets (pat);    /* Now read the string to match against */
  208.       if (*pat == 0)
  209.         break;
  210.  
  211.       i = re_search (&buf, pat, strlen (pat), 0, 0, ®s);
  212.       j = regs.end[0] - regs.start[0];
  213.       p = pat + regs.start[0];
  214.       printf ("Found \"%.*s\" at %d.\n", j, p, i);
  215.     }
  216.     }
  217. }
  218.  
  219. static void dump_buffer (struct re_pattern_buffer *bufp)
  220. {
  221.   int op;
  222.   int n, m;
  223.   char *p = bufp->buffer;
  224.   char *end = bufp->buffer + bufp->used;
  225.  
  226.   while (p < end)
  227.   {
  228.     printf("%.8X: ",(unsigned int)p);
  229.     switch (op = *p++)
  230.     {
  231.     case unused:
  232.       printf("Unused");
  233.       break;
  234.     case exactn:
  235.       n = *p++;
  236.       printf("Match ");
  237.       while (n-- > 0)
  238.     printchar(*p++);
  239.       break;
  240.     case begline:
  241.       printf("Start of line");
  242.       break;
  243.     case endline:
  244.       printf("End of line");
  245.       break;
  246.     case jump:
  247.       EXTRACT_NUMBER_AND_INCR(n,p);
  248.       printf("Jump to %.8X", (int)(p + n));
  249.       break;
  250.     case on_failure_jump:
  251.       EXTRACT_NUMBER_AND_INCR(n,p);
  252.       printf("Resume at %.8X on failure", (int)(p + n));
  253.       break;
  254.     case finalize_jump:
  255.       EXTRACT_NUMBER_AND_INCR(n,p);
  256.       printf("Finalise and jump to %.8X", (int)(p + n));
  257.       break;
  258.     case maybe_finalize_jump:
  259.       EXTRACT_NUMBER_AND_INCR(n,p);
  260.       printf("Jump to %.8X (finalise if possible)", (int)(p + n));
  261.       break;
  262.     case dummy_failure_jump:
  263.       EXTRACT_NUMBER_AND_INCR(n,p);
  264.       printf("Jump to %.8X and push a dummy failure", (int)(p + n));
  265.       break;
  266.     case succeed_n:
  267.       EXTRACT_NUMBER_AND_INCR(n,p);
  268.       EXTRACT_NUMBER_AND_INCR(m,p);
  269.       printf("Succeed at least %d time%s, then resume at %.8X on failure",
  270.           m, (m == 1 ? "" : "s"), (int)(p + n - 2));
  271.       break;
  272.     case jump_n:
  273.       EXTRACT_NUMBER_AND_INCR(n,p);
  274.       EXTRACT_NUMBER_AND_INCR(m,p);
  275.       printf("Jump to %.8X, %d time%s", (int)(p + n - 2),
  276.           m, (m == 1 ? "" : "s"));
  277.       break;
  278.     case set_number_at:
  279.       EXTRACT_NUMBER_AND_INCR(n,p);
  280.       EXTRACT_NUMBER_AND_INCR(m,p);
  281.       printf("Set the number at %.8X to %d", (int)(p + n - 5), m);
  282.       break;
  283.     case anychar:
  284.       printf("Any character");
  285.       break;
  286.     case charset:
  287.       printf("Character set: ");
  288.       for (n = *p++ * CHAR_BIT - 1; n >= 0; --n)
  289.     if (p[n / CHAR_BIT] & (1 << (n % CHAR_BIT)))
  290.       printchar(n);
  291.       p += p[-1];
  292.       break;
  293.     case charset_not:
  294.       printf("Negated character set: ");
  295.       for (n = *p++ * CHAR_BIT - 1; n >= 0; --n)
  296.     if (p[n / CHAR_BIT] & (1 << (n % CHAR_BIT)))
  297.       printchar(n);
  298.       p += p[-1];
  299.       break;
  300.     case start_memory:
  301.       printf("Start memory (%d)", *p++);
  302.       break;
  303.     case stop_memory:
  304.       printf("Stop memory (%d)", *p++);
  305.       break;
  306.     case duplicate:
  307.       printf("Duplicate (%d)", *p++);
  308.       break;
  309.     case begword:
  310.       printf("Start of word");
  311.       break;
  312.     case endword:
  313.       printf("End of word");
  314.       break;
  315.     case begbuf:
  316.       printf("Start of buffer");
  317.       break;
  318.     case endbuf:
  319.       printf("End of buffer");
  320.       break;
  321.     case wordchar:
  322.       printf("Word character");
  323.       break;
  324.     case notwordchar:
  325.       printf("Not word character");
  326.       break;
  327.     case spacechar:
  328.       printf("Space character");
  329.       break;
  330.     case notspacechar:
  331.       printf("Not space character");
  332.       break;
  333.     case digit:
  334.       printf("Digit");
  335.       break;
  336.     case notdigit:
  337.       printf("Not digit");
  338.       break;
  339.     case wordbound:
  340.       printf("Word boundary");
  341.       break;
  342.     case notwordbound:
  343.       printf("Not word boundary");
  344.       break;
  345.     default:
  346.       printf("Unknown code (0x%.2X)",op);
  347.       break;
  348.     }
  349.     putchar('\n');
  350.   }
  351. }
  352.  
  353. static void printchar (char c)
  354. {
  355.     if (!isprint(c))
  356.     {
  357.         switch (c)
  358.         {
  359.         case '\0':
  360.             printf("\\0");
  361.             break;
  362.         case '\a':
  363.             printf("\\a");
  364.             break;
  365.         case '\b':
  366.             printf("\\b");
  367.             break;
  368.         case '\f':
  369.             printf("\\f");
  370.             break;
  371.         case '\n':
  372.             printf("\\n");
  373.             break;
  374.         case '\r':
  375.             printf("\\r");
  376.             break;
  377.         case '\t':
  378.             printf("\\t");
  379.             break;
  380.         case '\v':
  381.             printf("\\v");
  382.             break;
  383.         default:
  384.             printf("\\x%.2X",c);
  385.             break;
  386.         }
  387.     }
  388.     else
  389.         putchar (c);
  390. }
  391.  
  392.