1153N/A/*
1153N/A * CDDL HEADER START
1153N/A *
1153N/A * The contents of this file are subject to the terms of the
1153N/A * Common Development and Distribution License (the "License").
1153N/A * You may not use this file except in compliance with the License.
1153N/A *
1153N/A * See LICENSE.txt included in this distribution for the specific
1153N/A * language governing permissions and limitations under the License.
1153N/A *
1153N/A * When distributing Covered Code, include this CDDL HEADER in each
1153N/A * file and include the License file at LICENSE.txt.
1153N/A * If applicable, add the following below this CDDL HEADER, with the
1153N/A * fields enclosed by brackets "[]" replaced with your own identifying
1153N/A * information: Portions Copyright [yyyy] [name of copyright owner]
1153N/A *
1153N/A * CDDL HEADER END
1153N/A */
1153N/A
1153N/A/*
1439N/A * Cross reference a PHP file
1153N/A */
1153N/A
1153N/Apackage org.opensolaris.opengrok.analysis.php;
1461N/A
1153N/Aimport java.io.IOException;
1461N/Aimport java.util.ArrayDeque;
1461N/Aimport java.util.Arrays;
1461N/Aimport java.util.HashSet;
1461N/Aimport java.util.Set;
1461N/A
1461N/Aimport org.opensolaris.opengrok.analysis.JFlexXref;
1153N/Aimport org.opensolaris.opengrok.web.Util;
1153N/A
1153N/A%%
1153N/A%public
1153N/A%class PhpXref
1153N/A%extends JFlexXref
1153N/A%unicode
1153N/A%ignorecase
1153N/A%int
1153N/A%{
1442N/A private final static Set<String> PSEUDO_TYPES;
1461N/A private ArrayDeque<String> docLabels = new ArrayDeque<String>();
1153N/A // TODO move this into an include file when bug #16053 is fixed
1153N/A @Override
1153N/A protected int getLineNumber() { return yyline; }
1153N/A @Override
1153N/A protected void setLineNumber(int x) { yyline = x; }
1442N/A
1442N/A static {
1442N/A PSEUDO_TYPES = new HashSet<String>(Arrays.asList(
1442N/A new String[] {
1443N/A "string", "integer", "int", "boolean", "bool", "float", "double",
1461N/A "object", "mixed", "array", "resource", "void", "NULL", "callback",
1461N/A "FALSE", "TRUE", "self", "callable"
1442N/A }
1442N/A ));
1442N/A }
1443N/A
1443N/A private void writeDocTag() throws IOException {
1443N/A out.write(yycharat(0));
1443N/A out.write("<strong>");
1443N/A out.write(Util.htmlize(yytext().substring(1)));
1443N/A out.write("</strong>");
1443N/A }
1443N/A
1443N/A private boolean isTabOrSpace(int i) {
1443N/A return yycharat(i) == '\t' || yycharat(i) == ' ';
1443N/A }
1451N/A
1451N/A private static boolean isHtmlState(int state) {
1451N/A return state == TAG_NAME || state == AFTER_TAG_NAME
1451N/A || state == ATTRIBUTE_NOQUOTE || state == ATTRIBUTE_SINGLE
1451N/A || state == ATTRIBUTE_DOUBLE || state == HTMLCOMMENT
1451N/A || state == YYINITIAL;
1451N/A }
1153N/A%}
1153N/A
1439N/AWhiteSpace = [ \t]+
1153N/AEOL = \r|\n|\r\n
1439N/AIdentifier = [a-zA-Z_\u007F-\u10FFFF] [a-zA-Z0-9_\u007F-\u10FFFF]*
1153N/A
1153N/AURIChar = [\?\+\%\&\:\/\.\@\_\;\=\$\,\-\!\~\*\\]
1153N/AFNameChar = [a-zA-Z0-9_\-\.]
1153N/AFile = [a-zA-Z]{FNameChar}* "." ("php"|"php3"|"php4"|"phps"|"phtml"|"inc"|"diff"|"patch")
1153N/APath = "/"? [a-zA-Z]{FNameChar}* ("/" [a-zA-Z]{FNameChar}*[a-zA-Z0-9])+
1153N/A
1439N/ABinaryNumber = 0[b|B][01]+
1439N/AOctalNumber = 0[0-7]+
1439N/ADecimalNumber = [1-9][0-9]+
1439N/AHexadecimalNumber = 0[xX][0-9a-fA-F]+
1439N/AFloatNumber = (([0-9]* "." [0-9]+) | ([0-9]+ "." [0-9]*) | [0-9]+)([eE][+-]?[0-9]+)?
1439N/ANumber = [+-]?({BinaryNumber}|{OctalNumber}|{DecimalNumber}|{HexadecimalNumber}|{FloatNumber})
1153N/A
1451N/A//do not support <script language="php"> and </script> opening/closing tags
1439N/AOpeningTag = ("<?" "php"?) | "<?="
1439N/AClosingTag = "?>"
1153N/A
1443N/ACastTypes = "int"|"integer"|"real"|"double"|"float"|"string"|"binary"|"array"
1443N/A |"object"|"bool"|"boolean"|"unset"
1443N/A
1445N/ADoubleQuoteEscapeSequences = \\ (([nrtfve\\$]) | ([xX] [0-9a-fA-F]{1,2}) | ([0-7]{1,3}))
1441N/ASingleQuoteEscapeSequences = \\ [\\\']
1441N/A
1443N/ADocPreviousChar = "*" | {WhiteSpace}
1443N/A
1443N/A//does not supported nested type expressions like ((array|integer)[]|boolean)[]
1443N/A//that would require additional states
1443N/ADocType = {IndividualDocType} (\| {IndividualDocType})*
1443N/AIndividualDocType = ({SimpleDocType} "[]"? | ( \( {SimpleDocType} "[]"? ( \| {SimpleDocType} "[]"? )* \)\[\] ))
1443N/ASimpleDocType = {Identifier}
1443N/A
1443N/ADocParamWithType = "return" | "throws" | "throw" | "var" | "see" //"see" can take a URL
1443N/ADocParamWithTypeAndName = "param" | "global" | "property" | "property-read"
1443N/A | "property-write"
1453N/ADocParamWithName = "uses"
1443N/ADocInlineTags = "internal" | "inheritDoc" | "link" | "example"
1443N/A//method needs special treatment
1442N/A
1454N/AHtmlNameStart = [a-zA-Z_\u00C0-\u10FFFFFF]
1439N/AHtmlName = {HtmlNameStart} ({HtmlNameStart} | [\-.0-9\u00B7])*
1439N/A
1443N/A%state TAG_NAME AFTER_TAG_NAME ATTRIBUTE_NOQUOTE ATTRIBUTE_SINGLE ATTRIBUTE_DOUBLE HTMLCOMMENT
1445N/A%state IN_SCRIPT STRING SCOMMENT HEREDOC NOWDOC COMMENT QSTRING BACKQUOTE STRINGEXPR STRINGVAR
1443N/A%state DOCCOMMENT DOCCOM_TYPE_THEN_NAME DOCCOM_NAME DOCCOM_TYPE
1153N/A
1153N/A%%
1439N/A<YYINITIAL> { //HTML
1461N/A "<" | "</" { out.write(Util.htmlize(yytext())); yypush(TAG_NAME, ""); }
1451N/A
1443N/A "<!--" {
1461N/A out.write("<span class=\"c\">&lt;!--"); spans.push("c");
1443N/A yybegin(HTMLCOMMENT);
1443N/A }
1439N/A}
1153N/A
1439N/A<TAG_NAME> {
1439N/A {HtmlName} {
1454N/A out.write("<span class=\"n\">");
1441N/A out.write(yytext());
1439N/A out.write("</span>");
1439N/A yybegin(AFTER_TAG_NAME);
1439N/A }
1454N/A
1454N/A {HtmlName}:{HtmlName} {
1454N/A out.write("<span class=\"n\">");
1454N/A int i = 0;
1454N/A while (yycharat(i) != ':') i++;
1454N/A out.write(yytext().substring(0,i));
1454N/A out.write("</span>:<span class=\"n\">");
1454N/A out.write(yytext().substring(i + 1));
1454N/A out.write("</span>");
1454N/A yybegin(AFTER_TAG_NAME);
1454N/A }
1153N/A}
1153N/A
1439N/A<AFTER_TAG_NAME> {
1439N/A {HtmlName} {
1454N/A out.write("<strong>");
1441N/A out.write(yytext()); //attribute
1454N/A out.write("</strong>");
1439N/A }
1439N/A
1439N/A "=" {WhiteSpace}* (\" | \')? {
1439N/A char attributeDelim = yycharat(yylength()-1);
1461N/A out.write("=<span class=\"s\">"); spans.push("s");
1439N/A out.write(yytext().substring(1));
1439N/A if (attributeDelim == '\'') {
1461N/A yypush(ATTRIBUTE_SINGLE, "");
1439N/A } else if (attributeDelim == '"') {
1461N/A yypush(ATTRIBUTE_DOUBLE, "");
1439N/A } else {
1461N/A yypush(ATTRIBUTE_NOQUOTE, "");
1439N/A }
1439N/A }
1439N/A}
1439N/A
1439N/A<TAG_NAME, AFTER_TAG_NAME> {
1439N/A ">" { out.write("&gt;"); yypop(); } //to YYINITIAL
1439N/A}
1439N/A
1439N/A<YYINITIAL, TAG_NAME, AFTER_TAG_NAME> {
1454N/A {OpeningTag} {
1454N/A out.write("<strong>");
1454N/A out.write(Util.htmlize(yytext()));
1454N/A out.write("</strong>");
1461N/A yypush(IN_SCRIPT, ""); }
1439N/A}
1439N/A
1439N/A<ATTRIBUTE_NOQUOTE> {
1439N/A {WhiteSpace}* {EOL} {
1461N/A out.write("</span>"); spans.pop();
1439N/A startNewLine();
1439N/A yypop();
1439N/A }
1439N/A {WhiteSpace} {
1439N/A out.write(yytext());
1461N/A out.write("</span>"); spans.pop();
1439N/A yypop();
1439N/A }
1461N/A ">" { out.write("&gt;</span>"); spans.pop(); yypop(); yypop(); } //pop twice
1153N/A}
1153N/A
1461N/A<ATTRIBUTE_DOUBLE>\" { out.write("\"</span>"); spans.pop(); yypop(); }
1461N/A<ATTRIBUTE_SINGLE>\' { out.write("'</span>"); spans.pop(); yypop(); }
1439N/A
1439N/A<ATTRIBUTE_DOUBLE, ATTRIBUTE_SINGLE> {
1439N/A {WhiteSpace}* {EOL} {
1461N/A out.write("</span>"); spans.pop();
1439N/A startNewLine();
1461N/A out.write("<span class=\"s\">"); spans.push("s");
1439N/A }
1439N/A}
1439N/A
1439N/A<ATTRIBUTE_NOQUOTE, ATTRIBUTE_DOUBLE, ATTRIBUTE_SINGLE> {
1439N/A {OpeningTag} {
1461N/A out.write("</span><strong>"); spans.pop();
1439N/A out.write(Util.htmlize(yytext()));
1454N/A out.write("</strong>");
1461N/A yypush(IN_SCRIPT, "<span class=\"s\">"); spans.push("s");
1439N/A }
1153N/A}
1153N/A
1443N/A<HTMLCOMMENT> {
1443N/A "-->" {
1461N/A out.write("--&gt;</span>"); spans.pop();
1443N/A yybegin(YYINITIAL);
1443N/A }
1443N/A
1443N/A {WhiteSpace}* {EOL} {
1461N/A out.write("</span>"); spans.pop();
1443N/A startNewLine();
1461N/A out.write("<span class=\"c\">"); spans.push("c");
1443N/A }
1443N/A
1443N/A {OpeningTag} {
1461N/A out.write("</span><strong>"); spans.pop();
1443N/A out.write(Util.htmlize(yytext()));
1454N/A out.write("</strong>");
1461N/A yypush(IN_SCRIPT, "<span class=\"c\">"); spans.push("c");
1443N/A }
1443N/A}
1443N/A
1439N/A<IN_SCRIPT> {
1439N/A "$" {Identifier} {
1439N/A //we ignore keywords if the identifier starts with one of variable chars
1439N/A String id = yytext().substring(1);
1439N/A out.write("$");
1469N/A writeSymbol(id, null, yyline, false);
1439N/A }
1153N/A
1439N/A {Identifier} {
1469N/A writeSymbol(yytext(), Consts.kwd, yyline, false);
1439N/A }
1439N/A
1443N/A \( {WhiteSpace}* {CastTypes} {WhiteSpace}* \) {
1443N/A out.write("(");
1443N/A int i = 1, j;
1443N/A while (isTabOrSpace(i)) { out.write(yycharat(i++)); }
1443N/A
1443N/A out.write("<em>");
1443N/A j = i + 1;
1443N/A while (!isTabOrSpace(j) && yycharat(j) != ')') { j++; }
1443N/A out.write(yytext().substring(i, j));
1443N/A out.write("</em>");
1451N/A
1443N/A out.write(yytext().substring(j, yylength()));
1443N/A }
1443N/A
1444N/A b? \" {
1461N/A yypush(STRING, "");
1444N/A if (yycharat(0) == 'b') { out.write('b'); }
1461N/A out.write("<span class=\"s\">\""); spans.push("s");
1444N/A }
1439N/A
1444N/A b? \' {
1461N/A yypush(QSTRING, "");
1444N/A if (yycharat(0) == 'b') { out.write('b'); }
1461N/A out.write("<span class=\"s\">\'"); spans.push("s");
1444N/A }
1444N/A
1461N/A ` { yypush(BACKQUOTE, ""); out.write("<span class=\"s\">`"); spans.push("s"); }
1445N/A
1444N/A b? "<<<" {WhiteSpace}* ({Identifier} | (\'{Identifier}\') | (\"{Identifier}\")){EOL} {
1444N/A if (yycharat(0) == 'b') { out.write('b'); }
1440N/A out.write("&lt;&lt;&lt;");
1444N/A int i = yycharat(0) == 'b' ? 4 : 3, j = yylength()-1;
1443N/A while (isTabOrSpace(i)) {
1440N/A out.write(yycharat(i++));
1439N/A }
1439N/A while (yycharat(j) == '\n' || yycharat(j) == '\r') { j--; }
1153N/A
1439N/A if (yycharat(i) == '\'' || yycharat(i) == '"') {
1461N/A yypush(NOWDOC, "");
1439N/A String text = yytext().substring(i+1, j);
1461N/A docLabels.push(text);
1439N/A out.write(yycharat(i));
1439N/A out.write("<span class=\"b\">");
1439N/A out.write(text);
1439N/A out.write("</span>");
1439N/A out.write(yycharat(i));
1439N/A } else {
1461N/A yypush(HEREDOC, "");
1440N/A String text = yytext().substring(i, j+1);
1461N/A docLabels.push(text);
1439N/A out.write("<span class=\"b\">");
1439N/A out.write(text);
1439N/A out.write("</span>");
1439N/A }
1440N/A startNewLine();
1461N/A out.write("<span class=\"s\">"); spans.push("s");
1439N/A }
1439N/A
1439N/A {Number} { out.write("<span class=\"n\">"); out.write(yytext()); out.write("</span>"); }
1439N/A
1461N/A "#"|"//" { yypush(SCOMMENT, ""); out.write("<span class=\"c\">" + yytext()); spans.push("c"); }
1461N/A "/**" { yypush(DOCCOMMENT, ""); out.write("<span class=\"c\">/*"); yypushback(1); spans.push("c"); }
1461N/A "/*" { yypush(COMMENT, ""); out.write("<span class=\"c\">/*"); spans.push("c"); }
1439N/A
1461N/A \{ { out.write(yytext()); yypush(IN_SCRIPT, ""); }
1451N/A \} {
1451N/A out.write(yytext());
1461N/A if (!stateStack.isEmpty() && !isHtmlState(stateStack.peek()))
1451N/A yypop(); //may pop STRINGEXPR/HEREDOC/BACKQUOTE
1451N/A /* we don't pop unconditionally because we can exit a <?php block with
1451N/A * with open braces and we discard the information about the number of
1451N/A * open braces when exiting the block (see the action for {ClosingTag}
1451N/A * below. An alternative would be keeping two stacks -- one for HTML
1451N/A * and another for PHP. The PHP scanner only needs one stack because
1451N/A * it doesn't need to keep state about the HTML */
1451N/A }
1439N/A
1451N/A {ClosingTag} {
1454N/A out.write("<strong>");
1451N/A out.write(Util.htmlize(yytext()));
1454N/A out.write("</strong>");
1451N/A while (!isHtmlState(yystate()))
1451N/A yypop();
1451N/A }
1439N/A} //end of IN_SCRIPT
1153N/A
1445N/A<STRING> {
1445N/A \\\" { out.write("<strong>"); out.write(yytext()); out.write("</strong>"); }
1461N/A \" { out.write("\"</span>"); spans.pop(); yypop(); }
1445N/A}
1440N/A
1445N/A<BACKQUOTE> {
1445N/A "\\`" { out.write("<strong>"); out.write(yytext()); out.write("</strong>"); }
1461N/A "`" { out.write("`</span>"); spans.pop(); yypop(); }
1445N/A}
1445N/A
1445N/A<STRING, BACKQUOTE, HEREDOC> {
1441N/A "\\{" {
1439N/A out.write(yytext());
1439N/A }
1439N/A
1441N/A {DoubleQuoteEscapeSequences} {
1441N/A out.write("<strong>");
1441N/A out.write(yytext());
1441N/A out.write("</strong>");
1441N/A }
1441N/A
1439N/A "$" {
1461N/A out.write("</span>$"); spans.pop();
1461N/A yypush(STRINGVAR, "<span class=\"s\">"); spans.push("s");
1439N/A }
1439N/A
1441N/A "${" {
1461N/A out.write("</span>"); spans.pop();
1439N/A out.write(yytext());
1461N/A yypush(STRINGEXPR, "<span class=\"s\">"); spans.push("s");
1439N/A }
1441N/A
1441N/A /* ${ is different from {$ -- for instance {$foo->bar[1]} is valid
1446N/A * but ${foo->bar[1]} is not. ${ only enters the full blown scripting state
1446N/A * when {Identifer}[ is found (see the PHP scanner). Tthe parser seems to
1446N/A * put more restrictions on the {$ scripting mode than on the
1446N/A * "${" {Identifer} "[" scripting mode, but that's not relevant here */
1441N/A "{$" {
1461N/A out.write("</span>"); spans.pop();
1441N/A out.write("{");
1441N/A yypushback(1);
1461N/A yypush(IN_SCRIPT, "<span class=\"s\">"); spans.push("s");
1441N/A }
1153N/A}
1153N/A
1153N/A<QSTRING> {
1441N/A {SingleQuoteEscapeSequences} {
1441N/A out.write("<strong>");
1439N/A out.write(yytext());
1441N/A out.write("</strong>");
1439N/A }
1441N/A
1461N/A \' { out.write("\"</span>"); spans.pop(); yypop(); }
1439N/A}
1439N/A
1441N/A<HEREDOC, NOWDOC>^{Identifier} ";"? {EOL} {
1439N/A int i = yylength() - 1;
1441N/A boolean hasSemi = false;
1439N/A while (yycharat(i) == '\n' || yycharat(i) == '\r') { i--; }
1441N/A if (yycharat(i) == ';') { hasSemi = true; i--; }
1461N/A if (yytext().substring(0, i+1).equals(docLabels.peek())) {
1461N/A String text = docLabels.pop();
1439N/A yypop();
1461N/A out.write("</span><span class=\"b\">"); spans.pop();
1439N/A out.write(text);
1441N/A out.write("</span>");
1441N/A if (hasSemi) out.write(";");
1440N/A startNewLine();
1440N/A } else {
1441N/A out.write(yytext().substring(0,i+1));
1441N/A if (hasSemi) out.write(";");
1439N/A startNewLine();
1439N/A }
1439N/A}
1439N/A
1445N/A<STRING, QSTRING, BACKQUOTE, HEREDOC, NOWDOC>{WhiteSpace}* {EOL} {
1461N/A out.write("</span>"); spans.pop();
1440N/A startNewLine();
1461N/A out.write("<span class=\"s\">"); spans.push("s");
1440N/A}
1440N/A
1439N/A<STRINGVAR> {
1469N/A {Identifier} { writeSymbol(yytext(), null, yyline, false); }
1439N/A
1439N/A \[ {Number} \] {
1439N/A out.write("[<span class=\"n\">");
1439N/A out.write(yytext().substring(1, yylength()-1));
1439N/A out.write("</span>]");
1439N/A yypop(); //because "$arr[0][1]" is the same as $arr[0] . "[1]"
1439N/A }
1439N/A
1439N/A \[ {Identifier} \] {
1439N/A //then the identifier is actually a string!
1439N/A out.write("[<span class=\"s\">");
1439N/A out.write(yytext().substring(1, yylength()-1));
1439N/A out.write("</span>]");
1439N/A yypop();
1439N/A }
1439N/A
1439N/A \[ "$" {Identifier} \] {
1439N/A out.write("[$");
1469N/A writeSymbol(yytext().substring(2, yylength()-1), null, yyline, false);
1439N/A out.write("]");
1439N/A yypop();
1439N/A }
1439N/A
1439N/A "->" {Identifier} {
1439N/A out.write("-&gt;");
1469N/A writeSymbol(yytext().substring(2), null, yyline, false);
1439N/A yypop(); //because "$arr->a[0]" is the same as $arr->a . "[0]"
1439N/A }
1439N/A
1439N/A . | \n { yypushback(1); yypop(); }
1439N/A}
1439N/A
1439N/A<STRINGEXPR> {
1439N/A {Identifier} {
1469N/A writeSymbol(yytext(), null, yyline, false);
1439N/A }
1439N/A \} { out.write('}'); yypop(); }
1441N/A \[ { out.write('['); yybegin(IN_SCRIPT); } /* don't push. when we find '}'
1441N/A * and we pop we want to go to
1441N/A * STRING/HEREDOC, not back to
1441N/A * STRINGEXPR */
1153N/A}
1153N/A
1153N/A<SCOMMENT> {
1439N/A {ClosingTag} {
1461N/A out.write("</span><strong>"); spans.pop();
1439N/A out.write(Util.htmlize(yytext()));
1454N/A out.write("</strong>");
1451N/A while (!isHtmlState(yystate()))
1451N/A yypop();
1439N/A }
1439N/A {WhiteSpace}* {EOL} {
1461N/A out.write("</span>"); spans.pop();
1439N/A startNewLine();
1439N/A yypop();
1439N/A }
1153N/A}
1153N/A
1442N/A<DOCCOMMENT> {
1443N/A {DocPreviousChar} "@" {DocParamWithType} {
1443N/A writeDocTag(); yybegin(DOCCOM_TYPE);
1443N/A }
1443N/A
1443N/A {DocPreviousChar} "@" {DocParamWithTypeAndName} {
1443N/A writeDocTag(); yybegin(DOCCOM_TYPE_THEN_NAME);
1443N/A }
1442N/A
1453N/A {DocPreviousChar} "@" {DocParamWithName} {
1453N/A writeDocTag(); yybegin(DOCCOM_NAME);
1453N/A }
1453N/A
1443N/A ("{@" {DocInlineTags}) | {DocPreviousChar} "@" {Identifier} {
1443N/A writeDocTag();
1443N/A }
1443N/A}
1442N/A
1443N/A<DOCCOM_TYPE_THEN_NAME, DOCCOM_TYPE> {
1443N/A {WhiteSpace}+ {DocType} {
1443N/A int i = 0;
1443N/A do { out.write(yycharat(i++)); } while (isTabOrSpace(i));
1442N/A int j = i;
1442N/A while (i < yylength()) {
1443N/A //skip over [], |, ( and )
1443N/A char c;
1443N/A while (i < yylength() && ((c = yycharat(i)) == '[' || c == ']'
1443N/A || c == '|' || c == '(' || c == ')')) {
1442N/A out.write(c);
1442N/A i++;
1442N/A }
1442N/A j = i;
1443N/A while (j < yylength() && (c = yycharat(j)) != ')' && c != '|'
1443N/A && c != '[') { j++; }
1442N/A out.write("<em>");
1469N/A writeSymbol(yytext().substring(i, j), PSEUDO_TYPES, yyline, true);
1442N/A out.write("</em>");
1442N/A i = j;
1442N/A }
1443N/A yybegin(yystate() == DOCCOM_TYPE_THEN_NAME ? DOCCOM_NAME : DOCCOMMENT);
1442N/A }
1442N/A
1443N/A .|\n { yybegin(DOCCOMMENT); yypushback(1); }
1443N/A}
1443N/A
1443N/A<DOCCOM_NAME> {
1443N/A {WhiteSpace}+ "$" {Identifier} {
1443N/A int i = 0;
1443N/A do { out.write(yycharat(i++)); } while (isTabOrSpace(i));
1443N/A
1442N/A out.write("<em>$");
1469N/A writeSymbol(yytext().substring(i + 1), null, yyline, false);
1442N/A out.write("</em>");
1443N/A yybegin(DOCCOMMENT);
1442N/A }
1442N/A
1443N/A .|\n { yybegin(DOCCOMMENT); yypushback(1); }
1442N/A}
1442N/A
1442N/A<COMMENT, DOCCOMMENT> {
1442N/A {WhiteSpace}* {EOL} {
1461N/A out.write("</span>"); spans.pop();
1442N/A startNewLine();
1461N/A out.write("<span class=\"c\">"); spans.push("c");
1442N/A }
1461N/A "*/" { out.write("*/</span>"); spans.pop(); yypop(); }
1153N/A}
1153N/A
1445N/A<YYINITIAL, TAG_NAME, AFTER_TAG_NAME, ATTRIBUTE_NOQUOTE, ATTRIBUTE_DOUBLE, ATTRIBUTE_SINGLE, HTMLCOMMENT, IN_SCRIPT, STRING, QSTRING, BACKQUOTE, HEREDOC, NOWDOC, SCOMMENT, COMMENT, DOCCOMMENT, STRINGEXPR, STRINGVAR> {
1439N/A "&" { out.write( "&amp;"); }
1439N/A "<" { out.write( "&lt;"); }
1439N/A ">" { out.write( "&gt;"); }
1439N/A {WhiteSpace}* {EOL} {
1439N/A startNewLine();
1439N/A }
1439N/A {WhiteSpace} {
1439N/A out.write(yytext());
1439N/A }
1439N/A [!-~] { out.write(yycharat(0)); }
1439N/A . { writeUnicodeChar(yycharat(0)); }
1439N/A}
1439N/A
1445N/A<YYINITIAL, HTMLCOMMENT, SCOMMENT, COMMENT, DOCCOMMENT, STRING, QSTRING, BACKQUOTE, HEREDOC, NOWDOC> {
1439N/A {Path}
1439N/A { out.write(Util.breadcrumbPath(urlPrefix+"path=",yytext(),'/'));}
1153N/A
1439N/A {File}
1439N/A {
1439N/A String path = yytext();
1439N/A out.write("<a href=\""+urlPrefix+"path=");
1439N/A out.write(path);
1439N/A appendProject();
1439N/A out.write("\">");
1439N/A out.write(path);
1439N/A out.write("</a>");}
1153N/A
1439N/A ("http" | "https" | "ftp" ) "://" ({FNameChar}|{URIChar})+[a-zA-Z0-9/]
1439N/A {
1439N/A String url = yytext();
1439N/A out.write("<a href=\"");
1472N/A out.write(Util.uriEncodeURL(url));out.write("\">");
1469N/A out.write(Util.htmlize(url));out.write("</a>");}
1153N/A
1439N/A {FNameChar}+ "@" {FNameChar}+ "." {FNameChar}+
1439N/A {
1439N/A writeEMailAddress(yytext());
1439N/A }
1153N/A}