diff --git a/.idea/misc.xml b/.idea/misc.xml index 36970fa..ac2c845 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -4,7 +4,7 @@ - + \ No newline at end of file diff --git a/src/main/CTests/test.c b/src/main/CTests/test.c index 25d0302..5df7da4 100644 --- a/src/main/CTests/test.c +++ b/src/main/CTests/test.c @@ -14,5 +14,7 @@ short munis(int a,int b){ int l = a; int f = b; int k = l - f; - return k; + int h = add(l,f); + int p = k / h; + return p; } \ No newline at end of file diff --git a/src/main/kotlin/Main.kt b/src/main/kotlin/Main.kt index 3b43ee0..9300f77 100644 --- a/src/main/kotlin/Main.kt +++ b/src/main/kotlin/Main.kt @@ -167,7 +167,7 @@ fun App() { getInvokeTraceTreeString("main",sf,relations) ttGraph = generateGraph(relations) - ivGraph = sf.functions.getInvokeGraph("main") + ivGraph = sf.functions.getInvokeGraph() showResult.value = true } diff --git a/src/main/kotlin/core/CFunction.kt b/src/main/kotlin/core/CFunction.kt index 823ca5f..cf2ff8c 100644 --- a/src/main/kotlin/core/CFunction.kt +++ b/src/main/kotlin/core/CFunction.kt @@ -130,7 +130,7 @@ fun List.find(name: String): CFunction? { * List.getInvokeTree * @param List: 要求包含所有函数以查找 * @param name: 从哪个函数开始查找 - * @return 特制的 TraceTree + * @return 特制的 TraceTree funcName -> tracetree[], 包含的是调用者的参数 */ fun List.getInvokeTree(name: String): Map> { // 先找到开始的函数 @@ -154,10 +154,13 @@ fun List.getInvokeTree(name: String): Map> { if (function != null) { val info = InvokeInfo(name, args) val tt = function.getTraceTree(info) - invokeTrees.addAll(tt) + // 过滤 trace tree + invokeTrees.addAll(tt.filter { it.name.startsWith(name) }) } if (funcName != "") { - resultMap[funcName] = invokeTrees + val newTree = invokeTrees.toList() + resultMap[funcName] = newTree // 因为之后要清空 + invokeTrees.clear() args.clear() funcName = "" } diff --git a/src/main/kotlin/core/GraphvizHelper.kt b/src/main/kotlin/core/GraphvizHelper.kt index 8197cb4..409664d 100644 --- a/src/main/kotlin/core/GraphvizHelper.kt +++ b/src/main/kotlin/core/GraphvizHelper.kt @@ -7,22 +7,23 @@ fun generateGraph(relations: Map>, crossLabelPaths: List< sb.append("digraph G {\n") for ((label, edges) in relations) { - sb.append(" subgraph cluster_$label {\n") - sb.append(" label = \"$label\";\n") + sb.append("subgraph cluster_$label {") + sb.append("label = \"$label\";") val uniquePaths = mutableSetOf() for (relation in edges) { 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 -> ${relation.to}$label;\n") + sb.append("${relation.from}$label[label=${relation.from}];${relation.to}$label[label=${relation.to}];") + sb.append("${relation.from}$label -> ${relation.to}$label;") } - sb.append(" }\n") + sb.append("}\n") } if (crossLabelPaths != null) { // 处理跨函数 + val hashes = mutableListOf() // 去重, 重复是因为一个参数可以有多个影响其他变量的路线,但一起显示太奇怪了 for (path in crossLabelPaths) { val parts = path.split(":") if (parts.size == 3) { @@ -31,13 +32,18 @@ fun generateGraph(relations: Map>, crossLabelPaths: List< val fromNode = subPath[0] // 这里就是z val toNode = subPath[1] // 下一个就是 // 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() } @@ -63,14 +69,13 @@ fun parseRelation(funcName: String, parse: String): Map>{ ) } -fun List.getInvokeGraph(funcName: String): String { +fun List.getInvokeGraph(): String { val relations = mutableMapOf>() - val func = this.find(funcName) ?: return "" - + val crossLabelPaths = StringBuilder() this.forEach { relations.putAll(parseRelation(it.name,it.getTraceTree().getStringRepr())) + crossLabelPaths.append(this.getInvokeTree(it.name).getFuncRepr(it.name)) + crossLabelPaths.append('\n') } - - val crossLabelPaths = this.getInvokeTree(func.name).getFuncRepr(func.name) - return generateGraph(relations,crossLabelPaths.split('\n')) + "\n" + return generateGraph(relations,crossLabelPaths.split('\n').filter { it.isNotEmpty() }) } \ No newline at end of file diff --git a/src/main/kotlin/core/SourceFile.kt b/src/main/kotlin/core/SourceFile.kt index debc35b..7702eb5 100644 --- a/src/main/kotlin/core/SourceFile.kt +++ b/src/main/kotlin/core/SourceFile.kt @@ -6,8 +6,6 @@ import java.io.File import core.CLanguage.Companion.OPERATION.* import core.CLanguage.Companion.declarationRegex import core.CLanguage.Companion.types -import utils.getDefineList -import utils.getUseList class SourceFile { companion object { @@ -156,18 +154,12 @@ fun main() { val funcs = sourceFile.parseFunction() val relations = mutableMapOf>() 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())) } - println(funcs.getInvokeTree("main").getFuncRepr("main")) + for (function in funcs) { + println(funcs.getInvokeTree(function.name).getFuncRepr(function.name)) + } println(generateGraph(relations)) - println(funcs.getInvokeGraph("main")) - - println(getDefineList(sourceFile.getDef())) - println(getUseList(sourceFile.getUse())) + println(funcs.getInvokeGraph()) } \ No newline at end of file diff --git a/src/main/kotlin/core/TraceTree.kt b/src/main/kotlin/core/TraceTree.kt index bd7b337..d8ccf4f 100644 --- a/src/main/kotlin/core/TraceTree.kt +++ b/src/main/kotlin/core/TraceTree.kt @@ -49,15 +49,13 @@ fun List.getStringRepr(): String { fun Map>.getFuncRepr(func: String): String { val result = StringBuilder() - var fName = "" this.forEach { (name, list) -> - fName = name 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() - result.lines().forEach { line -> - fixedResult.append("$fName:$line\n") - } - return fixedResult.toString() + return result.toString().trim() } \ No newline at end of file diff --git a/src/main/kotlin/utils/OpenBrowser.kt b/src/main/kotlin/utils/OpenBrowser.kt index 57aa370..ecd17ea 100644 --- a/src/main/kotlin/utils/OpenBrowser.kt +++ b/src/main/kotlin/utils/OpenBrowser.kt @@ -1,6 +1,10 @@ package utils 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.util.* @@ -10,7 +14,20 @@ fun openBrowser(uri: URI) { when { Desktop.isDesktopSupported() && desktop.isSupported(Desktop.Action.BROWSE) -> desktop.browse(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) } }