0N/A/*
0N/A * CDDL HEADER START
0N/A *
0N/A * The contents of this file are subject to the terms of the
0N/A * Common Development and Distribution License (the "License").
0N/A * You may not use this file except in compliance with the License.
0N/A *
0N/A * See LICENSE.txt included in this distribution for the specific
0N/A * language governing permissions and limitations under the License.
0N/A *
0N/A * When distributing Covered Code, include this CDDL HEADER in each
0N/A * file and include the License file at LICENSE.txt.
0N/A * If applicable, add the following below this CDDL HEADER, with the
0N/A * fields enclosed by brackets "[]" replaced with your own identifying
0N/A * information: Portions Copyright [yyyy] [name of copyright owner]
0N/A *
0N/A * CDDL HEADER END
0N/A */
0N/A
0N/A/*
1253N/A * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
0N/A */
0N/A
0N/A/**
0N/A * for plain text tokenizers
0N/A */
0N/Apackage org.opensolaris.opengrok.search.context;
0N/A
1080N/Aimport java.io.CharArrayReader;
686N/Aimport java.io.IOException;
686N/Aimport java.io.Reader;
686N/Aimport java.io.Writer;
686N/Aimport java.util.List;
686N/Aimport java.util.TreeMap;
0N/Aimport org.opensolaris.opengrok.search.Hit;
686N/Aimport org.opensolaris.opengrok.web.Util;
0N/A%%
0N/A
0N/A%public
0N/A%class PlainLineTokenizer
0N/A%line
0N/A%unicode
0N/A%type String
0N/A%ignorecase
0N/A%switch
1080N/A%char
0N/A
0N/A%{
1470N/A /**
1470N/A * Buffer that holds all the text from the start of the current line, or, in
1470N/A * the case of a match that spans multiple lines, from the start of the
1470N/A * first line part of the matching region.
1470N/A */
1470N/A private final StringBuilder markedContents = new StringBuilder();
1470N/A int markedPos = 0;
1470N/A int curLinePos = 0;
1470N/A int matchStart = -1;
1470N/A int markedLine = 0;
1470N/A int rest = 0;
1470N/A boolean wait = false;
1470N/A boolean dumpRest = false;
1470N/A Writer out;
1470N/A String url;
1470N/A TreeMap<Integer, String[]> tags;
1470N/A boolean prevHi = false;
1470N/A Integer prevLn = null;
1470N/A List<Hit> hits;
1470N/A Hit hit;
1470N/A StringBuilder sb;
1470N/A boolean alt;
0N/A
1470N/A /**
1470N/A * Set the writer that should receive all output
1470N/A *
1470N/A * @param out The new writer to write to
1470N/A */
1470N/A public void setWriter(Writer out) {
974N/A yyline = 1;
974N/A this.out = out;
1470N/A }
0N/A
1470N/A /**
1470N/A * Set the name of the file we are working on (needed if we would like to
1470N/A * generate a list of hits instead of generating html)
1470N/A *
1470N/A * @param filename the name of the file
1470N/A */
1470N/A public void setFilename(String filename) {
1470N/A this.url = filename;
1470N/A hit = new Hit(filename, null, null, false, alt);
1470N/A }
1470N/A
1470N/A /**
1470N/A * Set the list we should create Hit objects for
1470N/A *
1470N/A * @param hits the hits we should add Hit objects
1470N/A */
1470N/A public void setHitList(List<Hit> hits) {
1470N/A this.hits = hits;
1470N/A }
0N/A
0N/A public void setAlt(boolean alt) {
0N/A this.alt = alt;
0N/A }
0N/A
1470N/A /**
1470N/A * Reinitialize the tokenizer with new contents.
1470N/A *
1470N/A * @param buf a char buffer with text to tokenize
1470N/A * @param len the number of characters to use from the char buffer
1470N/A * @param out where to write htmlized results
1470N/A * @param url URI encoded URL prefix to use when generating links
1470N/A * @param tags tag map to use. If {@code null} a new one gets created.
1470N/A */
1470N/A public void reInit(char[] buf, int len, Writer out, String url,
1470N/A TreeMap<Integer, String[]> tags)
1470N/A {
1080N/A reInit(new CharArrayReader(buf, 0, len), out, url, tags);
1470N/A }
0N/A
1470N/A /**
1470N/A * Reinitialize the tokenizer with new contents.
1470N/A *
1470N/A * @param in source of the text to tokenize
1470N/A * @param out where to write htmlized results
1470N/A * @param url URI encoded URL prefix to use when generating links
1470N/A * @param tags tag map to use. If {@code null} a new one gets created.
1470N/A */
1470N/A public void reInit(Reader in, Writer out, String url,
1470N/A TreeMap<Integer, String[]> tags)
1470N/A {
1080N/A yyreset(in);
1080N/A markedContents.setLength(0);
974N/A wait = false;
974N/A dumpRest = false;
974N/A rest = 0;
1470N/A markedPos = 0;
1470N/A curLinePos = 0;
1470N/A matchStart = -1;
1470N/A markedLine = 0;
974N/A yyline = 1;
974N/A this.out = out;
974N/A this.url = url;
974N/A this.tags = tags;
1470N/A if (this.tags == null) {
1470N/A this.tags = new TreeMap<Integer, String[]>();
974N/A }
974N/A prevHi = false;
1470N/A }
0N/A
1470N/A /** Current token could be part of a match. Hold on... */
1470N/A public void holdOn() {
1470N/A if ( !wait) {
1470N/A wait = true;
1470N/A matchStart = markedContents.length() - yylength();
1470N/A }
1470N/A }
1080N/A
1470N/A /** Not a match after all. */
1470N/A public void neverMind() {
974N/A wait = false;
1470N/A if ( !dumpRest) {
1470N/A markedPos = curLinePos;
1470N/A markedLine = yyline;
974N/A }
974N/A matchStart = -1;
1470N/A }
0N/A
1470N/A private int printWithNum(int start, int end, int lineNo, boolean bold)
1470N/A throws IOException
1470N/A {
1390N/A // should be similar to Context::getContext()
1001N/A if (bold) {
1001N/A out.write("<b>");
1001N/A }
1470N/A for (int i = start; i < end; i++ ) {
1470N/A char ch = markedContents.charAt(i);
1470N/A switch (ch) {
974N/A case '\n':
1470N/A ++lineNo;
1470N/A Integer ln = Integer.valueOf(lineNo);
1470N/A boolean hi = tags.containsKey(ln);
1470N/A if (bold) {
1470N/A out.write("</b>");
1470N/A }
1470N/A out.write("</a>");
1470N/A if (prevHi) {
1470N/A out.write(" <span class=\"rshd\"> ");
1470N/A String[] desc = tags.remove(prevLn);
1470N/A out.write(desc[2]);
1470N/A out.write(" </span>");
1470N/A }
1470N/A out.write("<br/>");
1470N/A prevHi = hi;
1470N/A prevLn = ln;
1470N/A if (hi)
1470N/A out.write("<span class=\"rshh\">");
1470N/A // TODO: closing tag - where?
1470N/A out.write("<a class=\"rsh\" href=\"");
1470N/A out.write(url);
1470N/A String num = String.valueOf(lineNo);
1470N/A out.write(num);
1470N/A out.write("\"><span class=\"l\">");
1470N/A out.write(num);
1470N/A out.write("</span> ");
1470N/A if (bold) {
1470N/A out.write("<b>");
1470N/A }
1470N/A break;
974N/A case '<':
1470N/A out.write("&lt;");
1470N/A break;
974N/A case '>':
1470N/A out.write("&gt;");
1470N/A break;
974N/A case '&':
1470N/A out.write("&amp;");
1470N/A break;
974N/A default:
1470N/A out.write(ch);
1470N/A }
974N/A }
1001N/A if (bold) {
1001N/A out.write("</b>");
1001N/A }
974N/A return lineNo;
1470N/A }
0N/A
1470N/A private int formatWithNum(int start, int end, int lineNo) {
1470N/A for (int i = start; i < end; i++ ) {
1470N/A char ch = markedContents.charAt(i);
1470N/A switch (ch) {
974N/A case '\n':
1470N/A ++lineNo;
1470N/A Integer ln = Integer.valueOf(lineNo);
1470N/A boolean hi = tags.containsKey(ln);
1470N/A if (prevHi) {
1470N/A String[] desc = tags.remove(prevLn);
1470N/A hit.setTag(desc[2]);
1470N/A }
1470N/A prevHi = hi;
1470N/A prevLn = ln;
1470N/A sb.append(' ');
1470N/A break;
974N/A case '<':
1470N/A sb.append("&lt;");
1470N/A break;
974N/A case '>':
1470N/A sb.append("&gt;");
1470N/A break;
974N/A case '&':
1470N/A sb.append("&amp;");
1470N/A break;
974N/A default:
1470N/A sb.append(ch);
1470N/A }
974N/A }
974N/A return lineNo;
1470N/A }
0N/A
1470N/A public void printContext() throws IOException {
0N/A if (sb == null) {
0N/A sb = new StringBuilder();
0N/A }
0N/A if (hit == null) {
1470N/A hit = new Hit(url, null, null, false, alt);
0N/A }
974N/A wait = false;
974N/A if (matchStart == -1) {
1470N/A matchStart = markedContents.length() - yylength();
974N/A }
1185N/A if (curLinePos == markedPos) {
1470N/A Integer ln = Integer.valueOf(markedLine);
1470N/A prevHi = tags.containsKey(ln);
1470N/A prevLn = ln;
1470N/A if (prevHi) {
1470N/A prevLn = ln;
1470N/A }
1470N/A if (out != null) {
1470N/A out.write("<a class=\"rsh\" href=\"");
1470N/A out.write(url);
1470N/A String num = String.valueOf(markedLine);
1470N/A out.write(num);
1470N/A out.write("\"><span class=\"l\">");
1470N/A out.write(num);
1470N/A out.write("</span> ");
1470N/A }
974N/A }
0N/A if (out != null) {
1470N/A // print first part of line without normal font
1470N/A markedLine = printWithNum(markedPos, matchStart, markedLine, false);
1470N/A // use bold font for the match
1470N/A markedLine = printWithNum(matchStart, markedContents.length(),
1470N/A markedLine, true);
0N/A } else {
1470N/A markedLine = formatWithNum(markedPos, matchStart, markedLine);
1470N/A hit.setLineno(String.valueOf(markedLine));
1470N/A sb.append("<b>");
1470N/A markedLine =
1470N/A formatWithNum(matchStart, markedContents.length(), markedLine);
1470N/A sb.append("</b>");
0N/A }
1080N/A // Remove everything up to the start of the current line in the
1080N/A // buffered contents.
1080N/A markedContents.delete(0, curLinePos);
1080N/A curLinePos = 0;
1080N/A markedPos = markedContents.length();
974N/A matchStart = -1;
974N/A dumpRest = true;
1080N/A rest = markedPos;
1470N/A }
1470N/A
1470N/A public void dumpRest() throws IOException {
1185N/A if (dumpRest) {
1470N/A final int maxLooks = 100;
1470N/A for (int i = 0;; i++ ) {
1470N/A final boolean endOfBuffer =
1470N/A (i >= markedContents.length() - rest);
1470N/A final boolean newline =
1470N/A !endOfBuffer && markedContents.charAt(rest + i) == '\n';
1470N/A if (endOfBuffer || newline || i >= maxLooks) {
1470N/A if (out != null) {
1470N/A printWithNum(rest, rest + i - 1, markedLine, false);
1470N/A // Assume that this line has been truncated if we don't
1470N/A // find a newline after looking at maxLooks characters,
1470N/A // or if we reach the end of the buffer and the size of
1470N/A // the buffer is Context.MAXFILEREAD (which means that
1470N/A // the file has probably been truncated).
1470N/A if (!newline && ((i >= maxLooks) || (endOfBuffer
1470N/A && (yychar + yylength()) == Context.MAXFILEREAD)))
1470N/A {
1470N/A out.write(" (&hellip;)");
1470N/A }
1470N/A out.write("</a>");
1470N/A if (prevHi) {
1470N/A out.write(" <span class=\"rshd\"> ");
1470N/A String[] desc = tags.remove(prevLn);
1470N/A out.write(desc[2]);
1470N/A out.write(" </span>");
1470N/A }
1470N/A out.write("<br/>");
1470N/A } else {
1470N/A formatWithNum(rest, rest + i - 1, markedLine);
1470N/A hit.setLine(sb.toString());
1470N/A if (prevHi) {
1470N/A String[] desc = tags.remove(prevLn);
1470N/A hit.setTag(desc[2]);
1470N/A }
1470N/A hits.add(hit);
1470N/A }
1470N/A break;
390N/A }
1470N/A }
974N/A }
974N/A if (tags.size() > 0) {
1470N/A if (out != null) {
1470N/A for (Integer rem : tags.keySet()) {
1470N/A String[] desc = tags.get(rem);
1470N/A out.write("<a class=\"rsh\" href=\"");
1470N/A out.write(url);
1470N/A out.write(desc[1]);
1470N/A out.write("\"><span class=\"l\">");
1470N/A out.write(desc[1]);
1470N/A out.write("</span> ");
1470N/A out.write(Util.htmlize(desc[3]).replace(desc[0],
1470N/A "<b>" + desc[0] + "</b>"));
1470N/A out.write("</a> <span class=\"rshd\"> ");
1470N/A out.write(desc[2]);
1470N/A out.write(" </span><br/>");
1470N/A }
1470N/A } else {
1470N/A for (Integer rem : tags.keySet()) {
1470N/A String[] desc = tags.get(rem);
1470N/A hit = new Hit(url, "<html>"
1470N/A + Util.htmlize(desc[3]).replace(desc[0],
1470N/A "<b>" + desc[0] + "</b>"), desc[1], false, alt);
1470N/A hit.setTag(desc[2]);
1470N/A hits.add(hit);
1470N/A }
1470N/A }
0N/A }
1470N/A }
0N/A%}
0N/A
0N/A//WhiteSpace = [ \t\f\r]+|\n
0N/AIdentifier = [a-zA-Z_] [a-zA-Z0-9_]*
0N/ANumber = [0-9]+|[0-9]+\.[0-9]+| "0[xX]" [0-9a-fA-F]+
0N/APrintable = [\@\$\%\^\&\-+=\?\.\:]
0N/A
0N/A
0N/A%%
1080N/A{Identifier}|{Number}|{Printable} {
1470N/A String text = yytext();
1470N/A markedContents.append(text);
1470N/A return text;
1080N/A}
1470N/A<<EOF>> { return null; }
0N/A
974N/A\n {
1470N/A markedContents.append(yycharat(0));
1470N/A if ( !wait) {
1470N/A markedPos = markedContents.length();
1470N/A markedLine = yyline + 1;
1470N/A matchStart = -1;
1470N/A curLinePos = markedPos;
1470N/A }
1470N/A if (dumpRest) {
1470N/A int endPos = markedContents.length() - yylength();
1470N/A if (out != null) {
1470N/A printWithNum(rest, endPos, markedLine, false);
1470N/A out.write("</a>");
1470N/A if (prevHi) {
1470N/A out.write(" <span class=\"rshd\"> ");
1470N/A String[] desc = tags.remove(prevLn);
1470N/A out.write(desc[2]);
1470N/A out.write("</span> ");
1470N/A }
1470N/A out.write("<br/>");
1470N/A } else {
1470N/A formatWithNum(rest, endPos, markedLine);
1470N/A hit.setLine(sb.toString());
1470N/A if (prevHi) {
1470N/A String[] desc = tags.remove(prevLn);
1470N/A hit.setTag(desc[2]);
1470N/A }
1470N/A hits.add(hit);
1470N/A sb.setLength(0);
1470N/A hit = new Hit(url, null, null, false, alt);
974N/A }
1470N/A dumpRest = false;
1470N/A }
1470N/A if ( !wait) {
1470N/A // We have dumped the rest of the line, begun a new
1470N/A // line, and we're not inside a possible match, so it's
1470N/A // safe to forget the buffered contents.
1470N/A markedContents.setLength(0);
1470N/A markedPos = 0;
1470N/A curLinePos = 0;
1470N/A }
974N/A }
0N/A
1080N/A. { markedContents.append(yycharat(0)); }