diff --git a/chapi-ast-c/src/main/kotlin/chapi/ast/cast/CFullIdentListener.kt b/chapi-ast-c/src/main/kotlin/chapi/ast/cast/CFullIdentListener.kt index 2ef2ff7e..6ebd15d9 100644 --- a/chapi-ast-c/src/main/kotlin/chapi/ast/cast/CFullIdentListener.kt +++ b/chapi-ast-c/src/main/kotlin/chapi/ast/cast/CFullIdentListener.kt @@ -5,7 +5,7 @@ import chapi.domain.core.* open class CFullIdentListener(fileName: String) : CAstBaseListener() { private var currentDataStruct = CodeDataStruct() - private val defaultDataStruct = CodeDataStruct() + private val defaultDataStruct = CodeDataStruct(NodeName = "default") private var currentFunction = CodeFunction() private var structMap = mutableMapOf() private var codeContainer: CodeContainer = CodeContainer(FullName = fileName) @@ -116,7 +116,7 @@ open class CFullIdentListener(fileName: String) : CAstBaseListener() { currentFunction.Parameters = ctx.parameterTypeList().parameterList().parameterDeclaration().mapNotNull { val type = it.declarationSpecifier().firstOrNull()?.typeSpecifier()?.text - val name = it.declarator().directDeclarator()?.let { directDeclarator -> + val name = it.declarator()?.directDeclarator()?.let { directDeclarator -> when (directDeclarator) { is CParser.IdentifierDirectDeclaratorContext -> { directDeclarator.Identifier().text @@ -126,7 +126,7 @@ open class CFullIdentListener(fileName: String) : CAstBaseListener() { } } - val pointer = it.declarator().pointer()?.text ?: "" + val pointer = it.declarator()?.pointer()?.text ?: "" if (type != null && name != null) { CodeProperty(TypeValue = name, TypeType = type + pointer) @@ -158,7 +158,7 @@ open class CFullIdentListener(fileName: String) : CAstBaseListener() { currentFunction = CodeFunction(Position = buildPosition(ctx)) ctx?.declarationSpecifier()?.map { if (it.typeSpecifier().text != null) { - if (it.typeSpecifier().typedefName() != null) { + if (it.typeSpecifier()?.typedefName() != null) { currentFunction.Name = it.typeSpecifier().typedefName().text } else { currentFunction.ReturnType = it.typeSpecifier().text @@ -168,11 +168,9 @@ open class CFullIdentListener(fileName: String) : CAstBaseListener() { parseDirectDeclarator(ctx?.declarator()?.directDeclarator()) - if (currentFunction.Parameters.isEmpty()) return - // handle for a pointer - val firstParameter = currentFunction.Parameters[0] - if (firstParameter.TypeType.endsWith('*')) { + val firstParameter = currentFunction.Parameters.firstOrNull() + if (firstParameter?.TypeType?.endsWith('*') == true) { val baseType = firstParameter.TypeType.removeSuffix("*") structMap.getOrPut(baseType) { diff --git a/chapi-ast-c/src/test/kotlin/chapi/ast/cast/CFullIdentListenerTest.kt b/chapi-ast-c/src/test/kotlin/chapi/ast/cast/CFullIdentListenerTest.kt index 200d746a..102f7f07 100644 --- a/chapi-ast-c/src/test/kotlin/chapi/ast/cast/CFullIdentListenerTest.kt +++ b/chapi-ast-c/src/test/kotlin/chapi/ast/cast/CFullIdentListenerTest.kt @@ -241,5 +241,51 @@ typedef struct { val codeFile = CAnalyser().analysis(code, "helloworld.c") assertEquals(codeFile.Imports.size, 3) } -} + @Test + fun readlWorld() { + val code = """ + // https://stackoverflow.com/questions/12642830/can-i-define-a-function-inside-a-c-structure + #include + #include + #include + + struct point + { + int x; + int y; + void (*print)(const struct point*); + }; + + void print_x(const struct point* p) + { + printf("x=%d\n", p->x); + } + + void print_y(const struct point* p) + { + printf("y=%d\n", p->y); + } + + int main(void) + { + struct point p1 = { 2, 4, print_x }; + struct point p2 = { 7, 1, print_y }; + + p1.print(&p1); + p2.print(&p2); + + return 0; + } + """.trimIndent() + + val codeFile = CAnalyser().analysis(code, "helloworld.c") + assertEquals(codeFile.DataStructures.size, 2) + + assertEquals(codeFile.DataStructures[0].NodeName, "default") + assertEquals(codeFile.DataStructures[1].NodeName, "point") + + assertEquals(codeFile.DataStructures[0].Functions.size, 3) + assertEquals(codeFile.DataStructures[0].Functions[0].Name, "print_x") + } +}