#!/usr/bin/env ruby # encoding: utf-8 # ruby 2.6.5 =begin generates USB cables definitions in usb_cables.c define USB cable template as follows: static const uint8_t usb__a_host__b__abpower_pins[][2] = { {usb_a_host_pins[1], usb_b_device_pins[1]}, // VBUS {usb_a_host_pins[4], usb_b_device_pins[4]}, // GND }; any following variable declarations like static const uint8_t usb__a_device__b__abpower_pins[][2] will copy the array content from the first declaration and replace a_host with a_device and b with b this modified C file will be written to the path provided as argument =end class String # This method will return an array of MatchData's rather than the # array of strings returned by the vanilla `scan`. def match_all(regex) match_str = self match_datas = [] while match_str.length > 0 do md = match_str.match(regex) break unless md match_datas << md match_str = md.post_match end return match_datas end end # variable to process regexp cable_regex = /static const uint8_t (?usb__(?\w+)__(?\w+)__(?\w+)_(?pins|opts))\[\]\[2\] = (?\{[^;]+\});/m # read C definitions file usb_cables_text = IO.read("usb_cables.c") output_text = usb_cables_text.dup # get all variables to process cables = usb_cables_text.match_all(cable_regex) # go through variables cables.each_index do |i| next if 0 == i cable = cables[i] # find if there was a previously matching definition template = cables[0, i].filter {|c| c[:name] == cable[:name] and c[:type] == cable[:type]}.first next unless template puts "generate #{cable[:variable]} usng #{template[:variable]}" array = template[:array] array.gsub!(template[:connector1], cable[:connector1]) array.gsub!(template[:connector2], cable[:connector2]) generated = cable[0] generated.gsub!(cable[:array], array) puts generated puts output_text.gsub!(cable[0], generated) end if ARGV[0] then puts "saving to #{ARGV[0]}" File.open(ARGV[0], "w") {|f| f.write output_text} end