All Downloads are FREE. Search and download functionalities are using the official Maven repository.

hu.bme.mit.theta.xcfa.cli.witnesses.GraphmlWitness.kt Maven / Gradle / Ivy

The newest version!
/*
 *  Copyright 2024 Budapest University of Technology and Economics
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package hu.bme.mit.theta.xcfa.cli.witnesses

import hu.bme.mit.theta.analysis.Trace
import java.io.File
import java.io.StringReader
import java.io.StringWriter
import javax.xml.XMLConstants
import javax.xml.transform.OutputKeys
import javax.xml.transform.Source
import javax.xml.transform.Transformer
import javax.xml.transform.TransformerFactory
import javax.xml.transform.stream.StreamResult
import javax.xml.transform.stream.StreamSource

class GraphmlWitness(private val trace: Trace, programFile: File) {

  private val attributes: MutableList = ArrayList()
  private val data: MutableList> = ArrayList()

  init {
    attributes.add(GraphmlWitnessAttribute("sourcecodelang", "string", "graph", "sourcecodelang"))
    attributes.add(GraphmlWitnessAttribute("creationtime", "string", "graph", "creationtime"))
    attributes.add(GraphmlWitnessAttribute("witness-type", "string", "graph", "witness-type"))
    attributes.add(GraphmlWitnessAttribute("producer", "string", "graph", "producer"))
    attributes.add(GraphmlWitnessAttribute("architecture", "string", "graph", "architecture"))
    attributes.add(GraphmlWitnessAttribute("programHash", "string", "graph", "programhash"))
    attributes.add(GraphmlWitnessAttribute("programfile", "string", "graph", "programfile"))
    attributes.add(GraphmlWitnessAttribute("specification", "string", "graph", "specification"))

    attributes.add(GraphmlWitnessAttribute("assumption", "string", "edge", "assumption"))
    attributes.add(
      GraphmlWitnessAttribute("assumption.scope", "string", "edge", "assumption.scope")
    )
    attributes.add(
      GraphmlWitnessAttribute(
        "assumption.resultfunction",
        "string",
        "edge",
        "assumption.resultfunction",
      )
    )
    attributes.add(GraphmlWitnessAttribute("control", "string", "edge", "control"))
    attributes.add(GraphmlWitnessAttribute("startline", "string", "edge", "startline"))
    attributes.add(GraphmlWitnessAttribute("endline", "string", "edge", "endline"))
    attributes.add(GraphmlWitnessAttribute("startoffset", "string", "edge", "startoffset"))
    attributes.add(GraphmlWitnessAttribute("endoffset", "string", "edge", "endoffset"))
    attributes.add(GraphmlWitnessAttribute("enterLoopHead", "string", "edge", "enterLoopHead"))
    attributes.add(GraphmlWitnessAttribute("enterFunction", "string", "edge", "enterFunction"))
    attributes.add(
      GraphmlWitnessAttribute("returnFromFunction", "string", "edge", "returnFromFunction")
    )
    attributes.add(GraphmlWitnessAttribute("threadId", "string", "edge", "threadId"))
    attributes.add(GraphmlWitnessAttribute("createThread", "string", "edge", "createThread"))
    attributes.add(GraphmlWitnessAttribute("stmt", "string", "edge", "stmt"))
    attributes.add(GraphmlWitnessAttribute("cSource", "string", "edge", "cSource"))

    attributes.add(GraphmlWitnessAttribute("entry", "string", "node", "entry", "false"))
    attributes.add(GraphmlWitnessAttribute("sink", "string", "node", "sink", "false"))
    attributes.add(GraphmlWitnessAttribute("violation", "string", "node", "violation", "false"))
    attributes.add(GraphmlWitnessAttribute("locationStacks", "string", "node", "locationStacks"))
    attributes.add(GraphmlWitnessAttribute("sourceLines", "string", "node", "sourceLines"))
    attributes.add(GraphmlWitnessAttribute("state", "string", "node", "state"))

    data.add(Pair("witness-type", "violation_witness"))
    data.add(Pair("producer", "theta"))
    data.add(Pair("sourcecodelang", "C"))
    data.add(Pair("specification", "CHECK( init(main()), LTL(G ! call(reach_error())) )"))
    data.add(Pair("programfile", programFile.absolutePath))
    data.add(Pair("programhash", createTaskHash(programFile.path)))
    data.add(Pair("architecture", "32bit"))
    data.add(Pair("creationtime", getIsoDate()))
  }

  fun toPrettyXml(): String = prettyFormat(toXml(), 4)

  fun toXml(): String =
    """



${attributes.map(GraphmlWitnessAttribute::toXml).reduce { a, b -> "$a\n$b" }}
        


${data.map { "${it.second}" }.reduce { a, b -> "$a\n$b" }}

${trace.states.map(WitnessNode::toXml).reduce { a, b -> "$a\n$b" }}   
     
${trace.actions.map(WitnessEdge::toXml).reduce { a, b -> "$a\n$b" }}        



    """
      .trimIndent()
}

data class GraphmlWitnessAttribute(
  val name: String,
  val type: String,
  val `for`: String,
  val id: String,
  val defaultValue: String? = null,
) {

  fun toXml(): String =
    """
" else """
>
$defaultValue

""".trimIndent()
    }
"""
      .trimIndent()
}

private fun escapeXml(toEscape: String): String {
  var toEscape = toEscape
  toEscape = toEscape.replace("&", "&")
  toEscape = toEscape.replace("\"", """)
  toEscape = toEscape.replace("'", "'")
  toEscape = toEscape.replace("<", "<")
  toEscape = toEscape.replace(">", ">")
  return toEscape
}

// from https://stackoverflow.com/a/1264912
private fun prettyFormat(input: String, indent: Int): String {
  return try {
    val xmlInput: Source = StreamSource(StringReader(input.replace(Regex("(  )|[\\t\\n\\r]"), "")))
    val stringWriter = StringWriter()
    val xmlOutput = StreamResult(stringWriter)
    val transformerFactory: TransformerFactory = TransformerFactory.newInstance()
    transformerFactory.setAttribute("indent-number", indent)
    transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "")
    transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "")
    val transformer: Transformer = transformerFactory.newTransformer()
    transformer.setOutputProperty(OutputKeys.INDENT, "yes")
    transformer.transform(xmlInput, xmlOutput)
    xmlOutput.getWriter().toString()
  } catch (e: Exception) {
    System.err.println(input.replace(Regex("(  )|[\\t\\n\\r]"), ""))
    throw RuntimeException(e)
  }
}

fun WitnessNode.toXml(): String =
  """

    ${if (entry) "true" else ""}
    ${if (sink) "true" else ""}
    ${if (violation) "true" else ""}
    
    ${
    if (xcfaLocations.isNotEmpty()) "${
        escapeXml(xcfaLocations.toString())
    }" else ""
}
    ${
    if (cSources.isNotEmpty()) "${
        escapeXml(cSources.toString())
    }" else ""
}
    ${
    if (globalState != null) "${
        escapeXml(globalState.toString())
    }" else ""
}

    """
    .trimIndent()

fun WitnessEdge.toXml(): String =
  """
        
            ${if (assumption != null) "$assumption" else ""}
            ${if (assumption_scope != null) "$assumption_scope" else ""}
            ${if (assumption_resultfunction != null) "$assumption_resultfunction" else ""}
            ${if (control != null) "condition-$control" else ""}
            ${if (startline != null && startline != -1) "$startline" else ""}
            ${if (endline != null && endline != -1) "$endline" else ""}
            ${if (startoffset != null && startoffset != -1) "$startoffset" else ""}
            ${if (endoffset != null && endoffset != -1) "$endoffset" else ""}
            ${if (enterLoopHead) "true" else ""}
            ${if (enterFunction != null) "$enterFunction" else ""}
            ${if (returnFromFunction != null) "$returnFromFunction" else ""}
            ${if (threadId != null) "$threadId" else ""}
            ${if (createThread != null) "$createThread" else ""}

            ${if (stmt != null) "${escapeXml(stmt)}" else ""}
            ${
    if (cSource != null && cSource != "") "${
        escapeXml(cSource)
    }" else ""
}

        
    """
    .trimIndent()




© 2015 - 2024 Weber Informatics LLC | Privacy Policy