From 24c8a46b870bbd7feb69a918e9a66a3011ef5c14 Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Mon, 19 Feb 2024 18:32:34 +0200 Subject: initial play around with code generation from C to Go in Raku --- internal/generated/Makefile | 10 +++++-- internal/generated/generate.raku | 57 +++++++++++++++++++++++++++++++++++++++ internal/generated/types/types.go | 39 +++++++++++++++++++++++++++ 3 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 internal/generated/generate.raku create mode 100644 internal/generated/types/types.go diff --git a/internal/generated/Makefile b/internal/generated/Makefile index dd3c780..701d4f8 100644 --- a/internal/generated/Makefile +++ b/internal/generated/Makefile @@ -1,7 +1,13 @@ all: generate -.PHONY: generate -generate: +generate: types tracepoint_list + +.PHONY: types +types: + cat ../c/types.h | raku generate.raku nqctogo | tee types/types.go + +.PHONY: tracepoint_list +tracepoint_list: echo 'package generated' > tracepoint_list.go echo '' >> tracepoint_list.go echo 'var TracepointList = []string{' >> tracepoint_list.go diff --git a/internal/generated/generate.raku b/internal/generated/generate.raku new file mode 100644 index 0000000..babb655 --- /dev/null +++ b/internal/generated/generate.raku @@ -0,0 +1,57 @@ +#!/usr/bin/env raku +# +# This Raku program takes a list of C struct and constant definitions and converts +# it to valid Go code. + +#use Grammar::Debugger; + +# Not quite C +grammar NQC { + rule TOP { * } + rule construct { | || } + rule constant { '#define' } + rule statement { ';' } + rule struct { 'struct' '{' + %% ';' '}' } + rule member { ? } + rule comment { | } + rule single-line-comment { '//' <-[\n]>+ } + rule multi-line-comment { '/*' .*? '*/' } + token arraysize { '[' ']' } + token type { 'char' | '__s32' | '__u32' | '__u64' } + token identifier { <[a..z A..Z 0..9 _]>+ } + token number { \d+ } +} + +class NQCToGoActions { + method TOP($/) { make "package types\n\n" ~ $.map(*.made).join('') } + method construct($/) { make $.made // $.made // '' } + method statement($/) { make "\n" ~ $.made ~ "\n"; } + method constant($/) { make 'const ' ~ $ ~ ' = ' ~ $ ~ "\n" } + + method struct($/) { + make 'type ' ~ $.made ~ " struct \{\n\t" ~ + $.map(*.made).join("\n\t") ~ "\n\}" + } + + method member($/) { + make $.made ~ ' ' ~ ($ ?? $ !! '') ~ $.made + } + + method type($/) { + make do given ~$/ { + when 'char' { 'byte' } + when '__s32' { 'int32' } + when '__u32' { 'uint32' } + when '__u64' { 'uint64' } + }; + } + + method identifier($/) { + # Convert identifier from snake_case (C) to CamelCase (Go) + make $/.Str.split('_').map(*.tc).join('') + } +} + +multi sub MAIN('nqctogo') { + NQC.parse($*IN.slurp, :actions(NQCToGoActions.new)).made.say; +} diff --git a/internal/generated/types/types.go b/internal/generated/types/types.go new file mode 100644 index 0000000..ba384fe --- /dev/null +++ b/internal/generated/types/types.go @@ -0,0 +1,39 @@ +package types + +const MAX_PROGNAME_LENGTH = 16 +const OPENAT_ENTER_OP_ID = 1 +const OPENAT_EXIT_OP_ID = 2 +const OPEN_ENTER_OP_ID = 3 +const OPEN_EXIT_OP_ID = 4 +const CLOSE_ENTER_OP_ID = 5 +const CLOSE_EXIT_OP_ID = 6 +const WRITE_ENTER_OP_ID = 7 +const WRITE_EXIT_OP_ID = 8 +const WRITEV_ENTER_OP_ID = 9 +const WRITEV_EXIT_OP_ID = 10 + +type NullEvent struct { + OpId uint32 + PidTgid uint32 + Time uint64 +} + +type FdEvent struct { + OpId uint32 + PidTgid uint32 + Time uint64 + Fd int32 +} + +type OpenatEnterEvent struct { + OpId uint32 + PidTgid uint32 + Time uint64 + Filename [MAX_FILENAME_LENGTH]byte + Comm [MAX_PROGNAME_LENGTH]byte +} + +type Flags struct { + UidFilter uint32 +} + -- cgit v1.2.3