1 11 package org.eclipse.jdi.internal; 12 13 import com.ibm.icu.text.MessageFormat; 14 import java.util.ArrayList ; 15 import java.util.List ; 16 17 import com.sun.jdi.AbsentInformationException; 18 19 22 public class SourceDebugExtensionParser { 23 24 private static class Lexer { 25 26 static final int UNKNOWN= 0; 27 static final int SMAP= 1; 28 static final int NON_ASTERISK_STRING= 2; 29 static final int NUMBER= 3; 30 static final int CR= 4; 31 static final int ASTERISK_CHAR= 5; 32 static final int ASTERISK_C= 6; 33 static final int ASTERISK_E= 7; 34 static final int ASTERISK_F= 8; 35 static final int ASTERISK_L= 9; 36 static final int ASTERISK_O= 10; 37 static final int ASTERISK_S= 11; 38 static final int ASTERISK_V= 12; 39 static final int WHITE_SPACE= 13; 40 static final int COLON= 14; 41 static final int COMMA= 15; 42 static final int SHARP= 16; 43 static final int PLUS= 17; 44 45 private char[] fSmap; 46 private int fPointer; 47 private char fChar; 48 49 private char[] fLexem; 50 private int fLexemType; 51 52 private boolean fEOF; 53 54 public Lexer (String smap) { 55 fSmap= smap.toCharArray(); 56 fLexemType= UNKNOWN; 57 fPointer= -1; 58 nextChar(); 59 } 60 61 66 public int nextLexem() throws AbsentInformationException { 67 if (fEOF) { 68 throw new AbsentInformationException(JDIMessages.SourceDebugExtensionParser_0); 69 } 70 startWith(); 71 return fLexemType; 72 } 73 74 75 private char nextChar() { 76 if (++fPointer == fSmap.length) { 77 fEOF= true; 78 return '\000'; 79 } 80 fChar= fSmap[fPointer]; 81 return fChar; 82 } 83 84 private void startWith() throws AbsentInformationException { 85 switch (fChar) { 86 case '\n': 87 case '\r': 88 startWithCR(); 89 break; 90 case '*': 91 startWithAsterisk(); 92 break; 93 case ':': 94 fLexem= new char[] {':'}; 95 fLexemType= COLON; 96 nextChar(); 97 break; 98 case ',': 99 fLexem= new char[] {','}; 100 fLexemType= COMMA; 101 nextChar(); 102 break; 103 case '#': 104 fLexem= new char[] {'#'}; 105 fLexemType= SHARP; 106 nextChar(); 107 break; 108 case '+': 109 fLexem= new char[] {'+'}; 110 fLexemType= PLUS; 111 nextChar(); 112 break; 113 default: 114 startWithOtherChar(); 115 break; 116 } 117 } 118 119 122 private void startWithOtherChar() { 123 int lexemStart= fPointer; 124 consumeWhiteSpace(); 125 if (fChar >= '0' && fChar <= '9') { number(lexemStart); 127 } else { 128 nonAsteriskString(lexemStart); 129 } 130 } 131 132 135 private void nonAsteriskString(int lexemStart) { 136 while (fChar != '\n' && fChar != '\r' && !fEOF) { 137 nextChar(); 138 } 139 int length= fPointer - lexemStart; 140 fLexem= new char[length]; 141 System.arraycopy(fSmap, lexemStart, fLexem, 0, length); 142 if (length == 4 && fLexem[0] == 'S' && fLexem[1] == 'M' && fLexem[2] == 'A' && fLexem[3] == 'P') { 143 fLexemType= SMAP; 144 } else { 145 fLexemType= NON_ASTERISK_STRING; 146 } 147 } 148 149 152 private void number(int lexemStart) { 153 while (fChar >= '0' && fChar <= '9') { 154 nextChar(); 155 } 156 consumeWhiteSpace(); 157 fLexemType= NUMBER; 158 int length= fPointer - lexemStart; 159 fLexem= new char[length]; 160 System.arraycopy(fSmap, lexemStart, fLexem, 0, length); 161 } 162 163 166 private void startWithAsterisk() throws AbsentInformationException { 167 nextChar(); 168 if (fEOF) { 169 throw new AbsentInformationException(JDIMessages.SourceDebugExtensionParser_0); 170 } 171 switch (fChar) { 172 case 'C': 173 fLexemType= ASTERISK_C; 174 break; 175 case 'E': 176 fLexemType= ASTERISK_E; 177 break; 178 case 'F': 179 fLexemType= ASTERISK_F; 180 break; 181 case 'L': 182 fLexemType= ASTERISK_L; 183 break; 184 case 'O': 185 fLexemType= ASTERISK_O; 186 break; 187 case 'S': 188 fLexemType= ASTERISK_S; 189 break; 190 case 'V': 191 fLexemType= ASTERISK_V; 192 break; 193 default: 194 fLexemType= ASTERISK_CHAR; 195 break; 196 } 197 fLexem= new char[] {'*', fChar}; 198 nextChar(); 199 } 200 201 204 private void startWithCR() { 205 if (fChar == '\r') { 206 if (nextChar() == '\n') { 207 fLexem= new char[] {'\r', '\n'}; 208 nextChar(); 209 } else { 210 fLexem= new char[] {'\r'}; 211 } 212 } else { 213 fLexem= new char[] {fChar}; 214 nextChar(); 215 } 216 fLexemType= CR; 217 } 218 219 222 private void consumeWhiteSpace() { 223 while (fChar == ' ' || fChar == '\t') { 224 nextChar(); 225 } 226 } 227 228 231 public char[] lexem() { 232 return fLexem; 233 } 234 235 238 public int lexemType() { 239 return fLexemType; 240 } 241 242 } 243 244 247 private ReferenceTypeImpl fReferenceType; 248 249 private List fDefinedStrata; 250 251 private ReferenceTypeImpl.Stratum fCurrentStratum; 253 private boolean fFileSectionDefinedForCurrentStratum; 254 private boolean fLineSectionDefinedForCurrentStratum; 255 private int fCurrentLineFileId; 256 257 258 public static void parse(String smap, ReferenceTypeImpl referenceType) throws AbsentInformationException { 259 new SourceDebugExtensionParser(referenceType).parseSmap(smap); 260 } 261 262 265 private SourceDebugExtensionParser(ReferenceTypeImpl referenceType) { 266 fReferenceType= referenceType; 267 fDefinedStrata= new ArrayList (); 268 fDefinedStrata.add(VirtualMachineImpl.JAVA_STRATUM_NAME); 269 } 270 271 274 private void parseSmap(String smap) throws AbsentInformationException { 275 Lexer lexer= new Lexer(smap); 276 parseHeader(lexer); 277 parseSections(lexer); 278 if (!fDefinedStrata.contains(fReferenceType.defaultStratum())) { 279 throw new AbsentInformationException(JDIMessages.SourceDebugExtensionParser_2); 280 } 281 } 282 283 286 private void parseHeader(Lexer lexer) throws AbsentInformationException { 287 int lexemType= lexer.nextLexem(); 288 if (lexemType != Lexer.SMAP) { 289 throw new AbsentInformationException(JDIMessages.SourceDebugExtensionParser_3); 290 } 291 if (lexer.nextLexem() != Lexer.CR) { 292 throw new AbsentInformationException(JDIMessages.SourceDebugExtensionParser_4); 293 } 294 if (isAsteriskLexem(lexer.nextLexem())) { 295 throw new AbsentInformationException(JDIMessages.SourceDebugExtensionParser_5); 296 } 297 fReferenceType.setOutputFileName(getNonAsteriskString(lexer)); 298 if (isAsteriskLexem(lexer.lexemType())) { 299 throw new AbsentInformationException(JDIMessages.SourceDebugExtensionParser_6); 300 } 301 fReferenceType.setDefaultStratumId(getNonAsteriskString(lexer)); 302 } 303 304 307 private void parseSections(Lexer lexer) throws AbsentInformationException { 308 while (lexer.lexemType() != Lexer.ASTERISK_E) { 309 parseStratumSection(lexer); 310 } 311 } 312 313 316 private void parseStratumSection(Lexer lexer) throws AbsentInformationException { 317 if (lexer.lexemType() != Lexer.ASTERISK_S) { 318 throw new AbsentInformationException(JDIMessages.SourceDebugExtensionParser_7); 319 } 320 if (isAsteriskLexem(lexer.nextLexem())) { 321 throw new AbsentInformationException(JDIMessages.SourceDebugExtensionParser_8); 322 } 323 String stratumId= getNonAsteriskString(lexer); 324 if (fDefinedStrata.contains(stratumId)) { 325 throw new AbsentInformationException(MessageFormat.format(JDIMessages.SourceDebugExtensionParser_9, new String [] {stratumId})); 326 } 327 fCurrentStratum= new ReferenceTypeImpl.Stratum(stratumId); 328 fFileSectionDefinedForCurrentStratum= false; 329 fLineSectionDefinedForCurrentStratum= false; 330 int lexemType= lexer.lexemType(); 331 while (lexemType != Lexer.ASTERISK_E && lexemType != Lexer.ASTERISK_S) { 332 switch (lexemType) { 333 case Lexer.ASTERISK_F: 334 if (fFileSectionDefinedForCurrentStratum) { 335 throw new AbsentInformationException(MessageFormat.format(JDIMessages.SourceDebugExtensionParser_10, new String [] {stratumId})); 336 } 337 parseFileSection(lexer); 338 fFileSectionDefinedForCurrentStratum= true; 339 break; 340 case Lexer.ASTERISK_L: 341 if (fLineSectionDefinedForCurrentStratum) { 342 throw new AbsentInformationException(MessageFormat.format(JDIMessages.SourceDebugExtensionParser_11, new String [] {stratumId})); 343 } 344 parseLineSection(lexer); 345 fLineSectionDefinedForCurrentStratum= true; 346 break; 347 case Lexer.ASTERISK_V: 348 parseVendorSection(lexer); 349 break; 350 case Lexer.ASTERISK_CHAR: 351 parseFutureSection(lexer); 352 break; 353 default: 354 throw new AbsentInformationException(MessageFormat.format(JDIMessages.SourceDebugExtensionParser_12, new String [] {new String (lexer.lexem())})); 355 } 356 lexemType= lexer.lexemType(); 357 } 358 if (!fFileSectionDefinedForCurrentStratum) { 359 throw new AbsentInformationException(MessageFormat.format(JDIMessages.SourceDebugExtensionParser_13, new String [] {stratumId})); 360 } 361 if (!fLineSectionDefinedForCurrentStratum) { 362 throw new AbsentInformationException(MessageFormat.format(JDIMessages.SourceDebugExtensionParser_14, new String [] {stratumId})); 363 } 364 fDefinedStrata.add(stratumId); 365 fReferenceType.addStratum(fCurrentStratum); 366 } 367 368 371 private void parseFileSection(Lexer lexer) throws AbsentInformationException { 372 if (lexer.nextLexem() != Lexer.CR) { 373 throw new AbsentInformationException(MessageFormat.format(JDIMessages.SourceDebugExtensionParser_12, new String [] {new String (lexer.lexem())})); 374 } 375 lexer.nextLexem(); 376 while (!isAsteriskLexem(lexer.lexemType())) { 377 parseFileInfo(lexer); 378 } 379 } 380 381 384 private void parseFileInfo(Lexer lexer) throws AbsentInformationException { 385 int lexemType= lexer.lexemType(); 386 if (lexemType == Lexer.NUMBER) { 387 int fileId= integerValue(lexer.lexem()); 388 if (isAsteriskLexem(lexer.nextLexem())) { 389 throw new AbsentInformationException(JDIMessages.SourceDebugExtensionParser_16); 390 } 391 fCurrentStratum.addFileInfo(fileId, getNonAsteriskString(lexer)); 392 } else if (lexemType == Lexer.PLUS) { 393 if (lexer.nextLexem() != Lexer.NUMBER) { 394 throw new AbsentInformationException(JDIMessages.SourceDebugExtensionParser_17); 395 } 396 int fileId= integerValue(lexer.lexem()); 397 if (isAsteriskLexem(lexer.nextLexem())) { 398 throw new AbsentInformationException(JDIMessages.SourceDebugExtensionParser_16); 399 } 400 String fileName= getNonAsteriskString(lexer); 401 if (isAsteriskLexem(lexer.lexemType())) { 402 throw new AbsentInformationException(JDIMessages.SourceDebugExtensionParser_19); 403 } 404 fCurrentStratum.addFileInfo(fileId, fileName, getNonAsteriskString(lexer)); 405 } else { 406 throw new AbsentInformationException(MessageFormat.format(JDIMessages.SourceDebugExtensionParser_12, new String [] {new String (lexer.lexem())})); 407 } 408 } 409 410 413 private void parseLineSection(Lexer lexer) throws AbsentInformationException { 414 fCurrentLineFileId= 0; 415 if (lexer.nextLexem() != Lexer.CR) { 416 throw new AbsentInformationException(MessageFormat.format(JDIMessages.SourceDebugExtensionParser_12, new String [] {new String (lexer.lexem())})); 417 } 418 lexer.nextLexem(); 419 while (!isAsteriskLexem(lexer.lexemType())) { 420 parseLineInfo(lexer); 421 } 422 } 423 424 427 private void parseLineInfo(Lexer lexer) throws AbsentInformationException { 428 if (lexer.lexemType() != Lexer.NUMBER) { 429 throw new AbsentInformationException(JDIMessages.SourceDebugExtensionParser_22); 430 } 431 int inputStartLine= integerValue(lexer.lexem()); 432 int lexemType= lexer.nextLexem(); 433 if (lexemType == Lexer.SHARP) { 434 if (lexer.nextLexem() != Lexer.NUMBER) { 435 throw new AbsentInformationException(JDIMessages.SourceDebugExtensionParser_23); 436 } 437 fCurrentLineFileId= integerValue(lexer.lexem()); 438 lexemType= lexer.nextLexem(); 439 } 440 int repeatCount; 441 if (lexemType == Lexer.COMMA) { 442 if (lexer.nextLexem() != Lexer.NUMBER) { 443 throw new AbsentInformationException(JDIMessages.SourceDebugExtensionParser_24); 444 } 445 repeatCount= integerValue(lexer.lexem()); 446 lexemType= lexer.nextLexem(); 447 } else { 448 repeatCount= 1; 449 } 450 if (lexemType != Lexer.COLON) { 451 throw new AbsentInformationException(JDIMessages.SourceDebugExtensionParser_25); 452 } 453 if (lexer.nextLexem() != Lexer.NUMBER) { 454 throw new AbsentInformationException(JDIMessages.SourceDebugExtensionParser_26); 455 } 456 int outputStartLine= integerValue(lexer.lexem()); 457 lexemType= lexer.nextLexem(); 458 int outputLineIncrement; 459 if (lexemType == Lexer.COMMA) { 460 if (lexer.nextLexem() != Lexer.NUMBER) { 461 throw new AbsentInformationException(JDIMessages.SourceDebugExtensionParser_27); 462 } 463 outputLineIncrement= integerValue(lexer.lexem()); 464 lexemType= lexer.nextLexem(); 465 } else { 466 outputLineIncrement= 1; 467 } 468 if (lexemType != Lexer.CR) { 469 throw new AbsentInformationException(JDIMessages.SourceDebugExtensionParser_28); 470 } 471 lexer.nextLexem(); 472 fCurrentStratum.addLineInfo(inputStartLine, fCurrentLineFileId, repeatCount, outputStartLine, outputLineIncrement); 473 } 474 475 478 private void parseVendorSection(Lexer lexer) throws AbsentInformationException { 479 if (lexer.nextLexem() != Lexer.CR) { 480 throw new AbsentInformationException(MessageFormat.format(JDIMessages.SourceDebugExtensionParser_12, new String [] {new String (lexer.lexem())})); 481 } 482 lexer.nextLexem(); 483 while (!isAsteriskLexem(lexer.lexemType())) { 484 getNonAsteriskString(lexer); 486 } 487 } 488 489 492 private void parseFutureSection(Lexer lexer) throws AbsentInformationException { 493 if (lexer.nextLexem() != Lexer.CR) { 494 throw new AbsentInformationException(MessageFormat.format(JDIMessages.SourceDebugExtensionParser_12, new String [] {new String (lexer.lexem())})); 495 } 496 lexer.nextLexem(); 497 while (!isAsteriskLexem(lexer.lexemType())) { 498 getNonAsteriskString(lexer); 500 } 501 } 502 503 private String getNonAsteriskString(Lexer lexer) throws AbsentInformationException { 504 StringBuffer string= new StringBuffer (); 505 int lexemType= lexer.lexemType(); 506 while (lexemType != Lexer.CR) { 507 string.append(lexer.lexem()); 508 lexemType= lexer.nextLexem(); 509 } 510 lexer.nextLexem(); 511 int i= -1, length= string.length(); 513 char c; 514 while (++i < length && ((c= string.charAt(i)) == ' ' || c == '\t')); 515 return string.delete(0, i).toString(); 516 } 517 518 private int integerValue(char[] lexem) { 519 int i= 0; 520 char c= lexem[0]; 521 while (c == ' ' || c == '\t') { 522 c= lexem[++i]; 523 } 524 int value= 0; 525 while (c >= '0' && c <= '9') { 526 value= value * 10 + c - '0'; 527 if (++i == lexem.length) { 528 break; 529 } 530 c= lexem[i]; 531 } 532 return value; 533 } 534 535 private boolean isAsteriskLexem(int lexemType) { 536 switch (lexemType) { 537 case Lexer.ASTERISK_C: 538 case Lexer.ASTERISK_E: 539 case Lexer.ASTERISK_F: 540 case Lexer.ASTERISK_L: 541 case Lexer.ASTERISK_O: 542 case Lexer.ASTERISK_S: 543 case Lexer.ASTERISK_V: 544 case Lexer.ASTERISK_CHAR: 545 return true; 546 default: 547 return false; 548 } 549 } 550 551 } 552 | Popular Tags |