summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--.tool-versions1
-rw-r--r--Gemfile2
-rw-r--r--Gemfile.lock21
-rw-r--r--planning/structure.puml224
-rw-r--r--scan.rb83
-rw-r--r--src/backend/test.h12
-rw-r--r--src/backend/uctags.rb146
-rw-r--r--src/generate.rb (renamed from generate.rb)0
-rw-r--r--src/sample.config.rb (renamed from sample.config.rb)0
-rw-r--r--src/scan.rb85
-rw-r--r--src/templates.rb (renamed from templates.rb)0
11 files changed, 374 insertions, 200 deletions
diff --git a/.tool-versions b/.tool-versions
new file mode 100644
index 0000000..0b2d858
--- /dev/null
+++ b/.tool-versions
@@ -0,0 +1 @@
+ruby 3.1.2
diff --git a/Gemfile b/Gemfile
index f4b9259..527fc7f 100644
--- a/Gemfile
+++ b/Gemfile
@@ -4,4 +4,4 @@ source "https://rubygems.org"
# gem "rails"
-gem "activerecord", "~> 7.0"
+gem "cast", "~> 0.3.1"
diff --git a/Gemfile.lock b/Gemfile.lock
index 8184b71..c32dc74 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,28 +1,13 @@
GEM
remote: https://rubygems.org/
specs:
- activemodel (7.0.2.3)
- activesupport (= 7.0.2.3)
- activerecord (7.0.2.3)
- activemodel (= 7.0.2.3)
- activesupport (= 7.0.2.3)
- activesupport (7.0.2.3)
- concurrent-ruby (~> 1.0, >= 1.0.2)
- i18n (>= 1.6, < 2)
- minitest (>= 5.1)
- tzinfo (~> 2.0)
- concurrent-ruby (1.1.10)
- i18n (1.10.0)
- concurrent-ruby (~> 1.0)
- minitest (5.15.0)
- tzinfo (2.0.4)
- concurrent-ruby (~> 1.0)
+ cast (0.3.1)
PLATFORMS
x86_64-linux
DEPENDENCIES
- activerecord (~> 7.0)
+ cast (~> 0.3.1)
BUNDLED WITH
- 2.3.7
+ 2.3.20
diff --git a/planning/structure.puml b/planning/structure.puml
index 67cc77f..817a3bd 100644
--- a/planning/structure.puml
+++ b/planning/structure.puml
@@ -1,107 +1,107 @@
@startuml
- state Gem {
- state Headers
- state Structs #red {
- state Struct_Type_Init
- state Struct_Deinit #chocolate
- state "Struct Getter Method" as Struct_Getter #lawngreen {
- state fork_is_struct_getter <<fork>>
- state "Unwrap Struct\nand Read Value" as Unwrap_Struct_Getter
- state "Return Value" as Return_Struct_Getter
- state "Handle If Value\nIs Struct" as Handle_Struct_Value_Getter
-
- [*] -d-> Unwrap_Struct_Getter
- Unwrap_Struct_Getter -d-> fork_is_struct_getter
- fork_is_struct_getter -d-> Return_Struct_Getter
- fork_is_struct_getter -d-> Handle_Struct_Value_Getter
- Handle_Struct_Value_Getter -d-> Return_Struct_Getter
- }
- state "Struct Setter Method" as Struct_Setter #darkorchid {
- state "Initialize Vars" as Initialize_Vars_Setter
- state "Get and Assign\nArg" as Get_Arg_Setter
- state "Unwrap And Set" as Unwrap_Struct_Setter
- state "Return Var" as Return_Setter
-
- [*] -d-> Initialize_Vars_Setter
- Initialize_Vars_Setter -d-> Get_Arg_Setter
- Get_Arg_Setter -d-> Unwrap_Struct_Setter
- Unwrap_Struct_Setter -d-> Return_Setter
- }
- state Struct_Initializer as "Struct Initializer" #gold {
- state "Initialize Vars" as Initialize_Vars_Struct_Init
- state fork_kw_args_struct_init <<fork>>
- state "Get and Assign\nArg" as Get_Arg_Struct_Init
- state "Get and Assign\nKwargs" as Get_Kwargs_Struct_Init
- state "Build Struct" as Build_Struct_Struct_Init
- state "Wrap Struct" as Wrap_Struct_Struct_Init
- state "Return Ruby Object" as Return_Struct_Init
-
- [*] -d-> Initialize_Vars_Struct_Init
-
- Initialize_Vars_Struct_Init -d-> fork_kw_args_struct_init
-
- fork_kw_args_struct_init -d-> Get_Arg_Struct_Init
-
- fork_kw_args_struct_init -d-> Get_Kwargs_Struct_Init
-
- Get_Arg_Struct_Init -d-> Build_Struct_Struct_Init
- Get_Kwargs_Struct_Init -d-> Build_Struct_Struct_Init
-
- Build_Struct_Struct_Init -d-> Wrap_Struct_Struct_Init
-
- Wrap_Struct_Struct_Init -d-> Return_Struct_Init
- }
-
- Struct_Type_Init --> Struct_Deinit
+state Gem {
+ state Headers
+ state Structs #red {
+ state Struct_Type_Init
+ state Struct_Deinit #chocolate
+ state "Struct Getter Method" as Struct_Getter #lawngreen {
+ state fork_is_struct_getter <<fork>>
+ state "Unwrap Struct\nand Read Value" as Unwrap_Struct_Getter
+ state "Return Value" as Return_Struct_Getter
+ state "Handle If Value\nIs Struct" as Handle_Struct_Value_Getter
+ [*] -d-> Unwrap_Struct_Getter
+ Unwrap_Struct_Getter -d-> fork_is_struct_getter
+ fork_is_struct_getter -d-> Return_Struct_Getter
+ fork_is_struct_getter -d-> Handle_Struct_Value_Getter
+ Handle_Struct_Value_Getter -d-> Return_Struct_Getter
}
- state Methods #lightblue {
- state "Initialize Vars" as Initialize_Vars_C_Function
- state fork_kw_args_c_function <<fork>>
- state "Get and Assign Arg" as Get_Arg_C_Function
- state "Get and Assign Kwargs" as Get_Kwargs_C_Function
- state "Call Function" as Call_C_Function
- state fork_wrap_struct_c_function <<fork>>
- state "Wrap Struct" as Wrap_Struct_C_Function
- state "Return Value" as Return_C_Function
-
- [*] -d-> Initialize_Vars_C_Function
- [*] -d-> Call_C_Function
-
- Initialize_Vars_C_Function -d-> fork_kw_args_c_function
-
- fork_kw_args_c_function -d-> Get_Arg_C_Function
-
- fork_kw_args_c_function -d-> Get_Kwargs_C_Function
-
- Get_Arg_C_Function -d-> Call_C_Function
- Get_Kwargs_C_Function -d-> Call_C_Function
-
- Call_C_Function -d-> fork_wrap_struct_c_function
- fork_wrap_struct_c_function -d-> Wrap_Struct_C_Function
-
- fork_wrap_struct_c_function -d-> Return_C_Function
- Wrap_Struct_C_Function -d-> Return_C_Function
+ state "Struct Setter Method" as Struct_Setter #darkorchid {
+ state "Initialize Vars" as Initialize_Vars_Setter
+ state "Get and Assign\nArg" as Get_Arg_Setter
+ state "Unwrap And Set" as Unwrap_Struct_Setter
+ state "Return Var" as Return_Setter
+
+ [*] -d-> Initialize_Vars_Setter
+ Initialize_Vars_Setter -d-> Get_Arg_Setter
+ Get_Arg_Setter -d-> Unwrap_Struct_Setter
+ Unwrap_Struct_Setter -d-> Return_Setter
}
- state Gem_Initializer as "Gem Initializer" {
- state Define_Module as "Define Module" #crimson
- state Define_Struct_Classes as "Define Classes" #darkorange
- state Define_Struct_Methods as "Define Struct Methods" #hotpink
- state Define_Functions as "Define Functions" #lightblue
+ state Struct_Initializer as "Struct Initializer" #gold {
+ state "Initialize Vars" as Initialize_Vars_Struct_Init
+ state fork_kw_args_struct_init <<fork>>
+ state "Get and Assign\nArg" as Get_Arg_Struct_Init
+ state "Get and Assign\nKwargs" as Get_Kwargs_Struct_Init
+ state "Build Struct" as Build_Struct_Struct_Init
+ state "Wrap Struct" as Wrap_Struct_Struct_Init
+ state "Return Ruby Object" as Return_Struct_Init
+
+ [*] -d-> Initialize_Vars_Struct_Init
+
+ Initialize_Vars_Struct_Init -d-> fork_kw_args_struct_init
+
+ fork_kw_args_struct_init -d-> Get_Arg_Struct_Init
+
+ fork_kw_args_struct_init -d-> Get_Kwargs_Struct_Init
+
+ Get_Arg_Struct_Init -d-> Build_Struct_Struct_Init
+ Get_Kwargs_Struct_Init -d-> Build_Struct_Struct_Init
+
+ Build_Struct_Struct_Init -d-> Wrap_Struct_Struct_Init
+
+ Wrap_Struct_Struct_Init -d-> Return_Struct_Init
}
- state Gem_Finalizer as "Gem Finalizer"
-
-
- Headers -d-> Structs
- Structs -d-> Methods
- Methods -d-> Gem_Initializer
- Gem_Initializer -d-> Gem_Finalizer
-
- Define_Module -d-> Define_Struct_Classes
- Define_Struct_Classes -r-> Define_Struct_Methods
- Define_Struct_Classes -d-> Define_Functions
+
+ Struct_Type_Init --> Struct_Deinit
+
}
+ state Methods #lightblue {
+ state "Initialize Vars" as Initialize_Vars_C_Function
+ state fork_kw_args_c_function <<fork>>
+ state "Get and Assign Arg" as Get_Arg_C_Function
+ state "Get and Assign Kwargs" as Get_Kwargs_C_Function
+ state "Call Function" as Call_C_Function
+ state fork_wrap_struct_c_function <<fork>>
+ state "Wrap Struct" as Wrap_Struct_C_Function
+ state "Return Value" as Return_C_Function
+
+ [*] -d-> Initialize_Vars_C_Function
+ [*] -d-> Call_C_Function
+
+ Initialize_Vars_C_Function -d-> fork_kw_args_c_function
+
+ fork_kw_args_c_function -d-> Get_Arg_C_Function
+
+ fork_kw_args_c_function -d-> Get_Kwargs_C_Function
+
+ Get_Arg_C_Function -d-> Call_C_Function
+ Get_Kwargs_C_Function -d-> Call_C_Function
+
+ Call_C_Function -d-> fork_wrap_struct_c_function
+ fork_wrap_struct_c_function -d-> Wrap_Struct_C_Function
+
+ fork_wrap_struct_c_function -d-> Return_C_Function
+ Wrap_Struct_C_Function -d-> Return_C_Function
+ }
+ state Gem_Initializer as "Gem Initializer" {
+ state Define_Module as "Define Module" #crimson
+ state Define_Struct_Classes as "Define Classes" #darkorange
+ state Define_Struct_Methods as "Define Struct Methods" #hotpink
+ state Define_Functions as "Define Functions" #lightblue
+ }
+ state Gem_Finalizer as "Gem Finalizer"
+
+
+ Headers -d-> Structs
+ Structs -d-> Methods
+ Methods -d-> Gem_Initializer
+ Gem_Initializer -d-> Gem_Finalizer
+
+ Define_Module -d-> Define_Struct_Classes
+ Define_Struct_Classes -r-> Define_Struct_Methods
+ Define_Struct_Classes -d-> Define_Functions
+}
state Build_State as "Build State Hash" {
state BS_C_Gemname as "Gem Name" #crimson : string
@@ -137,7 +137,35 @@ state Build_State as "Build State Hash" {
BS_C_Function_Name -d[hidden]-> BS_C_Struct_Name
}
+state UCTags as "Universal Ctags Identifier" {
+ state UCT_KindIsProto as "Tag Kind Is\nPrototype"
+ state UCT_KindIsTypedef as "Tag Kind Is\nTypedef"
+ state UCT_KindIsMember as "Tag Kind Is\nMember"
+
+ state UCT_TyperefIsTypename as "Tag Typeref is\n'typename:{something}'"
+ state UCT_TyperefIsStruct as "Tag Typeref is\n'struct:{something}'"
+
+ state UCT_IsFunction as "It's a Function"
+ state UCT_IsStructParam as "It's a Struct\nParameter"
+ state UCT_IsTypedef as "It's an Alias\n(Typedef)"
+ state UCT_IsStruct as "It's a Struct"
+
+ [*] -d-> UCT_KindIsProto
+ [*] -d-> UCT_KindIsTypedef
+ [*] -d-> UCT_KindIsMember
+
+ UCT_KindIsProto -d-> UCT_IsFunction
+ UCT_KindIsMember -d-> UCT_IsStructParam
+
+ UCT_KindIsTypedef -d-> UCT_TyperefIsTypename
+ UCT_KindIsTypedef -d-> UCT_TyperefIsStruct
+ UCT_TyperefIsTypename -d-> UCT_IsStruct
+ UCT_TyperefIsStruct -d-> UCT_IsTypedef
+
+}
+
+
+
-
@enduml
diff --git a/scan.rb b/scan.rb
deleted file mode 100644
index 38dd95b..0000000
--- a/scan.rb
+++ /dev/null
@@ -1,83 +0,0 @@
-require 'json'
-
-#file_to_scan = 'raylib.h'
-
-class Scan
- class << self
- # ctags --list-kinds=c
- # p function prototypes
- # s structure names
- # z function parameters inside function or prototype definitions
- # m struct, and union members
- def ctag(file)
- `ctags --output-format=json --c-kinds=pm --fields=+S --language-force=c #{file}`
- end
- #File.write('json.json', parse)
- #$garbage = []
-
- def param_strip(signature)
- signature[1...-1].split(',')
- end
-
-
- def parse_header(path)
- parse = `ctags --output-format=json --c-kinds=pm --fields=+S --language-force=c #{path}`
- structs = {}
- functions = {}
- failed = []
- parse.each_line do |line|
- json_line = JSON.parse line
- if json_line['kind'] == 'prototype'
- functions["#{json_line['typeref'].sub(/^[^ ][^ ]* /,'')} #{json_line['name']}"] = param_strip(json_line['signature'])
- elsif json_line['kind'] == 'member'
- if json_line['scopeKind'] == 'struct'
- structs[json_line['scope']] ||= []
- structs[json_line['scope']].push "#{json_line['typeref'].delete_prefix('typename:')} #{json_line['name']}"
- else
- failed.push json_line
- end
- elsif json_line['kind'] == 'struct'
- structs[json_line['name']] = json_line
- else
- failed.push json_line
- end
- end
- [functions, structs, failed]
- end
-
-
- def debug_show(type, hash)
- puts "#{type.upcase}:"
- puts '---'
- hash.each do |key, params|
- puts "#{type.capitalize}: #{key}"
- params.each do |param|
- puts param
- end
- puts '---'
- end
- puts
- end
-
- def scan(file, destination)
- functions, structs, failed = parse_header(file)
- debug_show('functions', functions)
- debug_show('structs', structs)
-
- if !failed.empty?
- puts "-- Failed: --"
- pp failed
- puts
- end
-
- puts "Functions: #{functions.size}"
- puts "Structs: #{structs.size}"
- puts "Failed: #{failed.size}"
- puts
-
- result = [functions, structs]
-
- File.write(destination, JSON.generate(result))
- end
- end
-end
diff --git a/src/backend/test.h b/src/backend/test.h
new file mode 100644
index 0000000..c7b5ea9
--- /dev/null
+++ b/src/backend/test.h
@@ -0,0 +1,12 @@
+void InitWindow(int width, int height, const char *title);
+
+typedef struct Rectangle {
+ float height; // Rectangle height
+} Rectangle;
+
+typedef struct Texture {
+ unsigned int id; // OpenGL texture id
+ int format; // Data format (PixelFormat type)
+} Texture;
+
+typedef Texture Texture2D;
diff --git a/src/backend/uctags.rb b/src/backend/uctags.rb
new file mode 100644
index 0000000..0cfa3ee
--- /dev/null
+++ b/src/backend/uctags.rb
@@ -0,0 +1,146 @@
+require 'json'
+
+module FelBind
+ module Backends
+ class Intermediate < Hash
+
+ def initialize
+ self[:GemName] = ''
+ self[:Typedefs] = {}
+ self[:CFunctions] = {}
+ self[:CStructs] = {}
+ end
+
+ def add_function(name:, ruby_name: , ruby_class:, param_as_self: '')
+ #TODO
+ end
+
+ def add_struct
+ #TODO
+ end
+
+ def add_typedef
+ #TODO
+ end
+
+ def add_struct_param
+ #TODO
+ end
+
+ end
+
+ module UCTags
+ class << self
+
+ # ctags --list-kinds=c
+ # --c-kinds:
+ # p function prototypes
+ # (s structure names)
+ # (z function parameters inside function or prototype definitions)
+ # m struct, and union members
+ # t typedef
+ # --fields:
+ # S signature
+ def ctag(file)
+ `ctags --output-format=json --c-kinds=pmt --fields=+S --language-force=c #{file}`
+ end
+
+ def parse(file)
+ ctags_output = self.ctag(file).each_line.map do |tag|
+ JSON.parse tag
+ end
+ intermediate = FelBind::Backends::Intermediate.new
+
+ ctags_output.each do |tag|
+ if tag["kind"] == "prototype"
+ # its a function
+ puts 'its a function' #TODO remove
+ elsif tag["kind"] == "typedef"
+ if tag["typeref"].split(':').first == "typename"
+ # is a typedef
+ puts 'its an alias(typedef)' #TODO remove
+ elsif tag["typeref"].split(':').first == "struct"
+ # is a struct
+ puts 'its a struct' #TODO remove
+ else
+ puts "warning: no match" #TODO better errors
+ end
+ elsif tag['kind'] == 'member'
+ # is struct param
+ puts 'its a param' #TODO remove
+ else
+ puts "warning: no match" #TODO better errors
+ end
+ end
+
+ end
+
+=begin
+def param_strip(signature)
+ signature[1...-1].split(',')
+ end
+
+ def parse_header(path)
+ parse = `ctags --output-format=json --c-kinds=pm --fields=+S --language-force=c #{path}`
+ structs = {}
+ functions = {}
+ failed = []
+ parse.each_line do |line|
+ json_line = JSON.parse line
+ if json_line['kind'] == 'prototype'
+ functions["#{json_line['typeref'].sub(/^[^ ][^ ]* /,'')} #{json_line['name']}"] = param_strip(json_line['signature'])
+ elsif json_line['kind'] == 'member'
+ if json_line['scopeKind'] == 'struct'
+ structs[json_line['scope']] ||= []
+ structs[json_line['scope']].push "#{json_line['typeref'].delete_prefix('typename:')} #{json_line['name']}"
+ else
+ failed.push json_line
+ end
+ elsif json_line['kind'] == 'struct'
+ structs[json_line['name']] = json_line
+ else
+ failed.push json_line
+ end
+ end
+ [functions, structs, failed]
+ end
+
+
+ def debug_show(type, hash)
+ puts "#{type.upcase}:"
+ puts '---'
+ hash.each do |key, params|
+ puts "#{type.capitalize}: #{key}"
+ params.each do |param|
+ puts param
+ end
+ puts '---'
+ end
+ puts
+ end
+
+ def scan(file, destination)
+ functions, structs, failed = parse_header(file)
+ debug_show('functions', functions)
+ debug_show('structs', structs)
+
+ if !failed.empty?
+ puts "-- Failed: --"
+ pp failed
+ puts
+ end
+
+ puts "Functions: #{functions.size}"
+ puts "Structs: #{structs.size}"
+ puts "Failed: #{failed.size}"
+ puts
+
+ result = [functions, structs]
+
+ File.write(destination, JSON.generate(result))
+ end
+=end
+ end
+ end
+ end
+end
diff --git a/generate.rb b/src/generate.rb
index 4fa41be..4fa41be 100644
--- a/generate.rb
+++ b/src/generate.rb
diff --git a/sample.config.rb b/src/sample.config.rb
index 91d883b..91d883b 100644
--- a/sample.config.rb
+++ b/src/sample.config.rb
diff --git a/src/scan.rb b/src/scan.rb
new file mode 100644
index 0000000..9f9aede
--- /dev/null
+++ b/src/scan.rb
@@ -0,0 +1,85 @@
+require 'json'
+require 'cast'
+
+#file_to_scan = 'raylib.h'
+module FelBind
+ class Scan
+ class << self
+ # ctags --list-kinds=c
+ # p function prototypes
+ # s structure names
+ # z function parameters inside function or prototype definitions
+ # m struct, and union members
+ def ctag(file)
+ `ctags --output-format=json --c-kinds=pm --fields=+S --language-force=c #{file}`
+ end
+ #File.write('json.json', parse)
+ #$garbage = []
+
+ def param_strip(signature)
+ signature[1...-1].split(',')
+ end
+
+
+ def parse_header(path)
+ parse = `ctags --output-format=json --c-kinds=pm --fields=+S --language-force=c #{path}`
+ structs = {}
+ functions = {}
+ failed = []
+ parse.each_line do |line|
+ json_line = JSON.parse line
+ if json_line['kind'] == 'prototype'
+ functions["#{json_line['typeref'].sub(/^[^ ][^ ]* /,'')} #{json_line['name']}"] = param_strip(json_line['signature'])
+ elsif json_line['kind'] == 'member'
+ if json_line['scopeKind'] == 'struct'
+ structs[json_line['scope']] ||= []
+ structs[json_line['scope']].push "#{json_line['typeref'].delete_prefix('typename:')} #{json_line['name']}"
+ else
+ failed.push json_line
+ end
+ elsif json_line['kind'] == 'struct'
+ structs[json_line['name']] = json_line
+ else
+ failed.push json_line
+ end
+ end
+ [functions, structs, failed]
+ end
+
+
+ def debug_show(type, hash)
+ puts "#{type.upcase}:"
+ puts '---'
+ hash.each do |key, params|
+ puts "#{type.capitalize}: #{key}"
+ params.each do |param|
+ puts param
+ end
+ puts '---'
+ end
+ puts
+ end
+
+ def scan(file, destination)
+ functions, structs, failed = parse_header(file)
+ debug_show('functions', functions)
+ debug_show('structs', structs)
+
+ if !failed.empty?
+ puts "-- Failed: --"
+ pp failed
+ puts
+ end
+
+ puts "Functions: #{functions.size}"
+ puts "Structs: #{structs.size}"
+ puts "Failed: #{failed.size}"
+ puts
+
+ result = [functions, structs]
+
+ File.write(destination, JSON.generate(result))
+ end
+ end
+ end
+end
diff --git a/templates.rb b/src/templates.rb
index 7d88876..7d88876 100644
--- a/templates.rb
+++ b/src/templates.rb