//@category Vegvisir
import ghidra.app.script.GhidraScript;
import ghidra.app.decompiler.*;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Function;
import ghidra.program.model.pcode.*;
import java.util.*;

public class VegvisirListVariables extends GhidraScript {
    private static String q(String s){ if(s==null)return"null"; StringBuilder b=new StringBuilder("\""); for(int i=0;i<s.length();i++){char c=s.charAt(i); switch(c){case '\\':b.append("\\\\");break;case '"':b.append("\\\"");break;case '\n':b.append("\\n");break;case '\r':b.append("\\r");break;case '\t':b.append("\\t");break;default: if(c<0x20)b.append(String.format("\\u%04x",(int)c)); else b.append(c);}} return b.append('"').toString(); }
    private Function findFunction(String fn, String addrS) throws Exception { if(fn!=null && fn.length()>0){ for(Function f: currentProgram.getFunctionManager().getFunctions(true)){ if(f.getName().equals(fn)) return f; }} Address a=currentProgram.getAddressFactory().getAddress(addrS); if(a==null)return null; Function f=currentProgram.getFunctionManager().getFunctionAt(a); if(f==null)f=currentProgram.getFunctionManager().getFunctionContaining(a); return f; }
    public void run() throws Exception { String[] args=getScriptArgs(); String fn=args.length>0?args[0]:""; String addr=args.length>1?args[1]:""; int limit=args.length>2?Integer.parseInt(args[2]):200; Function f=findFunction(fn,addr); if(f==null){println("VEGVISIR_JSON:{\"ok\":false,\"error\":\"function not found\"}");return;} DecompInterface ifc=new DecompInterface(); ifc.toggleCCode(true); ifc.toggleSyntaxTree(true); ifc.setSimplificationStyle("decompile"); if(!ifc.openProgram(currentProgram)){println("VEGVISIR_JSON:{\"ok\":false,\"error\":\"failed to open decompiler\"}");return;} DecompileResults res=ifc.decompileFunction(f,30,monitor); if(!res.decompileCompleted() || res.getHighFunction()==null){println("VEGVISIR_JSON:{\"ok\":false,\"error\":"+q(res.getErrorMessage())+"}");return;} HighFunction hf=res.getHighFunction(); StringBuilder out=new StringBuilder(); out.append("{\n  \"ok\": true,\n  \"function\": {\"name\": ").append(q(f.getName())).append(", \"entry\": ").append(q(f.getEntryPoint().toString())).append("},\n  \"variables\": [\n"); Iterator<HighSymbol> it=hf.getLocalSymbolMap().getSymbols(); int count=0,total=0; while(it.hasNext()){ HighSymbol sym=it.next(); total++; if(count>=limit) continue; if(count>0) out.append(",\n"); out.append("    {\"name\": ").append(q(sym.getName())).append(", \"dataType\": ").append(q(sym.getDataType()==null?null:sym.getDataType().getDisplayName())).append(", \"kind\": ").append(q(sym.isParameter()?"parameter":"local")).append(", \"categoryIndex\": ").append(sym.getCategoryIndex()).append(", \"id\": ").append(sym.getId()).append("}"); count++; } out.append("\n  ],\n  \"emitted\": ").append(count).append(",\n  \"total\": ").append(total).append("\n}"); println("VEGVISIR_JSON:"+out.toString()); }
}
