This commit is contained in:
kagura 2024-10-30 15:06:07 +08:00
parent 30f3c67e32
commit 99c9440a39
8 changed files with 57 additions and 40 deletions

View file

@ -4,7 +4,7 @@
<component name="FrameworkDetectionExcludesConfiguration"> <component name="FrameworkDetectionExcludesConfiguration">
<file type="web" url="file://$PROJECT_DIR$" /> <file type="web" url="file://$PROJECT_DIR$" />
</component> </component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_23" project-jdk-name="openjdk-22" project-jdk-type="JavaSDK"> <component name="ProjectRootManager" version="2" languageLevel="JDK_22" default="true" project-jdk-name="openjdk-22" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" /> <output url="file://$PROJECT_DIR$/out" />
</component> </component>
</project> </project>

View file

@ -14,5 +14,7 @@ short munis(int a,int b){
int l = a; int l = a;
int f = b; int f = b;
int k = l - f; int k = l - f;
return k; int h = add(l,f);
int p = k / h;
return p;
} }

View file

@ -167,7 +167,7 @@ fun App() {
getInvokeTraceTreeString("main",sf,relations) getInvokeTraceTreeString("main",sf,relations)
ttGraph = generateGraph(relations) ttGraph = generateGraph(relations)
ivGraph = sf.functions.getInvokeGraph("main") ivGraph = sf.functions.getInvokeGraph()
showResult.value = true showResult.value = true
} }

View file

@ -130,7 +130,7 @@ fun List<CFunction>.find(name: String): CFunction? {
* List<CFunction>.getInvokeTree * List<CFunction>.getInvokeTree
* @param List<CFunction>: 要求包含所有函数以查找 * @param List<CFunction>: 要求包含所有函数以查找
* @param name: 从哪个函数开始查找 * @param name: 从哪个函数开始查找
* @return 特制的 TraceTree * @return 特制的 TraceTree funcName -> tracetree[], 包含的是调用者的参数
*/ */
fun List<CFunction>.getInvokeTree(name: String): Map<String, List<TraceTree>> { fun List<CFunction>.getInvokeTree(name: String): Map<String, List<TraceTree>> {
// 先找到开始的函数 // 先找到开始的函数
@ -154,10 +154,13 @@ fun List<CFunction>.getInvokeTree(name: String): Map<String, List<TraceTree>> {
if (function != null) { if (function != null) {
val info = InvokeInfo(name, args) val info = InvokeInfo(name, args)
val tt = function.getTraceTree(info) val tt = function.getTraceTree(info)
invokeTrees.addAll(tt) // 过滤 trace tree
invokeTrees.addAll(tt.filter { it.name.startsWith(name) })
} }
if (funcName != "") { if (funcName != "") {
resultMap[funcName] = invokeTrees val newTree = invokeTrees.toList()
resultMap[funcName] = newTree // 因为之后要清空
invokeTrees.clear()
args.clear() args.clear()
funcName = "" funcName = ""
} }

View file

@ -7,22 +7,23 @@ fun generateGraph(relations: Map<String, List<Relation>>, crossLabelPaths: List<
sb.append("digraph G {\n") sb.append("digraph G {\n")
for ((label, edges) in relations) { for ((label, edges) in relations) {
sb.append(" subgraph cluster_$label {\n") sb.append("subgraph cluster_$label {")
sb.append(" label = \"$label\";\n") sb.append("label = \"$label\";")
val uniquePaths = mutableSetOf<String>() val uniquePaths = mutableSetOf<String>()
for (relation in edges) { for (relation in edges) {
uniquePaths.add("${relation.from} -> ${relation.to}") uniquePaths.add("${relation.from} -> ${relation.to}")
sb.append("${relation.from}$label[label=${relation.from}];\n${relation.to}$label[label=${relation.to}];\n") sb.append("${relation.from}$label[label=${relation.from}];${relation.to}$label[label=${relation.to}];")
sb.append("${relation.from}$label -> ${relation.to}$label;\n") sb.append("${relation.from}$label -> ${relation.to}$label;")
} }
sb.append(" }\n") sb.append("}\n")
} }
if (crossLabelPaths != null) { if (crossLabelPaths != null) {
// 处理跨函数 // 处理跨函数
val hashes = mutableListOf<Int>() // 去重, 重复是因为一个参数可以有多个影响其他变量的路线,但一起显示太奇怪了
for (path in crossLabelPaths) { for (path in crossLabelPaths) {
val parts = path.split(":") val parts = path.split(":")
if (parts.size == 3) { if (parts.size == 3) {
@ -31,13 +32,18 @@ fun generateGraph(relations: Map<String, List<Relation>>, crossLabelPaths: List<
val fromNode = subPath[0] // 这里就是z val fromNode = subPath[0] // 这里就是z
val toNode = subPath[1] // 下一个就是 val toNode = subPath[1] // 下一个就是
// from 到 to 用虚线 // from 到 to 用虚线
sb.append(" $fromNode${parts[1]} -> $toNode${parts[0]} [style=dashed];\n") val str = "$fromNode${parts[1]} -> $toNode${parts[0]} [style=dashed];"
val hash = str.hashCode()
if (hash !in hashes){ // 不重复
sb.append(str)
hashes.add(hash)
}
} }
} }
} }
} }
sb.append("}\n") sb.append("\n}")
return sb.toString() return sb.toString()
} }
@ -63,14 +69,13 @@ fun parseRelation(funcName: String, parse: String): Map<String, List<Relation>>{
) )
} }
fun List<CFunction>.getInvokeGraph(funcName: String): String { fun List<CFunction>.getInvokeGraph(): String {
val relations = mutableMapOf<String, List<Relation>>() val relations = mutableMapOf<String, List<Relation>>()
val func = this.find(funcName) ?: return "" val crossLabelPaths = StringBuilder()
this.forEach { this.forEach {
relations.putAll(parseRelation(it.name,it.getTraceTree().getStringRepr())) relations.putAll(parseRelation(it.name,it.getTraceTree().getStringRepr()))
crossLabelPaths.append(this.getInvokeTree(it.name).getFuncRepr(it.name))
crossLabelPaths.append('\n')
} }
return generateGraph(relations,crossLabelPaths.split('\n').filter { it.isNotEmpty() })
val crossLabelPaths = this.getInvokeTree(func.name).getFuncRepr(func.name)
return generateGraph(relations,crossLabelPaths.split('\n')) + "\n"
} }

