From 0754cc4888bf96c77504c385d7aab0068202aa8f Mon Sep 17 00:00:00 2001
From: Nobuyoshi Nakada <nobu@ruby-lang.org>
Date: Tue, 27 Jul 2021 09:11:23 +0900
Subject: [PATCH] Added intern_ids.rb

---
 defs/id.def        | 26 ++++++++++++++++----------
 tool/intern_ids.rb | 35 +++++++++++++++++++++++++++++++++++
 2 files changed, 51 insertions(+), 10 deletions(-)
 create mode 100755 tool/intern_ids.rb

diff --git a/defs/id.def b/defs/id.def
index fc7a04ffbc..cf359c12b1 100644
--- a/defs/id.def
+++ b/defs/id.def
@@ -138,6 +138,21 @@ class KeywordError < RuntimeError
   end
 end
 
+def id2varname(token, prefix = nil)
+  if /#/ =~ token
+    token = "_#{token.gsub(/\W+/, '_')}"
+  else
+    token = token.sub(/\?/, 'P')
+    token = prefix + token if prefix
+    token.sub!(/\A[a-z]/) {$&.upcase}
+    token.sub!(/\A\$/, "_G_")
+    token.sub!(/\A@@/, "_C_")
+    token.sub!(/\A@/, "_I_")
+    token.gsub!(/\W+/, "")
+  end
+  token
+end
+
 predefined_ids = {}
 preserved_ids = []
 local_ids = []
@@ -153,16 +168,7 @@ predefined.split(/^/).each_with_index do |line, num|
   line.sub!(/\s+#.*/, '')
   name, token = line.split
   next unless name
-  token ||= name
-  if /#/ =~ token
-    token = "_#{token.gsub(/\W+/, '_')}"
-  else
-    token = token.sub(/\?/, 'P').sub(/\A[a-z]/) {$&.upcase}
-    token.sub!(/\A\$/, "_G_")
-    token.sub!(/\A@@/, "_C_")
-    token.sub!(/\A@/, "_I_")
-    token.gsub!(/\W+/, "")
-  end
+  token = id2varname(token || name)
   if name == '-'
     preserved_ids << token
     next
diff --git a/tool/intern_ids.rb b/tool/intern_ids.rb
new file mode 100755
index 0000000000..20483195e0
--- /dev/null
+++ b/tool/intern_ids.rb
@@ -0,0 +1,35 @@
+#!/usr/bin/ruby -sp
+# $ ruby -i tool/intern_ids.rb -prefix=_ foo.c
+
+BEGIN {
+  $prefix ||= nil
+
+  defs = File.join(File.dirname(__dir__), "defs/id.def")
+  ids = eval(File.read(defs), binding, defs)
+  table = {}
+  ids[:predefined].each {|v, t| table[t] = "id#{v}"}
+  ids[:token_op].each {|v, t, *| table[t] = "id#{v}"}
+  predefined = table.keys
+}
+
+$_.gsub!(/rb_intern\("([^\"]+)"\)/) do
+  token = $1
+  table[token] ||= "id" + id2varname(token, $prefix)
+end
+
+END {
+  predefined.each {|t| table.delete(t)}
+  unless table.empty?
+    table = table.sort_by {|t, v| v}
+
+    # Append at the last, then edit and move appropriately.
+    puts
+    puts "==== defs"
+    table.each {|t, v| puts "static ID #{v};"}
+    puts ">>>>"
+    puts
+    puts "==== init"
+    table.each {|t, v|puts "#{v} = rb_intern_const(\"#{t}\");"}
+    puts ">>>>"
+  end
+}