1. package com.sun.org.apache.regexp.internal;
  2. /*
  3. * ====================================================================
  4. *
  5. * The Apache Software License, Version 1.1
  6. *
  7. * Copyright (c) 1999 The Apache Software Foundation. All rights
  8. * reserved.
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions
  12. * are met:
  13. *
  14. * 1. Redistributions of source code must retain the above copyright
  15. * notice, this list of conditions and the following disclaimer.
  16. *
  17. * 2. Redistributions in binary form must reproduce the above copyright
  18. * notice, this list of conditions and the following disclaimer in
  19. * the documentation and/or other materials provided with the
  20. * distribution.
  21. *
  22. * 3. The end-user documentation included with the redistribution, if
  23. * any, must include the following acknowlegement:
  24. * "This product includes software developed by the
  25. * Apache Software Foundation (http://www.apache.org/)."
  26. * Alternately, this acknowlegement may appear in the software itself,
  27. * if and wherever such third-party acknowlegements normally appear.
  28. *
  29. * 4. The names "The Jakarta Project", "Jakarta-Regexp", and "Apache Software
  30. * Foundation" must not be used to endorse or promote products derived
  31. * from this software without prior written permission. For written
  32. * permission, please contact apache@apache.org.
  33. *
  34. * 5. Products derived from this software may not be called "Apache"
  35. * nor may "Apache" appear in their names without prior written
  36. * permission of the Apache Group.
  37. *
  38. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  39. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  40. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  41. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  42. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  43. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  44. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  45. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  46. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  47. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  48. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  49. * SUCH DAMAGE.
  50. * ====================================================================
  51. *
  52. * This software consists of voluntary contributions made by many
  53. * individuals on behalf of the Apache Software Foundation. For more
  54. * information on the Apache Software Foundation, please see
  55. * <http://www.apache.org/>.
  56. *
  57. */
  58. import java.util.*;
  59. import java.io.*;
  60. /**
  61. * A subclass of RECompiler which can dump a regular expression program
  62. * for debugging purposes.
  63. *
  64. * @author <a href="mailto:jonl@muppetlabs.com">Jonathan Locke</a>
  65. * @version $Id: REDebugCompiler.java,v 1.1 2000/04/27 01:22:33 jon Exp $
  66. */
  67. public class REDebugCompiler extends RECompiler
  68. {
  69. /**
  70. * Mapping from opcodes to descriptive strings
  71. */
  72. static Hashtable hashOpcode = new Hashtable();
  73. static
  74. {
  75. hashOpcode.put(new Integer(RE.OP_RELUCTANTSTAR), "OP_RELUCTANTSTAR");
  76. hashOpcode.put(new Integer(RE.OP_RELUCTANTPLUS), "OP_RELUCTANTPLUS");
  77. hashOpcode.put(new Integer(RE.OP_RELUCTANTMAYBE), "OP_RELUCTANTMAYBE");
  78. hashOpcode.put(new Integer(RE.OP_END), "OP_END");
  79. hashOpcode.put(new Integer(RE.OP_BOL), "OP_BOL");
  80. hashOpcode.put(new Integer(RE.OP_EOL), "OP_EOL");
  81. hashOpcode.put(new Integer(RE.OP_ANY), "OP_ANY");
  82. hashOpcode.put(new Integer(RE.OP_ANYOF), "OP_ANYOF");
  83. hashOpcode.put(new Integer(RE.OP_BRANCH), "OP_BRANCH");
  84. hashOpcode.put(new Integer(RE.OP_ATOM), "OP_ATOM");
  85. hashOpcode.put(new Integer(RE.OP_STAR), "OP_STAR");
  86. hashOpcode.put(new Integer(RE.OP_PLUS), "OP_PLUS");
  87. hashOpcode.put(new Integer(RE.OP_MAYBE), "OP_MAYBE");
  88. hashOpcode.put(new Integer(RE.OP_NOTHING), "OP_NOTHING");
  89. hashOpcode.put(new Integer(RE.OP_GOTO), "OP_GOTO");
  90. hashOpcode.put(new Integer(RE.OP_ESCAPE), "OP_ESCAPE");
  91. hashOpcode.put(new Integer(RE.OP_OPEN), "OP_OPEN");
  92. hashOpcode.put(new Integer(RE.OP_CLOSE), "OP_CLOSE");
  93. hashOpcode.put(new Integer(RE.OP_BACKREF), "OP_BACKREF");
  94. hashOpcode.put(new Integer(RE.OP_POSIXCLASS), "OP_POSIXCLASS");
  95. }
  96. /**
  97. * Returns a descriptive string for an opcode.
  98. * @param opcode Opcode to convert to a string
  99. * @return Description of opcode
  100. */
  101. String opcodeToString(char opcode)
  102. {
  103. // Get string for opcode
  104. String ret =(String)hashOpcode.get(new Integer(opcode));
  105. // Just in case we have a corrupt program
  106. if (ret == null)
  107. {
  108. ret = "OP_????";
  109. }
  110. return ret;
  111. }
  112. /**
  113. * Return a string describing a (possibly unprintable) character.
  114. * @param c Character to convert to a printable representation
  115. * @return String representation of character
  116. */
  117. String charToString(char c)
  118. {
  119. // If it's unprintable, convert to '\###'
  120. if (c < ' ' || c > 127)
  121. {
  122. return "\\" + (int)c;
  123. }
  124. // Return the character as a string
  125. return String.valueOf(c);
  126. }
  127. /**
  128. * Returns a descriptive string for a node in a regular expression program.
  129. * @param node Node to describe
  130. * @return Description of node
  131. */
  132. String nodeToString(int node)
  133. {
  134. // Get opcode and opdata for node
  135. char opcode = instruction[node + RE.offsetOpcode];
  136. int opdata = (int)instruction[node + RE.offsetOpdata];
  137. // Return opcode as a string and opdata value
  138. return opcodeToString(opcode) + ", opdata = " + opdata;
  139. }
  140. /**
  141. * Dumps the current program to a PrintWriter
  142. * @param p PrintWriter for program dump output
  143. */
  144. public void dumpProgram(PrintWriter p)
  145. {
  146. // Loop through the whole program
  147. for (int i = 0; i < lenInstruction; )
  148. {
  149. // Get opcode, opdata and next fields of current program node
  150. char opcode = instruction[i + RE.offsetOpcode];
  151. char opdata = instruction[i + RE.offsetOpdata];
  152. short next = (short)instruction[i + RE.offsetNext];
  153. // Display the current program node
  154. p.print(i + ". " + nodeToString(i) + ", next = ");
  155. // If there's no next, say 'none', otherwise give absolute index of next node
  156. if (next == 0)
  157. {
  158. p.print("none");
  159. }
  160. else
  161. {
  162. p.print(i + next);
  163. }
  164. // Move past node
  165. i += RE.nodeSize;
  166. // If character class
  167. if (opcode == RE.OP_ANYOF)
  168. {
  169. // Opening bracket for start of char class
  170. p.print(", [");
  171. // Show each range in the char class
  172. int rangeCount = opdata;
  173. for (int r = 0; r < rangeCount; r++)
  174. {
  175. // Get first and last chars in range
  176. char charFirst = instruction[i++];
  177. char charLast = instruction[i++];
  178. // Print range as X-Y, unless range encompasses only one char
  179. if (charFirst == charLast)
  180. {
  181. p.print(charToString(charFirst));
  182. }
  183. else
  184. {
  185. p.print(charToString(charFirst) + "-" + charToString(charLast));
  186. }
  187. }
  188. // Annotate the end of the char class
  189. p.print("]");
  190. }
  191. // If atom
  192. if (opcode == RE.OP_ATOM)
  193. {
  194. // Open quote
  195. p.print(", \"");
  196. // Print each character in the atom
  197. for (int len = opdata; len-- != 0; )
  198. {
  199. p.print(charToString(instruction[i++]));
  200. }
  201. // Close quote
  202. p.print("\"");
  203. }
  204. // Print a newline
  205. p.println("");
  206. }
  207. }
  208. }