/* Copyright (C) 2009 Mobile Sorcery AB This program is free software; you can redistribute it and/or modify it under the terms of the Eclipse Public License v1.0. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Eclipse Public License v1.0 for more details. You should have received a copy of the Eclipse Public License v1.0 along with this program. It is also available at http://www.eclipse.org/legal/epl-v10.html */ package com.mobilesorcery.sdk.internal; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.io.LineNumberReader; import java.io.Reader; import java.text.MessageFormat; import java.util.ArrayList; import org.eclipse.cdt.utils.CPPFilt; import com.mobilesorcery.sdk.core.CoreMoSyncPlugin; import com.mobilesorcery.sdk.core.MoSyncTool; import com.mobilesorcery.sdk.core.Util; public class SLDParser { public static final String FILE_MARKER = "Files"; public static final String SLD_MARKER = "SLD"; public static final String FUNCTIONS_MARKER = "FUNCTIONS"; public static final String LINE_IP_MARKER = "LINEIP"; private static final int FILE_STATE = 1; private static final int SLD_STATE = 2; private static final int FUNCTIONS_STATE = 3; private static final int LINE_IP_STATE = 4; private int state; private ArrayList<Exception> errors = new ArrayList<Exception>(); private SLDInfoImpl sld; private int currentLine; private CPPFilt cppFilt; public void parse(File sldFile) throws IOException { BufferedReader sldReader = new BufferedReader(new FileReader(sldFile)); try { parse(sldReader, sldFile); } finally { Util.safeClose(sldReader); } } public void parse(Reader sldReader) throws IOException { parse(sldReader, null); } private void parse(Reader sldReader, File sldFile) throws IOException { try { try { cppFilt = new CPPFilt(MoSyncTool.getDefault() .getBinary("c++filt").toOSString()); } catch (IOException e) { // Ignore but log. CoreMoSyncPlugin.getDefault().logOnce(e, getClass().getName() + "c++filt"); } sld = new SLDInfoImpl(sldFile); currentLine = 0; LineNumberReader sldLines = new LineNumberReader(sldReader); for (String line = sldLines.readLine(); line != null; line = sldLines .readLine()) { line = line.trim(); // Lines are 1-based. currentLine++; if (FILE_MARKER.equals(line)) { state = FILE_STATE; } else if (SLD_MARKER.equals(line)) { state = SLD_STATE; } else if (FUNCTIONS_MARKER.equals(line)) { state = FUNCTIONS_STATE; } else if (LINE_IP_MARKER.equals(line)) { state = LINE_IP_STATE; } else if (line.length() > 0) { parseEntry(line); } } } finally { if (cppFilt != null) { cppFilt.dispose(); } } } public SLDInfoImpl getSLD() { return sld; } public String[] getErrors() { return errors.toArray(new String[0]); } private void parseEntry(String line) { try { switch (state) { case FILE_STATE: parseFileEntry(line); break; case SLD_STATE: parseSLDEntry(line); break; case FUNCTIONS_STATE: parseFunctionEntry(line); break; } } catch (SLDParseException e) { errors.add(e); } } private void parseFunctionEntry(String line) { String[] functionEntry = line.split("\\s", 2); if (functionEntry.length == 2) { String symbol = functionEntry[0]; String unmangledFunctionName = symbol; try { unmangledFunctionName = cppFilt.getFunction(symbol); } catch (IOException e) { // Just present the mangled name } String addrRange = functionEntry[1]; sld.addRangeForFunction(unmangledFunctionName, AddressRange.parse(addrRange)); } } private void parseSLDEntry(String line) throws SLDParseException { String[] sldEntry = line.split(":", 3); if (sldEntry.length != 3) { throw new SLDParseException(MessageFormat.format( "Invalid line: {0}", line), currentLine); } int addr = parseInt(sldEntry[0], 16); int lineInFile = parseInt(sldEntry[1], 10); int fileId = parseInt(sldEntry[2], 10); sld.addLocationForAddress(addr, lineInFile, fileId); } private void parseFileEntry(String line) throws SLDParseException { String[] fileEntry = line.split(":", 3); if (fileEntry.length != 3) { throw new SLDParseException(MessageFormat.format( "Invalid line: {0}", line), currentLine); } String id = fileEntry[0]; String name = fileEntry[2]; int idValue = parseInt(id, 10); sld.addFile(idValue, name); } private int parseInt(String str, int radix) throws SLDParseException { return parseInt(str, radix, currentLine); } public static int parseInt(String str, int radix, int currentLine) throws SLDParseException { try { return Integer.parseInt(str, radix); } catch (Exception e) { throw new SLDParseException(MessageFormat.format( "Expected a number, found {0}", str), currentLine); } } }