View file

@ -6,8 +6,6 @@ import java.io.File
import core.CLanguage.Companion.OPERATION.* import core.CLanguage.Companion.OPERATION.*
import core.CLanguage.Companion.declarationRegex import core.CLanguage.Companion.declarationRegex
import core.CLanguage.Companion.types import core.CLanguage.Companion.types
import utils.getDefineList
import utils.getUseList
class SourceFile { class SourceFile {
companion object { companion object {
@ -156,18 +154,12 @@ fun main() {
val funcs = sourceFile.parseFunction() val funcs = sourceFile.parseFunction()
val relations = mutableMapOf<String, List<Relation>>() val relations = mutableMapOf<String, List<Relation>>()
funcs.forEach { funcs.forEach {
println("${it.name}(${it.params}) -> ${it.returnType} {\n${it.content}\n} ")
it.cParser.sentenceList.forEach{ s->
println("${s.left},${s.right},${s.type}")
}
println(it.getTraceTree().getStringRepr())
relations.putAll(parseRelation(it.name,it.getTraceTree().getStringRepr())) relations.putAll(parseRelation(it.name,it.getTraceTree().getStringRepr()))
} }
println(funcs.getInvokeTree("main").getFuncRepr("main")) for (function in funcs) {
println(funcs.getInvokeTree(function.name).getFuncRepr(function.name))
}
println(generateGraph(relations)) println(generateGraph(relations))
println(funcs.getInvokeGraph("main")) println(funcs.getInvokeGraph())
println(getDefineList(sourceFile.getDef()))
println(getUseList(sourceFile.getUse()))
} }

View file

@ -49,15 +49,13 @@ fun List<TraceTree>.getStringRepr(): String {
fun Map<String, List<TraceTree>>.getFuncRepr(func: String): String { fun Map<String, List<TraceTree>>.getFuncRepr(func: String): String {
val result = StringBuilder() val result = StringBuilder()
var fName = ""
this.forEach { (name, list) -> this.forEach { (name, list) ->
fName = name
val listRepr = list.getStringRepr() val listRepr = list.getStringRepr()
result.append(listRepr.split('\n').filter { it.startsWith(func) }.joinToString("\n")) for (line in listRepr.lines()) {
if (line.startsWith(func)){ // main:x-> 这样的
result.append("$name:$line\n")
}
}
} }
val fixedResult = StringBuilder() return result.toString().trim()
result.lines().forEach { line ->
fixedResult.append("$fName:$line\n")
}
return fixedResult.toString()
} }

View file

@ -1,6 +1,10 @@
package utils package utils
import java.awt.Desktop import java.awt.Desktop
import java.awt.Toolkit
import java.awt.datatransfer.StringSelection
import java.io.File
import java.io.IOException
import java.net.URI import java.net.URI
import java.util.* import java.util.*
@ -10,7 +14,20 @@ fun openBrowser(uri: URI) {
when { when {
Desktop.isDesktopSupported() && desktop.isSupported(Desktop.Action.BROWSE) -> desktop.browse(uri) Desktop.isDesktopSupported() && desktop.isSupported(Desktop.Action.BROWSE) -> desktop.browse(uri)
"mac" in osName -> Runtime.getRuntime().exec("open $uri") "mac" in osName -> Runtime.getRuntime().exec("open $uri")
"nix" in osName || "nux" in osName -> Runtime.getRuntime().exec("xdg-open $uri") "nix" in osName || "nux" in osName -> {
try {
Runtime.getRuntime().exec("xdg-open $uri")
}catch (_: IOException){
// xdg-open 不存在
if (File("/run/current-system/sw/bin/xdg-open").exists()){ // nixos
Runtime.getRuntime().exec("/run/current-system/sw/bin/xdg-open $uri")
}else{
val clipboard = Toolkit.getDefaultToolkit().systemClipboard
val content = StringSelection(uri.toString())
clipboard.setContents(content, null)
}
}
}
else -> desktop.browse(uri) else -> desktop.browse(uri)
} }
} }