In a large C project there are many struct
s that have other struct
s, or pointers to them, as fields. I want to create a directed graph to show the dependencies between the "types". An example would be
typedef struct javaStat {
int idNo;
struct idIdentList *className;
struct typeModifiers *thisType;
struct symbol thisClass;
} ...
From this I would like to generate a DOT structure, which would look like
digraph {
javaStat -> idIdentList
javaStat -> typeModifiers
javaStat -> symbol
}
or, using a DOT short-hand:
digraph {
javaStat -> {idIdentList typeModifiers symbol}
}
Of course the first and last lines can be added by hand, so the primary problem is converting the struct references to the graph "pointer" lines.
At this point I'm content with a first level solution, meaning that deeper nesting could be ignored.
I first tried a simple grep struct *.h
which produced something workable:
typedef struct javaStat {
struct idIdentList *className;
struct typeModifiers *thisType;
struct symbol thisClass;
typedef struct <next struct> {
This is a simple problem which a few lines of Python would solve, but are there other handy solutions, perhaps using sed
, grep
, awk
and their brethren?
EDIT: I've realized that the reason I want to do this is because I need to find one or more structures that are at the base of the "struct tree".
Clang 9
allows for JSON representation of the AST of c
file (found it in this question). JSON AST could be processed further to generate the target output.
E.g. this Python
script:
#clang_ast_to_dot.py
from jsonpath_rw_ext import parse;
import sys, json;
def extract_struct_name(fieldDefinition):
return fieldDefinition["type"]["qualType"].replace("struct", "").replace("*", "").replace(" ","")
def is_struct_field(fieldDefinition, knownStructs):
return (fieldDefinition["kind"] == "FieldDecl" and
("struct " in fieldDefinition["type"]["qualType"] or
extract_struct_name(fieldDefinition) in knownStructs))
data = json.load(sys.stdin)
allStructs = {}
for structDef in parse('$.inner[?(@.kind=="RecordDecl")]').find(data):
allStructs[structDef.value["name"]]=structDef.value
print("digraph {")
for name, structDescription in allStructs.items():
print(" %s -> {%s}"
% (name, ", ".join(extract_struct_name(field) for field in structDescription["inner"] if is_struct_field(field, allStructs))))
print("}")
called as:
clang -Xclang -ast-dump=json MyCFile.c | python clang_ast_to_dot.py
produces:
digraph {
javaStat -> {idIdentList, typeModifiers, symbol}
}
Of course this is a toy example, I'm sure it won't work for all cases.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With