#!/usr/bin/env python3 # # Dumper for HFS/HFS+ images and files with non-ASCII # file names. # # See https://wiki.scummvm.org/index.php?title=HOWTO-Dump_Macintosh_Media for # the full documentation # # prerequisites: pip3 install machfs # # Development information: # This file contains tests. They can be run with: # $ pytest dumper-companion.py # # Code is formatted with `black ` import argparse import io import os import sys from binascii import crc_hqx from pathlib import Path from struct import pack, unpack from typing import Any, ByteString, List, Tuple import unicodedata import machfs if sys.platform == "darwin": try: import xattr except ImportError: print("xattr is required for the 'mac' mode to work\n") # fmt: off decode_map = { "81": [" ", "、", "。", ",", ".", "・", ":", ";", "?", "!", "゛", "゜", "´", "`", "¨", "^", " ̄", "_", "ヽ", "ヾ", "ゝ", "ゞ", "〃", "仝", "々", "〆", "〇", "ー", "—", "‐", "/", "\", "〜", "‖", "|", "…", "‥", "‘", "’", "“", "”", "(", ")", "〔", "〕", "[", "]", "{", "}", "〈", "〉", "《", "》", "「", "」", "『", "』", "【", "】", "+", "−", "±", "×", None, "÷", "=", "≠", "<", ">", "≦", "≧", "∞", "∴", "♂", "♀", "°", "′", "″", "℃", "¥", "$", "¢", "£", "%", "#", "&", "*", "@", "§", "☆", "★", "○", "●", "◎", "◇", "◆", "□", "■", "△", "▲", "▽", "▼", "※", "〒", "→", "←", "↑", "↓", "〓", None, None, None, None, None, None, None, None, None, None, None, "∈", "∋", "⊆", "⊇", "⊂", "⊃", "∪", "∩", None, None, None, None, None, None, None, None, "∧", "∨", "¬", "⇒", "⇔", "∀", "∃", None, None, None, None, None, None, None, None, None, None, None, "∠", "⊥", "⌒", "∂", "∇", "≡", "≒", "≪", "≫", "√", "∽", "∝", "∵", "∫", "∬", None, None, None, None, None, None, None, "Å", "‰", "♯", "♭", "♪", "†", "‡", "¶", None, None, None, None, "◯"], "82": [None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", None, None, None, None, None, None, None, "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", None, None, None, None, None, None, None, "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", None, None, None, None, "ぁ", "あ", "ぃ", "い", "ぅ", "う", "ぇ", "え", "ぉ", "お", "か", "が", "き", "ぎ", "く", "ぐ", "け", "げ", "こ", "ご", "さ", "ざ", "し", "じ", "す", "ず", "せ", "ぜ", "そ", "ぞ", "た", "だ", "ち", "ぢ", "っ", "つ", "づ", "て", "で", "と", "ど", "な", "に", "ぬ", "ね", "の", "は", "ば", "ぱ", "ひ", "び", "ぴ", "ふ", "ぶ", "ぷ", "へ", "べ", "ぺ", "ほ", "ぼ", "ぽ", "ま", "み", "む", "め", "も", "ゃ", "や", "ゅ", "ゆ", "ょ", "よ", "ら", "り", "る", "れ", "ろ", "ゎ", "わ", "ゐ", "ゑ", "を", "ん"], "83": ["ァ", "ア", "ィ", "イ", "ゥ", "ウ", "ェ", "エ", "ォ", "オ", "カ", "ガ", "キ", "ギ", "ク", "グ", "ケ", "ゲ", "コ", "ゴ", "サ", "ザ", "シ", "ジ", "ス", "ズ", "セ", "ゼ", "ソ", "ゾ", "タ", "ダ", "チ", "ヂ", "ッ", "ツ", "ヅ", "テ", "デ", "ト", "ド", "ナ", "ニ", "ヌ", "ネ", "ノ", "ハ", "バ", "パ", "ヒ", "ビ", "ピ", "フ", "ブ", "プ", "ヘ", "ベ", "ペ", "ホ", "ボ", "ポ", "マ", "ミ", None, "ム", "メ", "モ", "ャ", "ヤ", "ュ", "ユ", "ョ", "ヨ", "ラ", "リ", "ル", "レ", "ロ", "ヮ", "ワ", "ヰ", "ヱ", "ヲ", "ン", "ヴ", "ヵ", "ヶ", None, None, None, None, None, None, None, None, "Α", "Β", "Γ", "Δ", "Ε", "Ζ", "Η", "Θ", "Ι", "Κ", "Λ", "Μ", "Ν", "Ξ", "Ο", "Π", "Ρ", "Σ", "Τ", "Υ", "Φ", "Χ", "Ψ", "Ω", None, None, None, None, None, None, None, None, "α", "β", "γ", "δ", "ε", "ζ", "η", "θ", "ι", "κ", "λ", "μ", "ν", "ξ", "ο", "π", "ρ", "σ", "τ", "υ", "φ", "χ", "ψ", "ω"], "84": ["А", "Б", "В", "Г", "Д", "Е", "Ё", "Ж", "З", "И", "Й", "К", "Л", "М", "Н", "О", "П", "Р", "С", "Т", "У", "Ф", "Х", "Ц", "Ч", "Ш", "Щ", "Ъ", "Ы", "Ь", "Э", "Ю", "Я", None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, "а", "б", "в", "г", "д", "е", "ё", "ж", "з", "и", "й", "к", "л", "м", "н", None, "о", "п", "р", "с", "т", "у", "ф", "х", "ц", "ч", "ш", "щ", "ъ", "ы", "ь", "э", "ю", "я", None, None, None, None, None, None, None, None, None, None, None, None, None, "─", "│", "┌", "┐", "┘", "└", "├", "┬", "┤", "┴", "┼", "━", "┃", "┏", "┓", "┛", "┗", "┣", "┳", "┫", "┻", "╋", "┠", "┯", "┨", "┷", "┿", "┝", "┰", "┥", "┸", "╂"], "85": ["①", "②", "③", "④", "⑤", "⑥", "⑦", "⑧", "⑨", "⑩", "⑪", "⑫", "⑬", "⑭", "⑮", "⑯", "⑰", "⑱", "⑲", "⑳", None, None, None, None, None, None, None, None, None, None, "⑴", "⑵", "⑶", "⑷", "⑸", "⑹", "⑺", "⑻", "⑼", "⑽", "⑾", "⑿", "⒀", "⒁", "⒂", "⒃", "⒄", "⒅", "⒆", "⒇", None, None, None, None, None, None, None, None, None, None, "❶", "❷", "❸", None, "❹", "❺", "❻", "❼", "❽", "❾", None, None, None, None, None, None, None, None, None, None, None, "0.", "⒈", "⒉", "⒊", "⒋", "⒌", "⒍", "⒎", "⒏", "⒐", None, None, None, None, "Ⅰ", "Ⅱ", "Ⅲ", "Ⅳ", "Ⅴ", "Ⅵ", "Ⅶ", "Ⅷ", "Ⅸ", "Ⅹ", "Ⅺ", "Ⅻ", "XIII", "XIV", "XV", None, None, None, None, None, "ⅰ", "ⅱ", "ⅲ", "ⅳ", "ⅴ", "ⅵ", "ⅶ", "ⅷ", "ⅸ", "ⅹ", "ⅺ", "ⅻ", "xiii", "xiv", "xv", None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, "⒜", "⒝", "⒞", "⒟", "⒠", "⒡", "⒢", "⒣", "⒤", "⒥", "⒦", "⒧", "⒨", "⒩", "⒪", "⒫", "⒬", "⒭", "⒮", "⒯", "⒰", "⒱", "⒲", "⒳", "⒴", "⒵"], "86": ["㎜", "㎟", "㎝", "㎠", "㎤", "m", "㎡", "㎥", "㎞", "㎢", "㎎", "g", "㎏", "㏄", "㎖", "㎗", "ℓ", "㎘", "㎳", "㎲", "㎱", "㎰", "℉", "㏔", "㏋", "㎐", "㎅", "㎆", "㎇", "TB", None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, "№", "㏍", "℡", "FAX", "♤", "♧", "♡", "♢", "♠", "♣", "♥", "♦", None, None, None, None, None, None, None, None, None, None, None, None, "〠", "☎", "〄", None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, "☞", "☜", "☝", "☟", "⇆", "⇄", "⇅", "↓↑", "⇨", "⇦", "⇧", "⇩", "⇨", "⇦", "⇧", "⇩"], "87": ["㈰", "㈪", "㈫", "㈬", "㈭", "㈮", "㈯", "㉀", "㈷", "㉂", "㉃", "㈹", "㈺", "㈱", "㈾", "㈴", "㈲", "㈻", "㈶", "㈳", "㈵", "㈼", "㈽", "㈿", "㈸", None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, "大⃝", "小⃝", "㊤", "㊥", "㊦", "㊧", "㊨", "㊩", "㊖", "㊝", "㊘", "㊞", "控⃝", "㊙", "㍉", "㌢", "㍍", "㌔", "㌖", "㌅", "㌳", "㍎", "㌃", "㌶", "㌘", "㌕", "㌧", "㍑", "㍊", "㌹", "㍗", "㌍", "㍂", "㌣", "㌦", "㌻", "㌫", None, None, None, None, None, None, None, "㌀", "㌞", "㌪", "㌱", "㍇", None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, "㍾", "㍽", "㍼", "㍻", None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, "㍿", "有限会社", "財団法人"], "88": ["∮", "∟", "⊿", None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, "〝", "〟", None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, "ゔ", None, "ヷ", "ヸ", "ヹ", "ヺ", None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, "亜", "唖", "娃", "阿", "哀", "愛", "挨", "姶", "逢", "葵", "茜", "穐", "悪", "握", "渥", "旭", "葦", "芦", "鯵", "梓", "圧", "斡", "扱", "宛", "姐", "虻", "飴", "絢", "綾", "鮎", "或", "粟", "袷", "安", "庵", "按", "暗", "案", "闇", "鞍", "杏", "以", "伊", "位", "依", "偉", "囲", "夷", "委", "威", "尉", "惟", "意", "慰", "易", "椅", "為", "畏", "異", "移", "維", "緯", "胃", "萎", "衣", "謂", "違", "遺", "医", "井", "亥", "域", "育", "郁", "磯", "一", "壱", "溢", "逸", "稲", "茨", "芋", "鰯", "允", "印", "咽", "員", "因", "姻", "引", "飲", "淫", "胤", "蔭"], "89": ["院", "陰", "隠", "韻", "吋", "右", "宇", "烏", "羽", "迂", "雨", "卯", "鵜", "窺", "丑", "碓", "臼", "渦", "嘘", "唄", "欝", "蔚", "鰻", "姥", "厩", "浦", "瓜", "閏", "噂", "云", "運", "雲", "荏", "餌", "叡", "営", "嬰", "影", "映", "曳", "栄", "永", "泳", "洩", "瑛", "盈", "穎", "頴", "英", "衛", "詠", "鋭", "液", "疫", "益", "駅", "悦", "謁", "越", "閲", "榎", "厭", "円", None, "園", "堰", "奄", "宴", "延", "怨", "掩", "援", "沿", "演", "炎", "焔", "煙", "燕", "猿", "縁", "艶", "苑", "薗", "遠", "鉛", "鴛", "塩", "於", "汚", "甥", "凹", "央", "奥", "往", "応", "押", "旺", "横", "欧", "殴", "王", "翁", "襖", "鴬", "鴎", "黄", "岡", "沖", "荻", "億", "屋", "憶", "臆", "桶", "牡", "乙", "俺", "卸", "恩", "温", "穏", "音", "下", "化", "仮", "何", "伽", "価", "佳", "加", "可", "嘉", "夏", "嫁", "家", "寡", "科", "暇", "果", "架", "歌", "河", "火", "珂", "禍", "禾", "稼", "箇", "花", "苛", "茄", "荷", "華", "菓", "蝦", "課", "嘩", "貨", "迦", "過", "霞", "蚊", "俄", "峨", "我", "牙", "画", "臥", "芽", "蛾", "賀", "雅", "餓", "駕", "介", "会", "解", "回", "塊", "壊", "廻", "快", "怪", "悔", "恢", "懐", "戒", "拐", "改"], "8a": ["魁", "晦", "械", "海", "灰", "界", "皆", "絵", "芥", "蟹", "開", "階", "貝", "凱", "劾", "外", "咳", "害", "崖", "慨", "概", "涯", "碍", "蓋", "街", "該", "鎧", "骸", "浬", "馨", "蛙", "垣", "柿", "蛎", "鈎", "劃", "嚇", "各", "廓", "拡", "撹", "格", "核", "殻", "獲", "確", "穫", "覚", "角", "赫", "較", "郭", "閣", "隔", "革", "学", "岳", "楽", "額", "顎", "掛", "笠", "樫", None, "橿", "梶", "鰍", "潟", "割", "喝", "恰", "括", "活", "渇", "滑", "葛", "褐", "轄", "且", "鰹", "叶", "椛", "樺", "鞄", "株", "兜", "竃", "蒲", "釜", "鎌", "噛", "鴨", "栢", "茅", "萱", "粥", "刈", "苅", "瓦", "乾", "侃", "冠", "寒", "刊", "勘", "勧", "巻", "喚", "堪", "姦", "完", "官", "寛", "干", "幹", "患", "感", "慣", "憾", "換", "敢", "柑", "桓", "棺", "款", "歓", "汗", "漢", "澗", "潅", "環", "甘", "監", "看", "竿", "管", "簡", "緩", "缶", "翰", "肝", "艦", "莞", "観", "諌", "貫", "還", "鑑", "間", "閑", "関", "陥", "韓", "館", "舘", "丸", "含", "岸", "巌", "玩", "癌", "眼", "岩", "翫", "贋", "雁", "頑", "顔", "願", "企", "伎", "危", "喜", "器", "基", "奇", "嬉", "寄", "岐", "希", "幾", "忌", "揮", "机", "旗", "既", "期", "棋", "棄"], "8b": ["機", "帰", "毅", "気", "汽", "畿", "祈", "季", "稀", "紀", "徽", "規", "記", "貴", "起", "軌", "輝", "飢", "騎", "鬼", "亀", "偽", "儀", "妓", "宜", "戯", "技", "擬", "欺", "犠", "疑", "祇", "義", "蟻", "誼", "議", "掬", "菊", "鞠", "吉", "吃", "喫", "桔", "橘", "詰", "砧", "杵", "黍", "却", "客", "脚", "虐", "逆", "丘", "久", "仇", "休", "及", "吸", "宮", "弓", "急", "救", None, "朽", "求", "汲", "泣", "灸", "球", "究", "窮", "笈", "級", "糾", "給", "旧", "牛", "去", "居", "巨", "拒", "拠", "挙", "渠", "虚", "許", "距", "鋸", "漁", "禦", "魚", "亨", "享", "京", "供", "侠", "僑", "兇", "競", "共", "凶", "協", "匡", "卿", "叫", "喬", "境", "峡", "強", "彊", "怯", "恐", "恭", "挟", "教", "橋", "況", "狂", "狭", "矯", "胸", "脅", "興", "蕎", "郷", "鏡", "響", "饗", "驚", "仰", "凝", "尭", "暁", "業", "局", "曲", "極", "玉", "桐", "粁", "僅", "勤", "均", "巾", "錦", "斤", "欣", "欽", "琴", "禁", "禽", "筋", "緊", "芹", "菌", "衿", "襟", "謹", "近", "金", "吟", "銀", "九", "倶", "句", "区", "狗", "玖", "矩", "苦", "躯", "駆", "駈", "駒", "具", "愚", "虞", "喰", "空", "偶", "寓", "遇", "隅", "串", "櫛", "釧", "屑", "屈"], "8c": ["掘", "窟", "沓", "靴", "轡", "窪", "熊", "隈", "粂", "栗", "繰", "桑", "鍬", "勲", "君", "薫", "訓", "群", "軍", "郡", "卦", "袈", "祁", "係", "傾", "刑", "兄", "啓", "圭", "珪", "型", "契", "形", "径", "恵", "慶", "慧", "憩", "掲", "携", "敬", "景", "桂", "渓", "畦", "稽", "系", "経", "継", "繋", "罫", "茎", "荊", "蛍", "計", "詣", "警", "軽", "頚", "鶏", "芸", "迎", "鯨", None, "劇", "戟", "撃", "激", "隙", "桁", "傑", "欠", "決", "潔", "穴", "結", "血", "訣", "月", "件", "倹", "倦", "健", "兼", "券", "剣", "喧", "圏", "堅", "嫌", "建", "憲", "懸", "拳", "捲", "検", "権", "牽", "犬", "献", "研", "硯", "絹", "県", "肩", "見", "謙", "賢", "軒", "遣", "鍵", "険", "顕", "験", "鹸", "元", "原", "厳", "幻", "弦", "減", "源", "玄", "現", "絃", "舷", "言", "諺", "限", "乎", "個", "古", "呼", "固", "姑", "孤", "己", "庫", "弧", "戸", "故", "枯", "湖", "狐", "糊", "袴", "股", "胡", "菰", "虎", "誇", "跨", "鈷", "雇", "顧", "鼓", "五", "互", "伍", "午", "呉", "吾", "娯", "後", "御", "悟", "梧", "檎", "瑚", "碁", "語", "誤", "護", "醐", "乞", "鯉", "交", "佼", "侯", "候", "倖", "光", "公", "功", "効", "勾", "厚", "口", "向"], "8d": ["后", "喉", "坑", "垢", "好", "孔", "孝", "宏", "工", "巧", "巷", "幸", "広", "庚", "康", "弘", "恒", "慌", "抗", "拘", "控", "攻", "昂", "晃", "更", "杭", "校", "梗", "構", "江", "洪", "浩", "港", "溝", "甲", "皇", "硬", "稿", "糠", "紅", "紘", "絞", "綱", "耕", "考", "肯", "肱", "腔", "膏", "航", "荒", "行", "衡", "講", "貢", "購", "郊", "酵", "鉱", "砿", "鋼", "閤", "降", None, "項", "香", "高", "鴻", "剛", "劫", "号", "合", "壕", "拷", "濠", "豪", "轟", "麹", "克", "刻", "告", "国", "穀", "酷", "鵠", "黒", "獄", "漉", "腰", "甑", "忽", "惚", "骨", "狛", "込", "此", "頃", "今", "困", "坤", "墾", "婚", "恨", "懇", "昏", "昆", "根", "梱", "混", "痕", "紺", "艮", "魂", "些", "佐", "叉", "唆", "嵯", "左", "差", "査", "沙", "瑳", "砂", "詐", "鎖", "裟", "坐", "座", "挫", "債", "催", "再", "最", "哉", "塞", "妻", "宰", "彩", "才", "採", "栽", "歳", "済", "災", "采", "犀", "砕", "砦", "祭", "斎", "細", "菜", "裁", "載", "際", "剤", "在", "材", "罪", "財", "冴", "坂", "阪", "堺", "榊", "肴", "咲", "崎", "埼", "碕", "鷺", "作", "削", "咋", "搾", "昨", "朔", "柵", "窄", "策", "索", "錯", "桜", "鮭", "笹", "匙", "冊", "刷"], "8e": ["察", "拶", "撮", "擦", "札", "殺", "薩", "雑", "皐", "鯖", "捌", "錆", "鮫", "皿", "晒", "三", "傘", "参", "山", "惨", "撒", "散", "桟", "燦", "珊", "産", "算", "纂", "蚕", "讃", "賛", "酸", "餐", "斬", "暫", "残", "仕", "仔", "伺", "使", "刺", "司", "史", "嗣", "四", "士", "始", "姉", "姿", "子", "屍", "市", "師", "志", "思", "指", "支", "孜", "斯", "施", "旨", "枝", "止", None, "死", "氏", "獅", "祉", "私", "糸", "紙", "紫", "肢", "脂", "至", "視", "詞", "詩", "試", "誌", "諮", "資", "賜", "雌", "飼", "歯", "事", "似", "侍", "児", "字", "寺", "慈", "持", "時", "次", "滋", "治", "爾", "璽", "痔", "磁", "示", "而", "耳", "自", "蒔", "辞", "汐", "鹿", "式", "識", "鴫", "竺", "軸", "宍", "雫", "七", "叱", "執", "失", "嫉", "室", "悉", "湿", "漆", "疾", "質", "実", "蔀", "篠", "偲", "柴", "芝", "屡", "蕊", "縞", "舎", "写", "射", "捨", "赦", "斜", "煮", "社", "紗", "者", "謝", "車", "遮", "蛇", "邪", "借", "勺", "尺", "杓", "灼", "爵", "酌", "釈", "錫", "若", "寂", "弱", "惹", "主", "取", "守", "手", "朱", "殊", "狩", "珠", "種", "腫", "趣", "酒", "首", "儒", "受", "呪", "寿", "授", "樹", "綬", "需", "囚", "収", "周"], "8f": ["宗", "就", "州", "修", "愁", "拾", "洲", "秀", "秋", "終", "繍", "習", "臭", "舟", "蒐", "衆", "襲", "讐", "蹴", "輯", "週", "酋", "酬", "集", "醜", "什", "住", "充", "十", "従", "戎", "柔", "汁", "渋", "獣", "縦", "重", "銃", "叔", "夙", "宿", "淑", "祝", "縮", "粛", "塾", "熟", "出", "術", "述", "俊", "峻", "春", "瞬", "竣", "舜", "駿", "准", "循", "旬", "楯", "殉", "淳", None, "準", "潤", "盾", "純", "巡", "遵", "醇", "順", "処", "初", "所", "暑", "曙", "渚", "庶", "緒", "署", "書", "薯", "藷", "諸", "助", "叙", "女", "序", "徐", "恕", "鋤", "除", "傷", "償", "勝", "匠", "升", "召", "哨", "商", "唱", "嘗", "奨", "妾", "娼", "宵", "将", "小", "少", "尚", "庄", "床", "廠", "彰", "承", "抄", "招", "掌", "捷", "昇", "昌", "昭", "晶", "松", "梢", "樟", "樵", "沼", "消", "渉", "湘", "焼", "焦", "照", "症", "省", "硝", "礁", "祥", "称", "章", "笑", "粧", "紹", "肖", "菖", "蒋", "蕉", "衝", "裳", "訟", "証", "詔", "詳", "象", "賞", "醤", "鉦", "鍾", "鐘", "障", "鞘", "上", "丈", "丞", "乗", "冗", "剰", "城", "場", "壌", "嬢", "常", "情", "擾", "条", "杖", "浄", "状", "畳", "穣", "蒸", "譲", "醸", "錠", "嘱", "埴", "飾"], "90": ["拭", "植", "殖", "燭", "織", "職", "色", "触", "食", "蝕", "辱", "尻", "伸", "信", "侵", "唇", "娠", "寝", "審", "心", "慎", "振", "新", "晋", "森", "榛", "浸", "深", "申", "疹", "真", "神", "秦", "紳", "臣", "芯", "薪", "親", "診", "身", "辛", "進", "針", "震", "人", "仁", "刃", "塵", "壬", "尋", "甚", "尽", "腎", "訊", "迅", "陣", "靭", "笥", "諏", "須", "酢", "図", "厨", None, "逗", "吹", "垂", "帥", "推", "水", "炊", "睡", "粋", "翠", "衰", "遂", "酔", "錐", "錘", "随", "瑞", "髄", "崇", "嵩", "数", "枢", "趨", "雛", "据", "杉", "椙", "菅", "頗", "雀", "裾", "澄", "摺", "寸", "世", "瀬", "畝", "是", "凄", "制", "勢", "姓", "征", "性", "成", "政", "整", "星", "晴", "棲", "栖", "正", "清", "牲", "生", "盛", "精", "聖", "声", "製", "西", "誠", "誓", "請", "逝", "醒", "青", "静", "斉", "税", "脆", "隻", "席", "惜", "戚", "斥", "昔", "析", "石", "積", "籍", "績", "脊", "責", "赤", "跡", "蹟", "碩", "切", "拙", "接", "摂", "折", "設", "窃", "節", "説", "雪", "絶", "舌", "蝉", "仙", "先", "千", "占", "宣", "専", "尖", "川", "戦", "扇", "撰", "栓", "栴", "泉", "浅", "洗", "染", "潜", "煎", "煽", "旋", "穿", "箭", "線"], "91": ["繊", "羨", "腺", "舛", "船", "薦", "詮", "賎", "践", "選", "遷", "銭", "銑", "閃", "鮮", "前", "善", "漸", "然", "全", "禅", "繕", "膳", "糎", "噌", "塑", "岨", "措", "曾", "曽", "楚", "狙", "疏", "疎", "礎", "祖", "租", "粗", "素", "組", "蘇", "訴", "阻", "遡", "鼠", "僧", "創", "双", "叢", "倉", "喪", "壮", "奏", "爽", "宋", "層", "匝", "惣", "想", "捜", "掃", "挿", "掻", None, "操", "早", "曹", "巣", "槍", "槽", "漕", "燥", "争", "痩", "相", "窓", "糟", "総", "綜", "聡", "草", "荘", "葬", "蒼", "藻", "装", "走", "送", "遭", "鎗", "霜", "騒", "像", "増", "憎", "臓", "蔵", "贈", "造", "促", "側", "則", "即", "息", "捉", "束", "測", "足", "速", "俗", "属", "賊", "族", "続", "卒", "袖", "其", "揃", "存", "孫", "尊", "損", "村", "遜", "他", "多", "太", "汰", "詑", "唾", "堕", "妥", "惰", "打", "柁", "舵", "楕", "陀", "駄", "騨", "体", "堆", "対", "耐", "岱", "帯", "待", "怠", "態", "戴", "替", "泰", "滞", "胎", "腿", "苔", "袋", "貸", "退", "逮", "隊", "黛", "鯛", "代", "台", "大", "第", "醍", "題", "鷹", "滝", "瀧", "卓", "啄", "宅", "托", "択", "拓", "沢", "濯", "琢", "託", "鐸", "濁", "諾", "茸", "凧", "蛸", "只"], "92": ["叩", "但", "達", "辰", "奪", "脱", "巽", "竪", "辿", "棚", "谷", "狸", "鱈", "樽", "誰", "丹", "単", "嘆", "坦", "担", "探", "旦", "歎", "淡", "湛", "炭", "短", "端", "箪", "綻", "耽", "胆", "蛋", "誕", "鍛", "団", "壇", "弾", "断", "暖", "檀", "段", "男", "談", "値", "知", "地", "弛", "恥", "智", "池", "痴", "稚", "置", "致", "蜘", "遅", "馳", "築", "畜", "竹", "筑", "蓄", None, "逐", "秩", "窒", "茶", "嫡", "着", "中", "仲", "宙", "忠", "抽", "昼", "柱", "注", "虫", "衷", "註", "酎", "鋳", "駐", "樗", "瀦", "猪", "苧", "著", "貯", "丁", "兆", "凋", "喋", "寵", "帖", "帳", "庁", "弔", "張", "彫", "徴", "懲", "挑", "暢", "朝", "潮", "牒", "町", "眺", "聴", "脹", "腸", "蝶", "調", "諜", "超", "跳", "銚", "長", "頂", "鳥", "勅", "捗", "直", "朕", "沈", "珍", "賃", "鎮", "陳", "津", "墜", "椎", "槌", "追", "鎚", "痛", "通", "塚", "栂", "掴", "槻", "佃", "漬", "柘", "辻", "蔦", "綴", "鍔", "椿", "潰", "坪", "壷", "嬬", "紬", "爪", "吊", "釣", "鶴", "亭", "低", "停", "偵", "剃", "貞", "呈", "堤", "定", "帝", "底", "庭", "廷", "弟", "悌", "抵", "挺", "提", "梯", "汀", "碇", "禎", "程", "締", "艇", "訂", "諦", "蹄", "逓"], "93": ["邸", "鄭", "釘", "鼎", "泥", "摘", "擢", "敵", "滴", "的", "笛", "適", "鏑", "溺", "哲", "徹", "撤", "轍", "迭", "鉄", "典", "填", "天", "展", "店", "添", "纏", "甜", "貼", "転", "顛", "点", "伝", "殿", "澱", "田", "電", "兎", "吐", "堵", "塗", "妬", "屠", "徒", "斗", "杜", "渡", "登", "菟", "賭", "途", "都", "鍍", "砥", "砺", "努", "度", "土", "奴", "怒", "倒", "党", "冬", None, "凍", "刀", "唐", "塔", "塘", "套", "宕", "島", "嶋", "悼", "投", "搭", "東", "桃", "梼", "棟", "盗", "淘", "湯", "涛", "灯", "燈", "当", "痘", "祷", "等", "答", "筒", "糖", "統", "到", "董", "蕩", "藤", "討", "謄", "豆", "踏", "逃", "透", "鐙", "陶", "頭", "騰", "闘", "働", "動", "同", "堂", "導", "憧", "撞", "洞", "瞳", "童", "胴", "萄", "道", "銅", "峠", "鴇", "匿", "得", "徳", "涜", "特", "督", "禿", "篤", "毒", "独", "読", "栃", "橡", "凸", "突", "椴", "届", "鳶", "苫", "寅", "酉", "瀞", "噸", "屯", "惇", "敦", "沌", "豚", "遁", "頓", "呑", "曇", "鈍", "奈", "那", "内", "乍", "凪", "薙", "謎", "灘", "捺", "鍋", "楢", "馴", "縄", "畷", "南", "楠", "軟", "難", "汝", "二", "尼", "弐", "迩", "匂", "賑", "肉", "虹", "廿", "日", "乳", "入"], "94": ["如", "尿", "韮", "任", "妊", "忍", "認", "濡", "禰", "祢", "寧", "葱", "猫", "熱", "年", "念", "捻", "撚", "燃", "粘", "乃", "廼", "之", "埜", "嚢", "悩", "濃", "納", "能", "脳", "膿", "農", "覗", "蚤", "巴", "把", "播", "覇", "杷", "波", "派", "琶", "破", "婆", "罵", "芭", "馬", "俳", "廃", "拝", "排", "敗", "杯", "盃", "牌", "背", "肺", "輩", "配", "倍", "培", "媒", "梅", None, "楳", "煤", "狽", "買", "売", "賠", "陪", "這", "蝿", "秤", "矧", "萩", "伯", "剥", "博", "拍", "柏", "泊", "白", "箔", "粕", "舶", "薄", "迫", "曝", "漠", "爆", "縛", "莫", "駁", "麦", "函", "箱", "硲", "箸", "肇", "筈", "櫨", "幡", "肌", "畑", "畠", "八", "鉢", "溌", "発", "醗", "髪", "伐", "罰", "抜", "筏", "閥", "鳩", "噺", "塙", "蛤", "隼", "伴", "判", "半", "反", "叛", "帆", "搬", "斑", "板", "氾", "汎", "版", "犯", "班", "畔", "繁", "般", "藩", "販", "範", "釆", "煩", "頒", "飯", "挽", "晩", "番", "盤", "磐", "蕃", "蛮", "匪", "卑", "否", "妃", "庇", "彼", "悲", "扉", "批", "披", "斐", "比", "泌", "疲", "皮", "碑", "秘", "緋", "罷", "肥", "被", "誹", "費", "避", "非", "飛", "樋", "簸", "備", "尾", "微", "枇", "毘", "琵", "眉", "美"], "95": ["鼻", "柊", "稗", "匹", "疋", "髭", "彦", "膝", "菱", "肘", "弼", "必", "畢", "筆", "逼", "桧", "姫", "媛", "紐", "百", "謬", "俵", "彪", "標", "氷", "漂", "瓢", "票", "表", "評", "豹", "廟", "描", "病", "秒", "苗", "錨", "鋲", "蒜", "蛭", "鰭", "品", "彬", "斌", "浜", "瀕", "貧", "賓", "頻", "敏", "瓶", "不", "付", "埠", "夫", "婦", "富", "冨", "布", "府", "怖", "扶", "敷", None, "斧", "普", "浮", "父", "符", "腐", "膚", "芙", "譜", "負", "賦", "赴", "阜", "附", "侮", "撫", "武", "舞", "葡", "蕪", "部", "封", "楓", "風", "葺", "蕗", "伏", "副", "復", "幅", "服", "福", "腹", "複", "覆", "淵", "弗", "払", "沸", "仏", "物", "鮒", "分", "吻", "噴", "墳", "憤", "扮", "焚", "奮", "粉", "糞", "紛", "雰", "文", "聞", "丙", "併", "兵", "塀", "幣", "平", "弊", "柄", "並", "蔽", "閉", "陛", "米", "頁", "僻", "壁", "癖", "碧", "別", "瞥", "蔑", "箆", "偏", "変", "片", "篇", "編", "辺", "返", "遍", "便", "勉", "娩", "弁", "鞭", "保", "舗", "鋪", "圃", "捕", "歩", "甫", "補", "輔", "穂", "募", "墓", "慕", "戊", "暮", "母", "簿", "菩", "倣", "俸", "包", "呆", "報", "奉", "宝", "峰", "峯", "崩", "庖", "抱", "捧", "放", "方", "朋"], "96": ["法", "泡", "烹", "砲", "縫", "胞", "芳", "萌", "蓬", "蜂", "褒", "訪", "豊", "邦", "鋒", "飽", "鳳", "鵬", "乏", "亡", "傍", "剖", "坊", "妨", "帽", "忘", "忙", "房", "暴", "望", "某", "棒", "冒", "紡", "肪", "膨", "謀", "貌", "貿", "鉾", "防", "吠", "頬", "北", "僕", "卜", "墨", "撲", "朴", "牧", "睦", "穆", "釦", "勃", "没", "殆", "堀", "幌", "奔", "本", "翻", "凡", "盆", None, "摩", "磨", "魔", "麻", "埋", "妹", "昧", "枚", "毎", "哩", "槙", "幕", "膜", "枕", "鮪", "柾", "鱒", "桝", "亦", "俣", "又", "抹", "末", "沫", "迄", "侭", "繭", "麿", "万", "慢", "満", "漫", "蔓", "味", "未", "魅", "巳", "箕", "岬", "密", "蜜", "湊", "蓑", "稔", "脈", "妙", "粍", "民", "眠", "務", "夢", "無", "牟", "矛", "霧", "鵡", "椋", "婿", "娘", "冥", "名", "命", "明", "盟", "迷", "銘", "鳴", "姪", "牝", "滅", "免", "棉", "綿", "緬", "面", "麺", "摸", "模", "茂", "妄", "孟", "毛", "猛", "盲", "網", "耗", "蒙", "儲", "木", "黙", "目", "杢", "勿", "餅", "尤", "戻", "籾", "貰", "問", "悶", "紋", "門", "匁", "也", "冶", "夜", "爺", "耶", "野", "弥", "矢", "厄", "役", "約", "薬", "訳", "躍", "靖", "柳", "薮", "鑓", "愉", "愈", "油", "癒"], "97": ["諭", "輸", "唯", "佑", "優", "勇", "友", "宥", "幽", "悠", "憂", "揖", "有", "柚", "湧", "涌", "猶", "猷", "由", "祐", "裕", "誘", "遊", "邑", "郵", "雄", "融", "夕", "予", "余", "与", "誉", "輿", "預", "傭", "幼", "妖", "容", "庸", "揚", "揺", "擁", "曜", "楊", "様", "洋", "溶", "熔", "用", "窯", "羊", "耀", "葉", "蓉", "要", "謡", "踊", "遥", "陽", "養", "慾", "抑", "欲", None, "沃", "浴", "翌", "翼", "淀", "羅", "螺", "裸", "来", "莱", "頼", "雷", "洛", "絡", "落", "酪", "乱", "卵", "嵐", "欄", "濫", "藍", "蘭", "覧", "利", "吏", "履", "李", "梨", "理", "璃", "痢", "裏", "裡", "里", "離", "陸", "律", "率", "立", "葎", "掠", "略", "劉", "流", "溜", "琉", "留", "硫", "粒", "隆", "竜", "龍", "侶", "慮", "旅", "虜", "了", "亮", "僚", "両", "凌", "寮", "料", "梁", "涼", "猟", "療", "瞭", "稜", "糧", "良", "諒", "遼", "量", "陵", "領", "力", "緑", "倫", "厘", "林", "淋", "燐", "琳", "臨", "輪", "隣", "鱗", "麟", "瑠", "塁", "涙", "累", "類", "令", "伶", "例", "冷", "励", "嶺", "怜", "玲", "礼", "苓", "鈴", "隷", "零", "霊", "麗", "齢", "暦", "歴", "列", "劣", "烈", "裂", "廉", "恋", "憐", "漣", "煉", "簾", "練", "聯"], "98": ["蓮", "連", "錬", "呂", "魯", "櫓", "炉", "賂", "路", "露", "労", "婁", "廊", "弄", "朗", "楼", "榔", "浪", "漏", "牢", "狼", "篭", "老", "聾", "蝋", "郎", "六", "麓", "禄", "肋", "録", "論", "倭", "和", "話", "歪", "賄", "脇", "惑", "枠", "鷲", "亙", "亘", "鰐", "詫", "藁", "蕨", "椀", "湾", "碗", "腕", None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, "弌", "丐", "丕", "个", "丱", "丶", "丼", "丿", "乂", "乖", "乘", "亂", "亅", "豫", "亊", "舒", "弍", "于", "亞", "亟", "亠", "亢", "亰", "亳", "亶", "从", "仍", "仄", "仆", "仂", "仗", "仞", "仭", "仟", "价", "伉", "佚", "估", "佛", "佝", "佗", "佇", "佶", "侈", "侏", "侘", "佻", "佩", "佰", "侑", "佯", "來", "侖", "儘", "俔", "俟", "俎", "俘", "俛", "俑", "俚", "俐", "俤", "俥", "倚", "倨", "倔", "倪", "倥", "倅", "伜", "俶", "倡", "倩", "倬", "俾", "俯", "們", "倆", "偃", "假", "會", "偕", "偐", "偈", "做", "偖", "偬", "偸", "傀", "傚", "傅", "傴", "傲"], "99": ["僉", "僊", "傳", "僂", "僖", "僞", "僥", "僭", "僣", "僮", "價", "僵", "儉", "儁", "儂", "儖", "儕", "儔", "儚", "儡", "儺", "儷", "儼", "儻", "儿", "兀", "兒", "兌", "兔", "兢", "竸", "兩", "兪", "兮", "冀", "冂", "囘", "册", "冉", "冏", "冑", "冓", "冕", "冖", "冤", "冦", "冢", "冩", "冪", "冫", "决", "冱", "冲", "冰", "况", "冽", "凅", "凉", "凛", "几", "處", "凩", "凭", None, "凰", "凵", "凾", "刄", "刋", "刔", "刎", "刧", "刪", "刮", "刳", "刹", "剏", "剄", "剋", "剌", "剞", "剔", "剪", "剴", "剩", "剳", "剿", "剽", "劍", "劔", "劒", "剱", "劈", "劑", "辨", "辧", "劬", "劭", "劼", "劵", "勁", "勍", "勗", "勞", "勣", "勦", "飭", "勠", "勳", "勵", "勸", "勹", "匆", "匈", "甸", "匍", "匐", "匏", "匕", "匚", "匣", "匯", "匱", "匳", "匸", "區", "卆", "卅", "丗", "卉", "卍", "凖", "卞", "卩", "卮", "夘", "卻", "卷", "厂", "厖", "厠", "厦", "厥", "厮", "厰", "厶", "參", "簒", "雙", "叟", "曼", "燮", "叮", "叨", "叭", "叺", "吁", "吽", "呀", "听", "吭", "吼", "吮", "吶", "吩", "吝", "呎", "咏", "呵", "咎", "呟", "呱", "呷", "呰", "咒", "呻", "咀", "呶", "咄", "咐", "咆", "哇", "咢", "咸", "咥", "咬", "哄", "哈", "咨"], "9a": ["咫", "哂", "咤", "咾", "咼", "哘", "哥", "哦", "唏", "唔", "哽", "哮", "哭", "哺", "哢", "唹", "啀", "啣", "啌", "售", "啜", "啅", "啖", "啗", "唸", "唳", "啝", "喙", "喀", "咯", "喊", "喟", "啻", "啾", "喘", "喞", "單", "啼", "喃", "喩", "喇", "喨", "嗚", "嗅", "嗟", "嗄", "嗜", "嗤", "嗔", "嘔", "嗷", "嘖", "嗾", "嗽", "嘛", "嗹", "噎", "噐", "營", "嘴", "嘶", "嘲", "嘸", None, "噫", "噤", "嘯", "噬", "噪", "嚆", "嚀", "嚊", "嚠", "嚔", "嚏", "嚥", "嚮", "嚶", "嚴", "囂", "嚼", "囁", "囃", "囀", "囈", "囎", "囑", "囓", "囗", "囮", "囹", "圀", "囿", "圄", "圉", "圈", "國", "圍", "圓", "團", "圖", "嗇", "圜", "圦", "圷", "圸", "坎", "圻", "址", "坏", "坩", "埀", "垈", "坡", "坿", "垉", "垓", "垠", "垳", "垤", "垪", "垰", "埃", "埆", "埔", "埒", "埓", "堊", "埖", "埣", "堋", "堙", "堝", "塲", "堡", "塢", "塋", "塰", "毀", "塒", "堽", "塹", "墅", "墹", "墟", "墫", "墺", "壞", "墻", "墸", "墮", "壅", "壓", "壑", "壗", "壙", "壘", "壥", "壜", "壤", "壟", "壯", "壺", "壹", "壻", "壼", "壽", "夂", "夊", "夐", "夛", "梦", "夥", "夬", "夭", "夲", "夸", "夾", "竒", "奕", "奐", "奎", "奚", "奘", "奢", "奠", "奧", "奬", "奩"], "9b": ["奸", "妁", "妝", "佞", "侫", "妣", "妲", "姆", "姨", "姜", "妍", "姙", "姚", "娥", "娟", "娑", "娜", "娉", "娚", "婀", "婬", "婉", "娵", "娶", "婢", "婪", "媚", "媼", "媾", "嫋", "嫂", "媽", "嫣", "嫗", "嫦", "嫩", "嫖", "嫺", "嫻", "嬌", "嬋", "嬖", "嬲", "嫐", "嬪", "嬶", "嬾", "孃", "孅", "孀", "孑", "孕", "孚", "孛", "孥", "孩", "孰", "孳", "孵", "學", "斈", "孺", "宀", None, "它", "宦", "宸", "寃", "寇", "寉", "寔", "寐", "寤", "實", "寢", "寞", "寥", "寫", "寰", "寶", "寳", "尅", "將", "專", "對", "尓", "尠", "尢", "尨", "尸", "尹", "屁", "屆", "屎", "屓", "屐", "屏", "孱", "屬", "屮", "乢", "屶", "屹", "岌", "岑", "岔", "妛", "岫", "岻", "岶", "岼", "岷", "峅", "岾", "峇", "峙", "峩", "峽", "峺", "峭", "嶌", "峪", "崋", "崕", "崗", "嵜", "崟", "崛", "崑", "崔", "崢", "崚", "崙", "崘", "嵌", "嵒", "嵎", "嵋", "嵬", "嵳", "嵶", "嶇", "嶄", "嶂", "嶢", "嶝", "嶬", "嶮", "嶽", "嶐", "嶷", "嶼", "巉", "巍", "巓", "巒", "巖", "巛", "巫", "已", "巵", "帋", "帚", "帙", "帑", "帛", "帶", "帷", "幄", "幃", "幀", "幎", "幗", "幔", "幟", "幢", "幤", "幇", "幵", "并", "幺", "麼", "广", "庠", "廁", "廂", "廈", "廐", "廏"], "9c": ["廖", "廣", "廝", "廚", "廛", "廢", "廡", "廨", "廩", "廬", "廱", "廳", "廰", "廴", "廸", "廾", "弃", "弉", "彝", "彜", "弋", "弑", "弖", "弩", "弭", "弸", "彁", "彈", "彌", "彎", "弯", "彑", "彖", "彗", "彙", "彡", "彭", "彳", "彷", "徃", "徂", "彿", "徊", "很", "徑", "徇", "從", "徙", "徘", "徠", "徨", "徭", "徼", "忖", "忻", "忤", "忸", "忱", "忝", "悳", "忿", "怡", "恠", None, "怙", "怐", "怩", "怎", "怱", "怛", "怕", "怫", "怦", "怏", "怺", "恚", "恁", "恪", "恷", "恟", "恊", "恆", "恍", "恣", "恃", "恤", "恂", "恬", "恫", "恙", "悁", "悍", "惧", "悃", "悚", "悄", "悛", "悖", "悗", "悒", "悧", "悋", "惡", "悸", "惠", "惓", "悴", "忰", "悽", "惆", "悵", "惘", "慍", "愕", "愆", "惶", "惷", "愀", "惴", "惺", "愃", "愡", "惻", "惱", "愍", "愎", "慇", "愾", "愨", "愧", "慊", "愿", "愼", "愬", "愴", "愽", "慂", "慄", "慳", "慷", "慘", "慙", "慚", "慫", "慴", "慯", "慥", "慱", "慟", "慝", "慓", "慵", "憙", "憖", "憇", "憬", "憔", "憚", "憊", "憑", "憫", "憮", "懌", "懊", "應", "懷", "懈", "懃", "懆", "憺", "懋", "罹", "懍", "懦", "懣", "懶", "懺", "懴", "懿", "懽", "懼", "懾", "戀", "戈", "戉", "戍", "戌", "戔", "戛"], "9d": ["戞", "戡", "截", "戮", "戰", "戲", "戳", "扁", "扎", "扞", "扣", "扛", "扠", "扨", "扼", "抂", "抉", "找", "抒", "抓", "抖", "拔", "抃", "抔", "拗", "拑", "抻", "拏", "拿", "拆", "擔", "拈", "拜", "拌", "拊", "拂", "拇", "抛", "拉", "挌", "拮", "拱", "挧", "挂", "挈", "拯", "拵", "捐", "挾", "捍", "搜", "捏", "掖", "掎", "掀", "掫", "捶", "掣", "掏", "掉", "掟", "掵", "捫", None, "捩", "掾", "揩", "揀", "揆", "揣", "揉", "插", "揶", "揄", "搖", "搴", "搆", "搓", "搦", "搶", "攝", "搗", "搨", "搏", "摧", "摯", "摶", "摎", "攪", "撕", "撓", "撥", "撩", "撈", "撼", "據", "擒", "擅", "擇", "撻", "擘", "擂", "擱", "擧", "舉", "擠", "擡", "抬", "擣", "擯", "攬", "擶", "擴", "擲", "擺", "攀", "擽", "攘", "攜", "攅", "攤", "攣", "攫", "攴", "攵", "攷", "收", "攸", "畋", "效", "敖", "敕", "敍", "敘", "敞", "敝", "敲", "數", "斂", "斃", "變", "斛", "斟", "斫", "斷", "旃", "旆", "旁", "旄", "旌", "旒", "旛", "旙", "无", "旡", "旱", "杲", "昊", "昃", "旻", "杳", "昵", "昶", "昴", "昜", "晏", "晄", "晉", "晁", "晞", "晝", "晤", "晧", "晨", "晟", "晢", "晰", "暃", "暈", "暎", "暉", "暄", "暘", "暝", "曁", "暹", "曉", "暾", "暼"], "9e": ["曄", "暸", "曖", "曚", "曠", "昿", "曦", "曩", "曰", "曵", "曷", "朏", "朖", "朞", "朦", "朧", "霸", "朮", "朿", "朶", "杁", "朸", "朷", "杆", "杞", "杠", "杙", "杣", "杤", "枉", "杰", "枩", "杼", "杪", "枌", "枋", "枦", "枡", "枅", "枷", "柯", "枴", "柬", "枳", "柩", "枸", "柤", "柞", "柝", "柢", "柮", "枹", "柎", "柆", "柧", "檜", "栞", "框", "栩", "桀", "桍", "栲", "桎", None, "梳", "栫", "桙", "档", "桷", "桿", "梟", "梏", "梭", "梔", "條", "梛", "梃", "檮", "梹", "桴", "梵", "梠", "梺", "椏", "梍", "桾", "椁", "棊", "椈", "棘", "椢", "椦", "棡", "椌", "棍", "棔", "棧", "棕", "椶", "椒", "椄", "棗", "棣", "椥", "棹", "棠", "棯", "椨", "椪", "椚", "椣", "椡", "棆", "楹", "楷", "楜", "楸", "楫", "楔", "楾", "楮", "椹", "楴", "椽", "楙", "椰", "楡", "楞", "楝", "榁", "楪", "榲", "榮", "槐", "榿", "槁", "槓", "榾", "槎", "寨", "槊", "槝", "榻", "槃", "榧", "樮", "榑", "榠", "榜", "榕", "榴", "槞", "槨", "樂", "樛", "槿", "權", "槹", "槲", "槧", "樅", "榱", "樞", "槭", "樔", "槫", "樊", "樒", "櫁", "樣", "樓", "橄", "樌", "橲", "樶", "橸", "橇", "橢", "橙", "橦", "橈", "樸", "樢", "檐", "檍", "檠", "檄", "檢", "檣"], "9f": ["檗", "蘗", "檻", "櫃", "櫂", "檸", "檳", "檬", "櫞", "櫑", "櫟", "檪", "櫚", "櫪", "櫻", "欅", "蘖", "櫺", "欒", "欖", "鬱", "欟", "欸", "欷", "盜", "欹", "飮", "歇", "歃", "歉", "歐", "歙", "歔", "歛", "歟", "歡", "歸", "歹", "歿", "殀", "殄", "殃", "殍", "殘", "殕", "殞", "殤", "殪", "殫", "殯", "殲", "殱", "殳", "殷", "殼", "毆", "毋", "毓", "毟", "毬", "毫", "毳", "毯", None, "麾", "氈", "氓", "气", "氛", "氤", "氣", "汞", "汕", "汢", "汪", "沂", "沍", "沚", "沁", "沛", "汾", "汨", "汳", "沒", "沐", "泄", "泱", "泓", "沽", "泗", "泅", "泝", "沮", "沱", "沾", "沺", "泛", "泯", "泙", "泪", "洟", "衍", "洶", "洫", "洽", "洸", "洙", "洵", "洳", "洒", "洌", "浣", "涓", "浤", "浚", "浹", "浙", "涎", "涕", "濤", "涅", "淹", "渕", "渊", "涵", "淇", "淦", "涸", "淆", "淬", "淞", "淌", "淨", "淒", "淅", "淺", "淙", "淤", "淕", "淪", "淮", "渭", "湮", "渮", "渙", "湲", "湟", "渾", "渣", "湫", "渫", "湶", "湍", "渟", "湃", "渺", "湎", "渤", "滿", "渝", "游", "溂", "溪", "溘", "滉", "溷", "滓", "溽", "溯", "滄", "溲", "滔", "滕", "溏", "溥", "滂", "溟", "潁", "漑", "灌", "滬", "滸", "滾", "漿", "滲", "漱", "滯", "漲", "滌"], "e0": ["漾", "漓", "滷", "澆", "潺", "潸", "澁", "澀", "潯", "潛", "濳", "潭", "澂", "潼", "潘", "澎", "澑", "濂", "潦", "澳", "澣", "澡", "澤", "澹", "濆", "澪", "濟", "濕", "濬", "濔", "濘", "濱", "濮", "濛", "瀉", "瀋", "濺", "瀑", "瀁", "瀏", "濾", "瀛", "瀚", "潴", "瀝", "瀘", "瀟", "瀰", "瀾", "瀲", "灑", "灣", "炙", "炒", "炯", "烱", "炬", "炸", "炳", "炮", "烟", "烋", "烝", None, "烙", "焉", "烽", "焜", "焙", "煥", "煕", "熈", "煦", "煢", "煌", "煖", "煬", "熏", "燻", "熄", "熕", "熨", "熬", "燗", "熹", "熾", "燒", "燉", "燔", "燎", "燠", "燬", "燧", "燵", "燼", "燹", "燿", "爍", "爐", "爛", "爨", "爭", "爬", "爰", "爲", "爻", "爼", "爿", "牀", "牆", "牋", "牘", "牴", "牾", "犂", "犁", "犇", "犒", "犖", "犢", "犧", "犹", "犲", "狃", "狆", "狄", "狎", "狒", "狢", "狠", "狡", "狹", "狷", "倏", "猗", "猊", "猜", "猖", "猝", "猴", "猯", "猩", "猥", "猾", "獎", "獏", "默", "獗", "獪", "獨", "獰", "獸", "獵", "獻", "獺", "珈", "玳", "珎", "玻", "珀", "珥", "珮", "珞", "璢", "琅", "瑯", "琥", "珸", "琲", "琺", "瑕", "琿", "瑟", "瑙", "瑁", "瑜", "瑩", "瑰", "瑣", "瑪", "瑶", "瑾", "璋", "璞", "璧", "瓊", "瓏", "瓔", "珱"], "e1": ["瓠", "瓣", "瓧", "瓩", "瓮", "瓲", "瓰", "瓱", "瓸", "瓷", "甄", "甃", "甅", "甌", "甎", "甍", "甕", "甓", "甞", "甦", "甬", "甼", "畄", "畍", "畊", "畉", "畛", "畆", "畚", "畩", "畤", "畧", "畫", "畭", "畸", "當", "疆", "疇", "畴", "疊", "疉", "疂", "疔", "疚", "疝", "疥", "疣", "痂", "疳", "痃", "疵", "疽", "疸", "疼", "疱", "痍", "痊", "痒", "痙", "痣", "痞", "痾", "痿", None, "痼", "瘁", "痰", "痺", "痲", "痳", "瘋", "瘍", "瘉", "瘟", "瘧", "瘠", "瘡", "瘢", "瘤", "瘴", "瘰", "瘻", "癇", "癈", "癆", "癜", "癘", "癡", "癢", "癨", "癩", "癪", "癧", "癬", "癰", "癲", "癶", "癸", "發", "皀", "皃", "皈", "皋", "皎", "皖", "皓", "皙", "皚", "皰", "皴", "皸", "皹", "皺", "盂", "盍", "盖", "盒", "盞", "盡", "盥", "盧", "盪", "蘯", "盻", "眈", "眇", "眄", "眩", "眤", "眞", "眥", "眦", "眛", "眷", "眸", "睇", "睚", "睨", "睫", "睛", "睥", "睿", "睾", "睹", "瞎", "瞋", "瞑", "瞠", "瞞", "瞰", "瞶", "瞹", "瞿", "瞼", "瞽", "瞻", "矇", "矍", "矗", "矚", "矜", "矣", "矮", "矼", "砌", "砒", "礦", "砠", "礪", "硅", "碎", "硴", "碆", "硼", "碚", "碌", "碣", "碵", "碪", "碯", "磑", "磆", "磋", "磔", "碾", "碼", "磅", "磊", "磬"], "e2": ["磧", "磚", "磽", "磴", "礇", "礒", "礑", "礙", "礬", "礫", "祀", "祠", "祗", "祟", "祚", "祕", "祓", "祺", "祿", "禊", "禝", "禧", "齋", "禪", "禮", "禳", "禹", "禺", "秉", "秕", "秧", "秬", "秡", "秣", "稈", "稍", "稘", "稙", "稠", "稟", "禀", "稱", "稻", "稾", "稷", "穃", "穗", "穉", "穡", "穢", "穩", "龝", "穰", "穹", "穽", "窈", "窗", "窕", "窘", "窖", "窩", "竈", "窰", None, "窶", "竅", "竄", "窿", "邃", "竇", "竊", "竍", "竏", "竕", "竓", "站", "竚", "竝", "竡", "竢", "竦", "竭", "竰", "笂", "笏", "笊", "笆", "笳", "笘", "笙", "笞", "笵", "笨", "笶", "筐", "筺", "笄", "筍", "笋", "筌", "筅", "筵", "筥", "筴", "筧", "筰", "筱", "筬", "筮", "箝", "箘", "箟", "箍", "箜", "箚", "箋", "箒", "箏", "筝", "箙", "篋", "篁", "篌", "篏", "箴", "篆", "篝", "篩", "簑", "簔", "篦", "篥", "籠", "簀", "簇", "簓", "篳", "篷", "簗", "簍", "篶", "簣", "簧", "簪", "簟", "簷", "簫", "簽", "籌", "籃", "籔", "籏", "籀", "籐", "籘", "籟", "籤", "籖", "籥", "籬", "籵", "粃", "粐", "粤", "粭", "粢", "粫", "粡", "粨", "粳", "粲", "粱", "粮", "粹", "粽", "糀", "糅", "糂", "糘", "糒", "糜", "糢", "鬻", "糯", "糲", "糴", "糶", "糺", "紆"], "e3": ["紂", "紜", "紕", "紊", "絅", "絋", "紮", "紲", "紿", "紵", "絆", "絳", "絖", "絎", "絲", "絨", "絮", "絏", "絣", "經", "綉", "絛", "綏", "絽", "綛", "綺", "綮", "綣", "綵", "緇", "綽", "綫", "總", "綢", "綯", "緜", "綸", "綟", "綰", "緘", "緝", "緤", "緞", "緻", "緲", "緡", "縅", "縊", "縣", "縡", "縒", "縱", "縟", "縉", "縋", "縢", "繆", "繦", "縻", "縵", "縹", "繃", "縷", None, "縲", "縺", "繧", "繝", "繖", "繞", "繙", "繚", "繹", "繪", "繩", "繼", "繻", "纃", "緕", "繽", "辮", "繿", "纈", "纉", "續", "纒", "纐", "纓", "纔", "纖", "纎", "纛", "纜", "缸", "缺", "罅", "罌", "罍", "罎", "罐", "网", "罕", "罔", "罘", "罟", "罠", "罨", "罩", "罧", "罸", "羂", "羆", "羃", "羈", "羇", "羌", "羔", "羞", "羝", "羚", "羣", "羯", "羲", "羹", "羮", "羶", "羸", "譱", "翅", "翆", "翊", "翕", "翔", "翡", "翦", "翩", "翳", "翹", "飜", "耆", "耄", "耋", "耒", "耘", "耙", "耜", "耡", "耨", "耿", "耻", "聊", "聆", "聒", "聘", "聚", "聟", "聢", "聨", "聳", "聲", "聰", "聶", "聹", "聽", "聿", "肄", "肆", "肅", "肛", "肓", "肚", "肭", "冐", "肬", "胛", "胥", "胙", "胝", "胄", "胚", "胖", "脉", "胯", "胱", "脛", "脩", "脣", "脯", "腋"], "e4": ["隋", "腆", "脾", "腓", "腑", "胼", "腱", "腮", "腥", "腦", "腴", "膃", "膈", "膊", "膀", "膂", "膠", "膕", "膤", "膣", "腟", "膓", "膩", "膰", "膵", "膾", "膸", "膽", "臀", "臂", "膺", "臉", "臍", "臑", "臙", "臘", "臈", "臚", "臟", "臠", "臧", "臺", "臻", "臾", "舁", "舂", "舅", "與", "舊", "舍", "舐", "舖", "舩", "舫", "舸", "舳", "艀", "艙", "艘", "艝", "艚", "艟", "艤", None, "艢", "艨", "艪", "艫", "舮", "艱", "艷", "艸", "艾", "芍", "芒", "芫", "芟", "芻", "芬", "苡", "苣", "苟", "苒", "苴", "苳", "苺", "莓", "范", "苻", "苹", "苞", "茆", "苜", "茉", "苙", "茵", "茴", "茖", "茲", "茱", "荀", "茹", "荐", "荅", "茯", "茫", "茗", "茘", "莅", "莚", "莪", "莟", "莢", "莖", "茣", "莎", "莇", "莊", "荼", "莵", "荳", "荵", "莠", "莉", "莨", "菴", "萓", "菫", "菎", "菽", "萃", "菘", "萋", "菁", "菷", "萇", "菠", "菲", "萍", "萢", "萠", "莽", "萸", "蔆", "菻", "葭", "萪", "萼", "蕚", "蒄", "葷", "葫", "蒭", "葮", "蒂", "葩", "葆", "萬", "葯", "葹", "萵", "蓊", "葢", "蒹", "蒿", "蒟", "蓙", "蓍", "蒻", "蓚", "蓐", "蓁", "蓆", "蓖", "蒡", "蔡", "蓿", "蓴", "蔗", "蔘", "蔬", "蔟", "蔕", "蔔", "蓼", "蕀", "蕣", "蕘", "蕈"], "e5": ["蕁", "蘂", "蕋", "蕕", "薀", "薤", "薈", "薑", "薊", "薨", "蕭", "薔", "薛", "藪", "薇", "薜", "蕷", "蕾", "薐", "藉", "薺", "藏", "薹", "藐", "藕", "藝", "藥", "藜", "藹", "蘊", "蘓", "蘋", "藾", "藺", "蘆", "蘢", "蘚", "蘰", "蘿", "虍", "乕", "虔", "號", "虧", "虱", "蚓", "蚣", "蚩", "蚪", "蚋", "蚌", "蚶", "蚯", "蛄", "蛆", "蚰", "蛉", "蠣", "蚫", "蛔", "蛞", "蛩", "蛬", None, "蛟", "蛛", "蛯", "蜒", "蜆", "蜈", "蜀", "蜃", "蛻", "蜑", "蜉", "蜍", "蛹", "蜊", "蜴", "蜿", "蜷", "蜻", "蜥", "蜩", "蜚", "蝠", "蝟", "蝸", "蝌", "蝎", "蝴", "蝗", "蝨", "蝮", "蝙", "蝓", "蝣", "蝪", "蠅", "螢", "螟", "螂", "螯", "蟋", "螽", "蟀", "蟐", "雖", "螫", "蟄", "螳", "蟇", "蟆", "螻", "蟯", "蟲", "蟠", "蠏", "蠍", "蟾", "蟶", "蟷", "蠎", "蟒", "蠑", "蠖", "蠕", "蠢", "蠡", "蠱", "蠶", "蠹", "蠧", "蠻", "衄", "衂", "衒", "衙", "衞", "衢", "衫", "袁", "衾", "袞", "衵", "衽", "袵", "衲", "袂", "袗", "袒", "袮", "袙", "袢", "袍", "袤", "袰", "袿", "袱", "裃", "裄", "裔", "裘", "裙", "裝", "裹", "褂", "裼", "裴", "裨", "裲", "褄", "褌", "褊", "褓", "襃", "褞", "褥", "褪", "褫", "襁", "襄", "褻", "褶", "褸", "襌", "褝", "襠", "襞"], "e6": ["襦", "襤", "襭", "襪", "襯", "襴", "襷", "襾", "覃", "覈", "覊", "覓", "覘", "覡", "覩", "覦", "覬", "覯", "覲", "覺", "覽", "覿", "觀", "觚", "觜", "觝", "觧", "觴", "觸", "訃", "訖", "訐", "訌", "訛", "訝", "訥", "訶", "詁", "詛", "詒", "詆", "詈", "詼", "詭", "詬", "詢", "誅", "誂", "誄", "誨", "誡", "誑", "誥", "誦", "誚", "誣", "諄", "諍", "諂", "諚", "諫", "諳", "諧", None, "諤", "諱", "謔", "諠", "諢", "諷", "諞", "諛", "謌", "謇", "謚", "諡", "謖", "謐", "謗", "謠", "謳", "鞫", "謦", "謫", "謾", "謨", "譁", "譌", "譏", "譎", "證", "譖", "譛", "譚", "譫", "譟", "譬", "譯", "譴", "譽", "讀", "讌", "讎", "讒", "讓", "讖", "讙", "讚", "谺", "豁", "谿", "豈", "豌", "豎", "豐", "豕", "豢", "豬", "豸", "豺", "貂", "貉", "貅", "貊", "貍", "貎", "貔", "豼", "貘", "戝", "貭", "貪", "貽", "貲", "貳", "貮", "貶", "賈", "賁", "賤", "賣", "賚", "賽", "賺", "賻", "贄", "贅", "贊", "贇", "贏", "贍", "贐", "齎", "贓", "賍", "贔", "贖", "赧", "赭", "赱", "赳", "趁", "趙", "跂", "趾", "趺", "跏", "跚", "跖", "跌", "跛", "跋", "跪", "跫", "跟", "跣", "跼", "踈", "踉", "跿", "踝", "踞", "踐", "踟", "蹂", "踵", "踰", "踴", "蹊"], "e7": ["蹇", "蹉", "蹌", "蹐", "蹈", "蹙", "蹤", "蹠", "踪", "蹣", "蹕", "蹶", "蹲", "蹼", "躁", "躇", "躅", "躄", "躋", "躊", "躓", "躑", "躔", "躙", "躪", "躡", "躬", "躰", "軆", "躱", "躾", "軅", "軈", "軋", "軛", "軣", "軼", "軻", "軫", "軾", "輊", "輅", "輕", "輒", "輙", "輓", "輜", "輟", "輛", "輌", "輦", "輳", "輻", "輹", "轅", "轂", "輾", "轌", "轉", "轆", "轎", "轗", "轜", None, "轢", "轣", "轤", "辜", "辟", "辣", "辭", "辯", "辷", "迚", "迥", "迢", "迪", "迯", "邇", "迴", "逅", "迹", "迺", "逑", "逕", "逡", "逍", "逞", "逖", "逋", "逧", "逶", "逵", "逹", "迸", "遏", "遐", "遑", "遒", "逎", "遉", "逾", "遖", "遘", "遞", "遨", "遯", "遶", "隨", "遲", "邂", "遽", "邁", "邀", "邊", "邉", "邏", "邨", "邯", "邱", "邵", "郢", "郤", "扈", "郛", "鄂", "鄒", "鄙", "鄲", "鄰", "酊", "酖", "酘", "酣", "酥", "酩", "酳", "酲", "醋", "醉", "醂", "醢", "醫", "醯", "醪", "醵", "醴", "醺", "釀", "釁", "釉", "釋", "釐", "釖", "釟", "釡", "釛", "釼", "釵", "釶", "鈞", "釿", "鈔", "鈬", "鈕", "鈑", "鉞", "鉗", "鉅", "鉉", "鉤", "鉈", "銕", "鈿", "鉋", "鉐", "銜", "銖", "銓", "銛", "鉚", "鋏", "銹", "銷", "鋩", "錏", "鋺", "鍄", "錮"], "e8": ["錙", "錢", "錚", "錣", "錺", "錵", "錻", "鍜", "鍠", "鍼", "鍮", "鍖", "鎰", "鎬", "鎭", "鎔", "鎹", "鏖", "鏗", "鏨", "鏥", "鏘", "鏃", "鏝", "鏐", "鏈", "鏤", "鐚", "鐔", "鐓", "鐃", "鐇", "鐐", "鐶", "鐫", "鐵", "鐡", "鐺", "鑁", "鑒", "鑄", "鑛", "鑠", "鑢", "鑞", "鑪", "鈩", "鑰", "鑵", "鑷", "鑽", "鑚", "鑼", "鑾", "钁", "鑿", "閂", "閇", "閊", "閔", "閖", "閘", "閙", None, "閠", "閨", "閧", "閭", "閼", "閻", "閹", "閾", "闊", "濶", "闃", "闍", "闌", "闕", "闔", "闖", "關", "闡", "闥", "闢", "阡", "阨", "阮", "阯", "陂", "陌", "陏", "陋", "陷", "陜", "陞", "陝", "陟", "陦", "陲", "陬", "隍", "隘", "隕", "隗", "險", "隧", "隱", "隲", "隰", "隴", "隶", "隸", "隹", "雎", "雋", "雉", "雍", "襍", "雜", "霍", "雕", "雹", "霄", "霆", "霈", "霓", "霎", "霑", "霏", "霖", "霙", "霤", "霪", "霰", "霹", "霽", "霾", "靄", "靆", "靈", "靂", "靉", "靜", "靠", "靤", "靦", "靨", "勒", "靫", "靱", "靹", "鞅", "靼", "鞁", "靺", "鞆", "鞋", "鞏", "鞐", "鞜", "鞨", "鞦", "鞣", "鞳", "鞴", "韃", "韆", "韈", "韋", "韜", "韭", "齏", "韲", "竟", "韶", "韵", "頏", "頌", "頸", "頤", "頡", "頷", "頽", "顆", "顏", "顋", "顫", "顯", "顰"], "e9": ["顱", "顴", "顳", "颪", "颯", "颱", "颶", "飄", "飃", "飆", "飩", "飫", "餃", "餉", "餒", "餔", "餘", "餡", "餝", "餞", "餤", "餠", "餬", "餮", "餽", "餾", "饂", "饉", "饅", "饐", "饋", "饑", "饒", "饌", "饕", "馗", "馘", "馥", "馭", "馮", "馼", "駟", "駛", "駝", "駘", "駑", "駭", "駮", "駱", "駲", "駻", "駸", "騁", "騏", "騅", "駢", "騙", "騫", "騷", "驅", "驂", "驀", "驃", None, "騾", "驕", "驍", "驛", "驗", "驟", "驢", "驥", "驤", "驩", "驫", "驪", "骭", "骰", "骼", "髀", "髏", "髑", "髓", "體", "髞", "髟", "髢", "髣", "髦", "髯", "髫", "髮", "髴", "髱", "髷", "髻", "鬆", "鬘", "鬚", "鬟", "鬢", "鬣", "鬥", "鬧", "鬨", "鬩", "鬪", "鬮", "鬯", "鬲", "魄", "魃", "魏", "魍", "魎", "魑", "魘", "魴", "鮓", "鮃", "鮑", "鮖", "鮗", "鮟", "鮠", "鮨", "鮴", "鯀", "鯊", "鮹", "鯆", "鯏", "鯑", "鯒", "鯣", "鯢", "鯤", "鯔", "鯡", "鰺", "鯲", "鯱", "鯰", "鰕", "鰔", "鰉", "鰓", "鰌", "鰆", "鰈", "鰒", "鰊", "鰄", "鰮", "鰛", "鰥", "鰤", "鰡", "鰰", "鱇", "鰲", "鱆", "鰾", "鱚", "鱠", "鱧", "鱶", "鱸", "鳧", "鳬", "鳰", "鴉", "鴈", "鳫", "鴃", "鴆", "鴪", "鴦", "鶯", "鴣", "鴟", "鵄", "鴕", "鴒", "鵁", "鴿", "鴾", "鵆", "鵈"], "ea": ["鵝", "鵞", "鵤", "鵑", "鵐", "鵙", "鵲", "鶉", "鶇", "鶫", "鵯", "鵺", "鶚", "鶤", "鶩", "鶲", "鷄", "鷁", "鶻", "鶸", "鶺", "鷆", "鷏", "鷂", "鷙", "鷓", "鷸", "鷦", "鷭", "鷯", "鷽", "鸚", "鸛", "鸞", "鹵", "鹹", "鹽", "麁", "麈", "麋", "麌", "麒", "麕", "麑", "麝", "麥", "麩", "麸", "麪", "麭", "靡", "黌", "黎", "黏", "黐", "黔", "黜", "點", "黝", "黠", "黥", "黨", "黯", None, "黴", "黶", "黷", "黹", "黻", "黼", "黽", "鼇", "鼈", "皷", "鼕", "鼡", "鼬", "鼾", "齊", "齒", "齔", "齣", "齟", "齠", "齡", "齦", "齧", "齬", "齪", "齷", "齲", "齶", "龕", "龜", "龠", "堯", "槇", "遙", "瑤", "凜", "熙"], "eb": [None, "、", "。", None, None, None, None, None, None, None, None, None, None, None, None, None, " ̄", "︳", None, None, None, None, None, None, None, None, None, "ー", "︱", "‐", None, None, "〜", "‖", "|", "…", "︰", None, None, None, None, "︵", "︶", "︹", "︺", "[", "]", "︷", "︸", "︿", "﹀", "︽", "︾", "﹁", "﹂", "﹃", "﹄", "︻", "︼", None, None, None, None, None, None, "="], "ec": [None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, "ぁ", None, "ぃ", None, "ぅ", None, "ぇ", None, "ぉ", None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, "っ", None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, "ゃ", None, "ゅ", None, "ょ", None, None, None, None, None, None, "ゎ"], "ed": ["ァ", None, "ィ", None, "ゥ", None, "ェ", None, "ォ", None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, "ッ", None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, "ャ", None, "ュ", None, "ョ", None, None, None, None, None, None, "ヮ", None, None, None, None, None, None, "ヵ", "ヶ"], } # fmt: on def decode_macjapanese(text: ByteString) -> str: """ Decode Mac Japanse Mac OS Japanese https://en.wikipedia.org/wiki/Shift_JIS#MacJapanese https://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/JAPANESE.TXT """ res = "" i_text = iter(text) hi = next(i_text, None) while hi: if hi <= 0x7F: # ASCII res += chr(hi) elif hi == 0x80: # reverse solidus res += "\u005C" elif (0x81 <= hi <= 0x9F) or (0xE0 <= hi <= 0xFC): # two-byte sequence lo = next(i_text, None) if lo is None: print(f"WARNING: Mac Japanese sequence missing second byte 0x{hi:02x}") return text.decode('mac-roman') hi_key = f'{hi:02x}' lo_key = lo - 0x40 if lo_key < 0: print(f"WARNING: second byte out of range 0x{lo:02x}") return text.decode('mac-roman') elif decode_map.get(hi_key) is None or decode_map[hi_key][lo_key] is None: print(f"WARNING: No mapping for MacJapanese sequence 0x{hi_key}{lo:02x}") return text.decode('mac-roman') assert_tmp = decode_map[hi_key][lo_key] assert assert_tmp # mypy assert res += assert_tmp elif hi == 0xA0: # no-break space res += "\u00A0" elif 0xA1 <= hi <= 0xDF: # Katakana res += chr(hi - 0xA1 + 0xFF61) elif hi == 0xFD: # copyright sign res += "\u00A9" elif hi == 0xFE: # trade mark sign res += "\u2122" elif hi == 0xFF: # halfwidth horizontal ellipsis res += "\u2026\uF87F" else: raise Exception(f"No mapping for MacJapanese sequence 0x{hi:02x}") hi = next(i_text, None) return res def file_to_macbin(f: machfs.File, name: ByteString) -> bytes: oldFlags = f.flags >> 8 newFlags = f.flags & 0xFF macbin = pack( ">x64p4s4sBxHHHBxIIIIHB14xIHBB", name, f.type, f.creator, oldFlags, 0, 0, 0, f.locked, len(f.data), len(f.rsrc), f.crdate, f.mddate, 0, newFlags, 0, 0, 129, 129, ) macbin += pack(">H2x", crc_hqx(macbin, 0)) if f.data: macbin += f.data if len(f.data) % 128: macbin += b"\x00" * (128 - len(f.data) % 128) if f.rsrc: macbin += f.rsrc if len(f.rsrc) % 128: macbin += b"\x00" * (128 - len(f.rsrc) % 128) return macbin def escape_string(s: str) -> str: """ Escape strings Escape the following: - escape char: \x81 - unallowed filename chars: https://en.wikipedia.org/wiki/Filename#Reserved_characters_and_words - control chars < 0x20 """ new_name = "" for char in s: if char == "\x81": new_name += "\x81\x79" elif char in '/":*|\\?%<>' or ord(char) < 0x20: new_name += "\x81" + chr(0x80 + ord(char)) else: new_name += char return new_name def unescape_string(s: str) -> str: """unescape strings""" orig_name = "" s_iter = iter(s) hi = next(s_iter, None) while hi is not None: if hi == "\x81": low = next(s_iter, None) assert low is not None, "Error decoding string" if low == "\x79": orig_name += "\x81" else: orig_name += chr(ord(low) - 0x80) else: orig_name += hi hi = next(s_iter, None) return orig_name def needs_punyencoding(orig: str) -> bool: """ A filename needs to be punyencoded when it: - contains a char that should be escaped or - ends with a dot or a space. """ if orig != escape_string(orig): return True if orig[-1] in " .": return True return False def punyencode(orig: str) -> str: """ Punyencode strings - escape special characters and - ensure filenames can't end in a space or dot """ s = escape_string(orig) encoded = s.encode("punycode").decode("ascii") # punyencoding adds an '-' at the end when there are no special chars # don't use it for comparing compare = encoded if encoded.endswith("-"): compare = encoded[:-1] if orig != compare or compare[-1] in " .": return "xn--" + encoded return orig def decode_string(orig: str) -> str: """ Decode punyencoded strings """ st = orig[4:].encode("ascii").decode("punycode") return unescape_string(st) def encode_string(args: argparse.Namespace) -> int: if args.string: var = args.string if args.stdin: var = input() if var.startswith("xn--"): print(decode_string(var)) else: print(punyencode(var)) return 0 def generate_punyencoded_path(destination_dir: Path, hpath: Tuple[str]) -> Path: """Convert a filepath to a punyencoded one""" upath = destination_dir for el in hpath: upath /= punyencode(el) return upath def extract_volume(args: argparse.Namespace) -> int: """Extract an mac iso""" source_volume: Path = args.src destination_dir: Path = args.dir punify: bool = args.punycode japanese: bool = args.japanese print(f"Loading {source_volume} ...") vol = machfs.Volume() vol.read(source_volume.read_bytes()) destination_dir.mkdir(parents=True, exist_ok=True) for hpath, obj in vol.iter_paths(): # Encode the path upath = destination_dir for el in hpath: if japanese: el = decode_macjapanese(el.encode("mac_roman")) if punify or needs_punyencoding(el): el = punyencode(el) upath /= el # Write the file to disk if isinstance(obj, machfs.Folder): upath.mkdir(exist_ok=True) # Set the modified time for folders os.utime(upath, (obj.mddate - 2082844800, obj.mddate - 2082844800)) else: print(upath) file = obj.data if obj.rsrc: file = file_to_macbin(obj, hpath[-1].encode("mac_roman")) upath.write_bytes(file) os.utime(upath, (obj.mddate - 2082844800, obj.mddate - 2082844800)) # This needs to be done after writing files as writing files resets # the parent folder's modified time that was set before parent_folder_modtime = vol.get(hpath[:-1]).mddate - 2082844800 os.utime(upath.parent, (parent_folder_modtime, parent_folder_modtime)) return 0 def punyencode_paths(paths: List[Path], verbose: bool = False, source_encoding: str = None) -> int: """Rename filepaths to their punyencoded names""" count = 0 for path in paths: if source_encoding is not None: new_name = punyencode(demojibake_hfs_bytestring(bytes(path.name, "utf8"), source_encoding)) else: new_name = punyencode(path.name) if path.stem != new_name: count += 1 new_path = path.parent / new_name if verbose: print(f"Renamed {path} to {new_path}") path.rename(new_path) return count def demojibake_hfs_bytestring(s: ByteString, encoding: str): """ Takes misinterpreted bytestrings from macOS and transforms them into the correct interpretation. When not able to figure out the correct encoding for legacy non-Unicode HFS filesystems, which is most of the time, macOS interprets filenames as though they're MacRoman. Once mounted, the files are presented via all of the macOS filesystem APIs as though they're UTF-8. This is great for Western European languages, but falls over for other languages. For example, Japanese filenames will be rendered as gibberish (mojibake). This can be fixed by normalizing the filenames' UTF-8 encoding, transforming it back to "MacRoman", then correctly reinterpreting via the correct encoding. """ return decode_bytestring( # macOS renders paths as NFD, but to correctly translate # this back to the original MacRoman, we first have to # renormalize it to NFC. unicodedata.normalize('NFC', s.decode('utf8')).encode('macroman'), encoding ) def decode_bytestring(s: ByteString, encoding: str): """Wrapper for decode() that can dispatch to decode_macjapanese""" if encoding == "mac_japanese": return decode_macjapanese(s) else: return s.decode(encoding) def punyencode_arg(args: argparse.Namespace) -> int: """wrapper function""" punyencode_dir(args.directory, verbose=True) return 0 def punyencode_dir(directory: Path, verbose: bool = False, source_encoding: str = None) -> int: """ Recursively punyencode all directory and filenames Renames the leaves, i.e. files, first and the works it way up the tree by renaming the """ files: List[Path] = [] dirs: List[Path] = [] if source_encoding is not None: directory = Path(demojibake_hfs_bytestring(directory, source_encoding)) path_glob = directory.glob("**/*") for item in path_glob: if item.is_file(): files.append(item) if item.is_dir(): dirs.append(item) dirs.reverse() # start renaming with the one at the bottom count = punyencode_paths(files, verbose=verbose, source_encoding=source_encoding) count += punyencode_paths(dirs, verbose=verbose, source_encoding=source_encoding) return count def has_resource_fork(dirpath: bytes, filename: bytes) -> bool: """ Check if file has a resource fork Ease of compatibility between macOS and linux """ filepath = os.path.join(dirpath, filename) return os.path.exists(os.path.join(filepath, bytes("..namedfork/rsrc", "utf8"))) def collect_forks(args: argparse.Namespace) -> int: """ Collect resource forks and move them to a macbinary file - combine them with the data fork when it's available - punyencode the filename when requested """ directory: bytes = bytes(args.dir) punify: bool = args.punycode count_resources = 0 count_renames = 0 for dirpath, _, filenames in os.walk(directory): for filename in filenames: if has_resource_fork(dirpath, filename): print(f"Resource in {filename}") count_resources += 1 resource_filename = filename + bytes("/..namedfork/rsrc", "utf8") to_filename = filename filepath = os.path.join(dirpath, filename) resourcepath = os.path.join(dirpath, resource_filename) file = machfs.File() # Set the file times and convert them to Mac epoch info = os.stat(filepath) file.crdate = 2082844800 + int(info.st_birthtime) file.mddate = 2082844800 + int(info.st_mtime) # Get info on creator and type try: finderInfo = xattr.xattr(filepath)["com.apple.FinderInfo"][0:8] except (IOError, OSError) as e: print(f"Error getting type and creator for: {filename}") return 1 file.type, file.creator = unpack("4s4s", finderInfo) with open(resourcepath, "rb") as rsrc: file.rsrc = rsrc.read() with open(filepath, "rb") as data: file.data = data.read() with open(filepath, "wb") as to_file: to_file.write(file_to_macbin(file, to_filename)) if to_filename != filename: os.remove(filepath) # Remove the original file os.utime( filepath, (info.st_mtime, info.st_mtime), ) if punify: count_renames = punyencode_dir(directory, verbose=True, source_encoding=args.source_encoding) print(f"Macbinary {count_resources}, Renamed {count_renames} files") return 0 def generate_parser() -> argparse.ArgumentParser: """ Generate the parser The parser is split into multiple subparsers. One for each mode we support. Each subparser has a default function that handles that mode. """ parser = argparse.ArgumentParser() subparsers = parser.add_subparsers() parser_iso = subparsers.add_parser("iso", help="Dump hfs isos") parser_iso.add_argument("src", metavar="INPUT", type=Path, help="Disk image") parser_iso.add_argument( "--punycode", action="store_true", help="encode pathnames into punycode" ) parser_iso.add_argument( "--japanese", action="store_true", help="read mac_japanese hfs+" ) parser_iso.add_argument( "dir", metavar="OUTPUT", type=Path, help="Destination folder" ) parser_iso.set_defaults(func=extract_volume) parser_dir = subparsers.add_parser( "dir", help="Punyencode all files and dirs in place" ) parser_dir.add_argument("directory", metavar="directory ", type=Path, help="Path") parser_dir.set_defaults(func=punyencode_arg) parser_str = subparsers.add_parser( "str", help="Convert strings or standard in to or from punycode" ) parser_str.add_argument( "--stdin", action="store_true", help="Convert stdin to punycode" ) parser_str.add_argument( "string", metavar="STRING", type=str, help="Convert string to or from punycode", nargs="?", ) parser_str.set_defaults(func=encode_string) if sys.platform == "darwin": parser_macbinary = subparsers.add_parser( "mac", help="MacOS only: Operate in MacBinary encoding mode. Recursively encode all resource forks in the current directory", ) parser_macbinary.add_argument( "--punycode", action="store_true", help="encode pathnames into punycode", ) parser_macbinary.add_argument( "--source-encoding", metavar="source_encoding", type=str, help="encoding used for filenames in this path", ) parser_macbinary.add_argument( "dir", metavar="directory", type=Path, help="input directory" ) parser_macbinary.set_defaults(func=collect_forks) return parser if __name__ == "__main__": parser = generate_parser() args = parser.parse_args() try: f = args.func except AttributeError: parser.error("too few arguments") exit(f(args)) ### Test functions def call_test_parser(input_args: List[str]) -> Any: """Helper function to call the parser""" parser = generate_parser() args = parser.parse_args(input_args) args.func(args) def test_decode_mac_japanese(): checks = [ [ b"QuickTime\xfe \x89\xb9\x90F\x91\xce\x89\x9e\x95\\", "QuickTime™ 音色対応表", ], [ b"Asant\x8e", "Asanté" ] ] for input, expected in checks: assert decode_macjapanese(input) == expected def test_encode_string(capsys): checks = [["Icon\r", "xn--Icon-ja6e"]] for input, output in checks: call_test_parser(["str", input]) captured = capsys.readouterr() assert captured.out == output + "\n" call_test_parser(["str", output]) captured = capsys.readouterr() assert captured.out == input + "\n" def test_encode_stdin(capsys, monkeypatch): monkeypatch.setattr("sys.stdin", io.StringIO("Icon\r")) call_test_parser(["str", "--stdin"]) captured = capsys.readouterr() assert captured.out == "xn--Icon-ja6e\n" def test_decode_name(): checks = [ ["Icon\r", "xn--Icon-ja6e"], ["ends with dot .", "xn--ends with dot .-"], ["ends with space ", "xn--ends with space -"], ["バッドデイ(Power PC)", "xn--(Power PC)-jx4ilmwb1a7h"], ["Hello*", "xn--Hello-la10a"], ["File I/O", "xn--File IO-oa82b"], ["HDにコピーして下さい。G3", "xn--HDG3-rw3c5o2dpa9kzb2170dd4tzyda5j4k"], ["Buried in Time™ Demo", "xn--Buried in Time Demo-eo0l"], ["•Main Menu", "xn--Main Menu-zd0e"], ["Spaceship Warlock™", "xn--Spaceship Warlock-306j"], ["ワロビージャックの大冒険<デモ>", "xn--baa0pja0512dela6bueub9gshf1k1a1rt742c060a2x4u"], ["Jönssonligan går på djupet.exe", "xn--Jnssonligan gr p djupet.exe-glcd70c"], ["Jönssonligan.exe", "xn--Jnssonligan.exe-8sb"], ["G3フォルダ", "xn--G3-3g4axdtexf"], ["Where \\ Do Want / To: G* ? ;Unless=nowhere,or|\"(everything)/\":*|\\?%<>,;=", "xn--Where Do you Want To G ;Unless=nowhere,or(everything),;=-5baedgdcbtamaaaaaaaaa99woa3wnnmb82aqb71ekb9g3c1f1cyb7bx6rfcv2pxa"], ["Buried in Timeェ Demo", "xn--Buried in Time Demo-yp97h"], ["ぱそすけPPC", "xn--PPC-873bpbxa3l"] ] for input, output in checks: assert punyencode(input) == output assert decode_string(output) == input def test_needs_punyencoding(): checks = [ ["Icon\r", True], ["ascii", False], ["バッドデイ(Power PC)", False], ["ends_with_dot .", True], ["ends_with_space ", True], ["Big[test]", False] ] for input, expected in checks: assert needs_punyencoding(input) == expected def test_escape_string(): checks = [["\r", "\x81\x8d"], ["\x81", "\x81\x79"]] for input, output in checks: assert escape_string(input) == output assert unescape_string(output) == input