1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * See LICENSE.txt included in this distribution for the specific 9 * language governing permissions and limitations under the License. 10 * 11 * When distributing Covered Code, include this CDDL HEADER in each 12 * file and include the License file at LICENSE.txt. 13 * If applicable, add the following below this CDDL HEADER, with the 14 * fields enclosed by brackets "[]" replaced with your own identifying 15 * information: Portions Copyright [yyyy] [name of copyright owner] 16 * 17 * CDDL HEADER END 18 */ 19 20 /* 21 * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. 22 * Portions Copyright (c) 2017, Chris Fraire <cfraire@me.com>. 23 */ 24 25 /* 26 * Cross reference a C file 27 */ 28 29 package org.opengrok.indexer.analysis.c; 30 31 import java.io.IOException; 32 import java.util.regex.Matcher; 33 import java.util.regex.Pattern; 34 import org.opengrok.indexer.analysis.JFlexSymbolMatcher; 35 import org.opengrok.indexer.analysis.ScopeAction; 36 import org.opengrok.indexer.util.StringUtils; 37 import org.opengrok.indexer.web.HtmlConsts; 38 %% 39 %public 40 %class CXref 41 %extends JFlexSymbolMatcher 42 %unicode 43 %int 44 %char 45 %include ../CommonLexer.lexh 46 %include ../CommonXref.lexh 47 %{ 48 private static final Pattern MATCH_INCLUDE = Pattern.compile( 49 "^(#.*)(include)(.*)([<\"])(.*)([>\"])$"); 50 private static final int INCL_HASH_G = 1; 51 private static final int INCLUDE_G = 2; 52 private static final int INCL_POST_G = 3; 53 private static final int INCL_PUNC0_G = 4; 54 private static final int INCL_PATH_G = 5; 55 private static final int INCL_PUNCZ_G = 6; 56 57 @Override yypop()58 public void yypop() throws IOException { 59 onDisjointSpanChanged(null, yychar); 60 super.yypop(); 61 } 62 chkLOC()63 protected void chkLOC() { 64 switch (yystate()) { 65 case COMMENT: 66 case SCOMMENT: 67 break; 68 default: 69 phLOC(); 70 break; 71 } 72 } 73 %} 74 75 File = [a-zA-Z]{FNameChar}* "." ([cChHsStT] | [Cc][Oo][Nn][Ff] | 76 [Jj][Aa][Vv][Aa] | [CcHh][Pp][Pp] | [Cc][Cc] | [Tt][Xx][Tt] | 77 [Hh][Tt][Mm][Ll]? | [Pp][Ll] | [Xx][Mm][Ll] | [CcHh][\+][\+] | [Hh][Hh] | 78 [CcHh][Xx][Xx] | [Dd][Ii][Ff][Ff] | [Pp][Aa][Tt][Cc][Hh]) 79 80 %state STRING COMMENT SCOMMENT QSTRING 81 82 %include ../Common.lexh 83 %include ../CommonURI.lexh 84 %include ../CommonPath.lexh 85 %include C.lexh 86 %% 87 <YYINITIAL>{ 88 \{ { chkLOC(); onScopeChanged(ScopeAction.INC, yytext(), yychar); } 89 \} { chkLOC(); onScopeChanged(ScopeAction.DEC, yytext(), yychar); } 90 \; { chkLOC(); onScopeChanged(ScopeAction.END, yytext(), yychar); } 91 92 {Identifier} { 93 chkLOC(); 94 String id = yytext(); 95 onFilteredSymbolMatched(id, yychar, Consts.kwd); 96 } 97 98 "#" {WhspChar}* "include" {WhspChar}* ("<"[^>\n\r]+">" | \"[^\"\n\r]+\") { 99 chkLOC(); 100 String capture = yytext(); 101 Matcher match = MATCH_INCLUDE.matcher(capture); 102 if (match.matches()) { 103 onNonSymbolMatched(match.group(INCL_HASH_G), yychar); 104 onFilteredSymbolMatched(match.group(INCLUDE_G), yychar, Consts.kwd); 105 onNonSymbolMatched(match.group(INCL_POST_G), yychar); 106 onNonSymbolMatched(match.group(INCL_PUNC0_G), yychar); 107 String path = match.group(INCL_PATH_G); 108 onPathlikeMatched(path, '/', false, yychar); 109 onNonSymbolMatched(match.group(INCL_PUNCZ_G), yychar); 110 } else { 111 onNonSymbolMatched(capture, yychar); 112 } 113 } 114 115 /*{Hier} 116 { onPathlikeMatched(yytext(), '.', false, yychar); } 117 */ 118 {Number} { 119 chkLOC(); 120 onDisjointSpanChanged(HtmlConsts.NUMBER_CLASS, yychar); 121 onNonSymbolMatched(yytext(), yychar); 122 onDisjointSpanChanged(null, yychar); 123 } 124 125 \\[\"\'] { chkLOC(); onNonSymbolMatched(yytext(), yychar); } 126 \" { 127 chkLOC(); 128 yypush(STRING); 129 onDisjointSpanChanged(HtmlConsts.STRING_CLASS, yychar); 130 onNonSymbolMatched(yytext(), yychar); 131 } 132 \' { 133 chkLOC(); 134 yypush(QSTRING); 135 onDisjointSpanChanged(HtmlConsts.STRING_CLASS, yychar); 136 onNonSymbolMatched(yytext(), yychar); 137 } 138 "/*" { 139 yypush(COMMENT); 140 onDisjointSpanChanged(HtmlConsts.COMMENT_CLASS, yychar); 141 onNonSymbolMatched(yytext(), yychar); 142 } 143 "//" { 144 yypush(SCOMMENT); 145 onDisjointSpanChanged(HtmlConsts.COMMENT_CLASS, yychar); 146 onNonSymbolMatched(yytext(), yychar); 147 } 148 } 149 150 <STRING> { 151 \\[\"\\] | 152 \" {WhspChar}+ \" { chkLOC(); onNonSymbolMatched(yytext(), yychar); } 153 \" { chkLOC(); onNonSymbolMatched(yytext(), yychar); yypop(); } 154 } 155 156 <QSTRING> { 157 \\[\'\\] | 158 \' {WhspChar}+ \' { chkLOC(); onNonSymbolMatched(yytext(), yychar); } 159 \' { chkLOC(); onNonSymbolMatched(yytext(), yychar); yypop(); } 160 } 161 162 <COMMENT> { 163 "*/" { onNonSymbolMatched(yytext(), yychar); yypop(); } 164 } 165 166 <SCOMMENT> { 167 {WhspChar}*{EOL} { 168 yypop(); 169 onEndOfLineMatched(yytext(), yychar);} 170 } 171 172 173 <YYINITIAL, STRING, COMMENT, SCOMMENT, QSTRING> { 174 {WhspChar}*{EOL} { onEndOfLineMatched(yytext(), yychar); } 175 [[\s]--[\n]] { onNonSymbolMatched(yytext(), yychar); } 176 [^\n] { chkLOC(); onNonSymbolMatched(yytext(), yychar); } 177 } 178 179 <STRING, COMMENT, SCOMMENT, QSTRING> { 180 {FPath} { 181 chkLOC(); 182 onPathlikeMatched(yytext(), '/', false, yychar); 183 } 184 185 {File} 186 { 187 chkLOC(); 188 String path = yytext(); 189 onFilelikeMatched(path, yychar); 190 } 191 192 {FNameChar}+ "@" {FNameChar}+ "." {FNameChar}+ 193 { 194 chkLOC(); 195 onEmailAddressMatched(yytext(), yychar); 196 } 197 } 198 199 <STRING, SCOMMENT> { 200 {BrowseableURI} { 201 chkLOC(); 202 onUriMatched(yytext(), yychar); 203 } 204 } 205 206 <COMMENT> { 207 {BrowseableURI} { 208 onUriMatched(yytext(), yychar, StringUtils.END_C_COMMENT); 209 } 210 } 211 212 <QSTRING> { 213 {BrowseableURI} { 214 chkLOC(); 215 onUriMatched(yytext(), yychar, StringUtils.APOS_NO_BSESC); 216 } 217 } 218