1module Fiddle 2 # A mixin that provides methods for parsing C struct and prototype signatures. 3 # 4 # == Example 5 # require 'fiddle/import' 6 # 7 # include Fiddle::CParser 8 # #=> Object 9 # 10 # parse_ctype('int increment(int)') 11 # #=> ["increment", Fiddle::TYPE_INT, [Fiddle::TYPE_INT]] 12 # 13 module CParser 14 # Parses a C struct's members 15 # 16 # Example: 17 # 18 # include Fiddle::CParser 19 # #=> Object 20 # 21 # parse_struct_signature(['int i', 'char c']) 22 # #=> [[Fiddle::TYPE_INT, Fiddle::TYPE_CHAR], ["i", "c"]] 23 # 24 def parse_struct_signature(signature, tymap=nil) 25 if( signature.is_a?(String) ) 26 signature = signature.split(/\s*,\s*/) 27 end 28 mems = [] 29 tys = [] 30 signature.each{|msig| 31 tks = msig.split(/\s+(\*)?/) 32 ty = tks[0..-2].join(" ") 33 member = tks[-1] 34 35 case ty 36 when /\[(\d+)\]/ 37 n = $1.to_i 38 ty.gsub!(/\s*\[\d+\]/,"") 39 ty = [ty, n] 40 when /\[\]/ 41 ty.gsub!(/\s*\[\]/, "*") 42 end 43 44 case member 45 when /\[(\d+)\]/ 46 ty = [ty, $1.to_i] 47 member.gsub!(/\s*\[\d+\]/,"") 48 when /\[\]/ 49 ty = ty + "*" 50 member.gsub!(/\s*\[\]/, "") 51 end 52 53 mems.push(member) 54 tys.push(parse_ctype(ty,tymap)) 55 } 56 return tys, mems 57 end 58 59 # Parses a C prototype signature 60 # 61 # If Hash +tymap+ is provided, the return value and the arguments from the 62 # +signature+ are expected to be keys, and the value will be the C type to 63 # be looked up. 64 # 65 # Example: 66 # 67 # include Fiddle::CParser 68 # #=> Object 69 # 70 # parse_signature('double sum(double, double)') 71 # #=> ["sum", Fiddle::TYPE_DOUBLE, [Fiddle::TYPE_DOUBLE, Fiddle::TYPE_DOUBLE]] 72 # 73 def parse_signature(signature, tymap=nil) 74 tymap ||= {} 75 signature = signature.gsub(/\s+/, " ").strip 76 case signature 77 when /^([\w@\*\s]+)\(([\w\*\s\,\[\]]*)\)$/ 78 ret = $1 79 (args = $2).strip! 80 ret = ret.split(/\s+/) 81 args = args.split(/\s*,\s*/) 82 func = ret.pop 83 if( func =~ /^\*/ ) 84 func.gsub!(/^\*+/,"") 85 ret.push("*") 86 end 87 ret = ret.join(" ") 88 return [func, parse_ctype(ret, tymap), args.collect{|arg| parse_ctype(arg, tymap)}] 89 else 90 raise(RuntimeError,"can't parse the function prototype: #{signature}") 91 end 92 end 93 94 # Given a String of C type +ty+, returns the corresponding Fiddle constant. 95 # 96 # +ty+ can also accept an Array of C type Strings, and will be returned in 97 # a corresponding Array. 98 # 99 # If Hash +tymap+ is provided, +ty+ is expected to be the key, and the 100 # value will be the C type to be looked up. 101 # 102 # Example: 103 # 104 # include Fiddle::CParser 105 # #=> Object 106 # 107 # parse_ctype('int') 108 # #=> Fiddle::TYPE_INT 109 # 110 # parse_ctype('double') 111 # #=> Fiddle::TYPE_DOUBLE 112 # 113 # parse_ctype('unsigned char') 114 # #=> -Fiddle::TYPE_CHAR 115 # 116 def parse_ctype(ty, tymap=nil) 117 tymap ||= {} 118 case ty 119 when Array 120 return [parse_ctype(ty[0], tymap), ty[1]] 121 when "void" 122 return TYPE_VOID 123 when "char" 124 return TYPE_CHAR 125 when "unsigned char" 126 return -TYPE_CHAR 127 when "short" 128 return TYPE_SHORT 129 when "unsigned short" 130 return -TYPE_SHORT 131 when "int" 132 return TYPE_INT 133 when "unsigned int", 'uint' 134 return -TYPE_INT 135 when "long" 136 return TYPE_LONG 137 when "unsigned long" 138 return -TYPE_LONG 139 when "long long" 140 if( defined?(TYPE_LONG_LONG) ) 141 return TYPE_LONG_LONG 142 else 143 raise(RuntimeError, "unsupported type: #{ty}") 144 end 145 when "unsigned long long" 146 if( defined?(TYPE_LONG_LONG) ) 147 return -TYPE_LONG_LONG 148 else 149 raise(RuntimeError, "unsupported type: #{ty}") 150 end 151 when "float" 152 return TYPE_FLOAT 153 when "double" 154 return TYPE_DOUBLE 155 when "size_t" 156 return TYPE_SIZE_T 157 when "ssize_t" 158 return TYPE_SSIZE_T 159 when "ptrdiff_t" 160 return TYPE_PTRDIFF_T 161 when "intptr_t" 162 return TYPE_INTPTR_T 163 when "uintptr_t" 164 return TYPE_UINTPTR_T 165 when /\*/, /\[\s*\]/ 166 return TYPE_VOIDP 167 else 168 if( tymap[ty] ) 169 return parse_ctype(tymap[ty], tymap) 170 else 171 raise(DLError, "unknown type: #{ty}") 172 end 173 end 174 end 175 end 176end 177