error C2332: 'enum' : missing tag name

本文详细解释了在使用Visual Studio 2013编译C++代码时遇到的错误问题,特别是关于vs2010库与C++0x新增的强类型enumclass不兼容的问题,并提供了解决方法。通过调整项目属性,选择正确的平台工具集,可以避免这些编译错误,顺利进行C++开发。

环境;win7 32,vs2013

代码:

#include <iostream>
using namespace std;

namespace MYSPACE{
	enum class choice
	{
		rock,
		paper,
		scissors
	};
}
typedef MYSPACE::choice Mchoice;

int main()
{
	Mchoice c = Mchoice::rock;
	return 0;
}

报错:

1>d:\hbj\test\test0505\test0505\t.cpp(5): error C2332: 'enum' : missing tag name
1>d:\hbj\test\test0505\test0505\t.cpp(6): error C2236: unexpected 'class' 'MYSPACE::choice'. Did you forget a ';'?
1>d:\hbj\test\test0505\test0505\t.cpp(6): error C3381: 'MYSPACE::choice' : assembly access specifiers are only available in code compiled with a /clr option
1>d:\hbj\test\test0505\test0505\t.cpp(7): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>d:\hbj\test\test0505\test0505\t.cpp(8): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>d:\hbj\test\test0505\test0505\t.cpp(10): error C2143: syntax error : missing ';' before '}'
1>d:\hbj\test\test0505\test0505\t.cpp(10): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>d:\hbj\test\test0505\test0505\t.cpp(18): error C2039: 'rock' : is not a member of 'MYSPACE::choice'
1>          d:\hbj\test\test0505\test0505\t.cpp(6) : see declaration of 'MYSPACE::choice'
1>d:\hbj\test\test0505\test0505\t.cpp(18): error C2065: 'rock' : undeclared identifier

原因:vs2013使用了vs2010库,而vs2010不支持c++0x新增的强类型enum class

解决:在vs2013项目属性里,General->Platform Toolset,选择Visual Studio 2013 - Windows XP (v120_xp)或者Visual Studio 2013

参考:http://blog.youkuaiyun.com/zhanglei5415/article/details/1588258

http://zhidao.baidu.com/link?url=OTbxL2KFkfdunxC1dspL7dsa31zKQbHz-_kj6ZaB8O6TDhbpRmUyUqGUTV_DVr8pGS3msaXxxCg9i1aqXguMLd_i7YGP-XZEy62ELU2Utwm

http://blog.youkuaiyun.com/u012333003/article/details/20612267?utm_source=tuicool

http://www.cnblogs.com/tekkaman/p/3500904.html

http://www.xuebuyuan.com/1390932.html

http://blog.jobbole.com/44015/

# power/power_sync.py import json import os import re import logging import sys from pathlib import Path from shutil import copy2 from datetime import datetime from utils import resource_path from typing import Dict, List, Tuple, Any # ------------------------------- # 日志配置 # ------------------------------- PROJECT_ROOT = Path(__file__).parent.parent.resolve() LOG_DIR = PROJECT_ROOT / "output" / "log" LOG_DIR.mkdir(parents=True, exist_ok=True) LOG_FILE = LOG_DIR / f"power_sync_{datetime.now().strftime('%Y%m%d_%H%M%S')}.log" class PowerTableSynchronizer: def __init__(self, c_file_path=None, dry_run=False, config_path="config/config.json"): self.logger = logging.getLogger(__name__) # === Step 1: 使用 resource_path 解析所有路径 === self.config_file_path = resource_path(config_path) self.logger.info(f"配置文件: {self.config_file_path}") if not os.path.exists(self.config_file_path): raise FileNotFoundError(f"配置文件不存在: {self.config_file_path}") try: with open(self.config_file_path, 'r', encoding='utf-8') as f: self.config = json.load(f) self.logger.info(f"配置文件已加载: {self.config_file_path}") except json.JSONDecodeError as e: raise ValueError(f"配置文件格式错误,JSON 解析失败: {self.config_file_path}") from e except Exception as e: raise RuntimeError(f"读取配置文件时发生未知错误: {e}") from e self.dry_run = dry_run # === Step 2: 目标 C 文件处理 === if c_file_path is None: if "target_c_file" not in self.config: raise KeyError("config 文件缺少 'target_c_file' 字段") internal_c_path = self.config["target_c_file"] logging.info(f"使用内置 C 文件: {internal_c_path}") self.c_file_path =resource_path(internal_c_path) self._is_internal_c_file = True else: self.c_file_path = Path(c_file_path) self._is_internal_c_file = False if not self.c_file_path.exists(): raise FileNotFoundError(f"找不到 C 源文件: {self.c_file_path}") # === Step 3: 初始化数据容器 === self.locale_enums = {} # enum_name -> {"macros": [macro], "values": {macro: idx}} self.power_tables = {} # table_name -> [lines] self.table_pending_appends = {} # table_name -> List[str] # === Step 4: 加载锚点标记 === for marker_key in ["STR_POWER_LOCALE_ENUM", "END_POWER_LOCALE_ENUM", "STR_POWER_TABLE", "END_POWER_TABLE"]: if marker_key not in self.config: raise KeyError(f"config 文件缺少 '{marker_key}' 字段") self.start_enum_marker = self.config["STR_POWER_LOCALE_ENUM"] self.end_enum_marker = self.config["END_POWER_LOCALE_ENUM"] self.start_table_marker = self.config["STR_POWER_TABLE"] self.end_table_marker = self.config["END_POWER_TABLE"] # === Step 5: 功率表文件 === gen_file = PROJECT_ROOT / "output" / "tx_limit_table.c" if not gen_file.exists(): self.logger.error(f" 找不到生成文件: {gen_file}") raise FileNotFoundError(f"请先运行 excel_to_clm.py 生成 tx_limit_table.c: {gen_file}") try: self.power = gen_file.read_text(encoding='utf-8') except Exception as e: self.logger.error(f" 读取 {gen_file} 失败: {e}") raise # 加载 locale_targets 配置 if "locale_targets" not in self.config: raise KeyError("config 文件缺少 'locale_targets' 字段") required_keys = {"enum", "table", "suffix"} for i, item in enumerate(self.config["locale_targets"]): if not isinstance(item, dict) or not required_keys.issubset(item.keys()): raise ValueError(f"locale_targets[{i}] 缺少必要字段 {required_keys}: {item}") self.locale_targets = self.config["locale_targets"] self.logger.info(f"已加载 {len(self.locale_targets)} 个 Locale 映射目标") def offset_to_lineno(self, content: str, offset: int) -> int: """将字符偏移量转换为行号(从1开始)""" return content.count('\n', 0, offset) + 1 def _extract_brace_content(self, content: str, start_brace_pos: int) -> tuple[str | None, int]: depth = 0 i = start_brace_pos while i < len(content): c = content[i] if c == '{': depth += 1 elif c == '}': depth -= 1 if depth == 0: inner = content[start_brace_pos + 1:i].strip() return inner, i + 1 # 返回内部内容 和 '}' 后的下一个索引 i += 1 return None, -1 def parse_c_power_definitions(self): """解析 C 源文件中的 enum locale_xxx_idx 和 static const unsigned char locales_xxx[]""" self.logger.info("解析 C 文件中的功率表定义...") self.logger.info("...") content = self.c_file_path.read_text(encoding='utf-8') # --- 解析 ENUM 区域 --- try: enum_start_idx = content.find(self.start_enum_marker) enum_end_idx = content.find(self.end_enum_marker) if enum_start_idx == -1 or enum_end_idx == -1: raise ValueError("未找到 LOCALE ENUM 标记块") enum_block = content[enum_start_idx:enum_end_idx] start_line = self.offset_to_lineno(content, enum_start_idx) end_line = self.offset_to_lineno(content, enum_end_idx) self.logger.info(f"找到 ENUM 标记范围:第 {start_line} 行 → 第 {end_line} 行") enum_pattern = re.compile( r'(enum\s+locale_[a-zA-Z0-9_]+(?:_[a-zA-Z0-9_]+)*_idx\s*\{)([^}]*)\}\s*;', re.DOTALL | re.IGNORECASE ) for match in enum_pattern.finditer(enum_block): enum_decl = match.group(0) self.logger.debug(f" 解析枚举声明: {enum_decl}") enum_name_match = re.search(r'locale_[\w\d_]+_idx', enum_decl, re.IGNORECASE) if not enum_name_match: continue enum_name = enum_name_match.group(0) body = match.group(2) # 在 parse_c_power_definitions() 中 body_no_comment = re.sub(r'//.*|/\*.*?\*/', '', body, flags=re.DOTALL) # 只提取 = 数字 的宏 valid_assignments = re.findall( r'(LOCALE_[A-Za-z0-9_]+)\s*=\s*(-?\b\d+\b)', body_no_comment ) macro_list = [m[0] for m in valid_assignments] value_map = {m: int(v) for m, v in valid_assignments} self.locale_enums[enum_name] = { "macros": macro_list, "values": value_map, "raw_body": body } self.logger.info(f" 解析枚举 {enum_name}: {len(macro_list)} 个宏") except Exception as e: self.logger.error(f"解析 ENUM 失败: {e}", exc_info=True) # --- 解析 TABLE 区域 --- try: table_start_idx = content.find(self.start_table_marker) table_end_idx = content.find(self.end_table_marker) if table_start_idx == -1 or table_end_idx == -1: raise ValueError("未找到 POWER TABLE 标记块") table_block = content[table_start_idx:table_end_idx] start_line = self.offset_to_lineno(content, table_start_idx) end_line = self.offset_to_lineno(content, table_end_idx) self.logger.info(f"找到 TABLE 标记范围:第 {start_line} 行 → 第 {end_line} 行") # === 增强解析 TABLE:按 /* Locale X */ 分块提取 === array_matches = list(re.finditer( r''' ^ # 行首(配合 MULTILINE) \s* # 可选前导空白 (?:static\s+)? # 可选 static (?:const\s+)? # 可选 const (?:PROGMEM\s+)? # 可选 PROGMEM(常见于嵌入式) (?:unsigned\s+char|uint8_t) # 支持两种类型 \s+ # 类型与变量之间至少一个空白 ([a-zA-Z_]\w*) # 数组(如 locales_2g_ht) \s*\[\s*\] # 匹配 [ ],允许空格 ''', table_block, re.VERBOSE | re.MULTILINE | re.IGNORECASE )) if not array_matches: self.logger.warning("未在 TABLE 区域找到任何 power table 数组定义") # === 新增调试信息 === sample = table_block[:1000] self.logger.debug(f"TABLE block 前 1000 字符内容:\n{sample}") else: for match in array_matches: table_name = match.group(1) self.logger.info( f" 找到数组定义: {table_name} @ 第 {self.offset_to_lineno(table_block, match.start())} 行") self.logger.debug(f" 正则匹配到数组: '{table_name}' (原始匹配: {match.group(0)})") self.logger.debug(f" match.end() = {match.end()}, " f"后续字符 = '{table_block[match.end():match.end() + 20].replace(chr(10), '\\n')}'") # 查找 '{' 的位置 brace_start = table_block.find('{', match.end()) if brace_start == -1: self.logger.warning(f" 未找到 起始符 → 跳过数组 {table_name}") continue else: self.logger.debug( f" 找到 '{{' 位置: 偏移量 {brace_start}, 行号 {self.offset_to_lineno(table_block, brace_start)}") # 提取大括号内的内容 inner_content, end_pos = self._extract_brace_content(table_block, brace_start) if inner_content is None: self.logger.warning(f" 提取 {table_name} 的大括号内容失败 → inner_content 为 None") continue else: self.logger.info(f" 成功提取 {table_name} 的大括号内容,长度: {len(inner_content)} 字符") # self.logger.info(f"--- 开始 ---") # self.logger.info(f"{inner_content}") # self.logger.info(f"--- 结束 ---") # 按行分割 lines = inner_content.splitlines() self.logger.info(f" {table_name} 共提取 {len(lines)} 行数据") # 可选:打印前几行预览(避免日志爆炸) preview_lines = min(10, len(lines)) for i in range(preview_lines): self.logger.debug(f"[{i:2d}] {lines[i]}") if len(lines) > 10: self.logger.debug("... 还有更多行") # 逐行解析 body_content,按 /* Locale X */ 分块 entries = [] # 存储每一块: {'locale_tag': 'a_359', 'lines': [...]} current_block = [] current_locale = None for line_num, line in enumerate(lines): stripped = line.strip() self.logger.debug(f"[Line {line_num:3d}] |{line}|") # 原始行(含空白) self.logger.debug(f" → stripped: |{stripped}|") # 检查是否是新的 Locale 注释 comment_match = re.match(r'/\*\s*Locale\s+([A-Za-z0-9_-]+)\s*\([^)]+\)\s*\*/', stripped, re.IGNORECASE) if comment_match: # 保存上一个 block if current_locale and current_block: entries.append({ 'locale_tag': current_locale, 'lines': [ln.rstrip(',').rstrip() for ln in current_block] }) # self.logger.info( # f" 保存前一个 Locale 数据块: {current_locale.} ({len(current_block)} 行)") # 开始新 block raw_name = comment_match.group(1) # 如 A-359 normalized = raw_name.replace('-', '_') # → A_359 current_locale = normalized current_block = [] #self.logger.info(f" 发现新 Locale 注释: '{raw_name}' → 标准化为 '{normalized}'") continue # 忽略空行、纯注释行 clean_line = re.sub(r'/\*.*?\*/|//.*', '', stripped).strip() if clean_line: current_block.append(stripped) self.logger.debug(f" 添加有效行: {stripped}") else: if not stripped: self.logger.debug(" 忽略空行") elif '//' in stripped or ('/*' in stripped and '*/' in stripped): self.logger.debug(f" 忽略纯注释行: {stripped}") else: self.logger.warning(f" 可疑但未处理的行: {stripped}") # 可能是跨行注释开头 # 保存最后一个 block if current_locale and current_block: entries.append({ 'locale_tag': current_locale, 'lines': [ln.rstrip(',').rstrip() for ln in current_block] }) self.power_tables[table_name] = entries self.logger.info(f" 解析数组 {table_name}: {len(entries)} 个 Locale 数据块") except Exception as e: self.logger.error(f"解析 TABLE 失败: {e}", exc_info=True) def validate_and_repair(self): self.logger.info("对原始数据块进行验证和修复...") self.logger.info("...") modified = False changes = [] # 提取所有 Locale 原始数据块(已由 extract_all_raw_locale_data 返回原始行) tx_power_data = self.extract_all_raw_locale_data() for target in self.locale_targets: enum_name = target["enum"] table_name = target["table"] suffix = target["suffix"] # 关键字段检查 if "assigned_locale" not in target: raise KeyError(f"locale_targets 缺少 'assigned_locale': {target}") locale = target["assigned_locale"] macro_name = f"LOCALE_{suffix}_IDX_{locale.replace('-', '_')}" # 检查是否能在源文件中找到该 Locale 数据 if locale not in tx_power_data: self.logger.warning(f" 在 tx_limit_table.c 中找不到 Locale 数据: {locale}") continue # 获取原始行列表(含缩进、注释、逗号) data_lines = tx_power_data[locale] # ← 这些是原始字符串行 # --- 处理 ENUM --- if enum_name not in self.locale_enums: self.logger.warning(f"未找到枚举定义: {enum_name}") continue enum_data = self.locale_enums[enum_name] macros = enum_data["macros"] values = enum_data["values"] next_idx = self._get_next_enum_index(enum_name) if macro_name not in macros: macros.append(macro_name) values[macro_name] = next_idx changes.append(f"ENUM + {macro_name} = {next_idx}") modified = True if "pending_updates" not in enum_data: enum_data["pending_updates"] = [] enum_data["pending_updates"].append((macro_name, next_idx)) # --- 处理 TABLE --- if table_name not in self.power_tables: self.logger.warning(f"未找到 power table 数组: {table_name}") continue self.logger.info(f"找到 power table 数组: {table_name}") current_entries = self.power_tables[table_name] # 已加载的条目列表 # 归一化目标 locale 称用于比较 target_locale_normalized = locale.replace('-', '_') self.logger.debug(f" 目标 Locale : {locale} → 标准化为 {target_locale_normalized}") # 检查是否已存在(仅比对 locale_tag) self.logger.debug(f"当前 {table_name} 中已有的 locale_tags: {[e['locale_tag'] for e in current_entries]}") already_exists = any( entry['locale_tag'] == target_locale_normalized for entry in current_entries ) if already_exists: self.logger.warning(f"Locale '{locale}' 已存在于 {table_name},跳过") continue # 直接记录原始行,不再清洗! current_entries.append({ 'locale_tag': target_locale_normalized, 'lines': data_lines # 原样保存原始行(用于后续显示或校验) }) changes.append(f"TABLE + {len(data_lines)} 行 → {table_name}") modified = True # 记录待写入的数据块(包含原始带格式内容) if table_name not in self.table_pending_appends: self.table_pending_appends[table_name] = [] self.table_pending_appends[table_name].append({ 'locale_tag': locale, # 原始称 'data_lines': data_lines # 完整原始行(含缩进、注释、逗号) }) if changes: self.logger.info(f"共需添加 {len(changes)} 项:\n" + "\n".join(f" → {ch}" for ch in changes)) return modified def _get_next_enum_index(self, enum_name): """基于已解析的 values 获取下一个可用索引""" if enum_name not in self.locale_enums: self.logger.warning(f"未找到枚举定义: {enum_name}") return 0 value_map = self.locale_enums[enum_name]["values"] # 直接使用已解析的数据 if not value_map: return 0 # 只考虑非负数(排除 CLM_LOC_NONE=-1, CLM_LOC_SAME=-2 等保留值) used_indices = [v for v in value_map.values() if v >= 0] if used_indices: next_idx = max(used_indices) + 1 else: next_idx = 0 # 没有有效数值时从 0 开始 return next_idx def extract_all_raw_locale_data(self) -> Dict[str, List[str]]: """ 从 output/tx_limit_table.c 中提取所有 /* Locale XXX */ 后面的数据块(直到下一个 Locale 或 EOF) 使用逐行解析,保留原始格式(含缩进、注释、逗号),不进行任何清洗 """ lines = self.power.splitlines() locale_data = {} current_locale = None current_block = [] for i, line in enumerate(lines): stripped = line.strip() # 检查是否是新的 Locale 标记 match = re.match(r'/\*\s*Locale\s+([A-Za-z0-9_]+)\s*\*/', stripped, re.IGNORECASE) if match: # 保存上一个 block(直接保存原始行,不清洗) if current_locale: locale_data[current_locale] = current_block self.logger.debug(f" 已提取 Locale {current_locale},共 {len(current_block)} 行") # 开始新 block current_locale = match.group(1) current_block = [] self.logger.debug(f" 发现 Locale: {current_locale}") continue # 收集当前 locale 的内容(原样保留) if current_locale is not None: current_block.append(line.rstrip('\r\n')) # 仅去除换行符,其他不变 # 处理最后一个 block if current_locale: locale_data[current_locale] = current_block self.logger.debug(f" 已提取最后 Locale {current_locale},共 {len(current_block)} 行") self.logger.info(f" 成功提取 {len(locale_data)} 个 Locale 数据块: {list(locale_data.keys())}") return locale_data def _write_back_in_blocks(self): """将修改后的 enum 和 table 块写回原 C 文件,基于锚点 block 精准更新""" self.logger.info("正在写回修改后的数据...") if self.dry_run: self.logger.info("DRY-RUN: 跳过写入文件") return try: content = self.c_file_path.read_text(encoding='utf-8') # === Step 1: 查找所有锚点位置 === enum_start = content.find(self.start_enum_marker) enum_end = content.find(self.end_enum_marker) table_start = content.find(self.start_table_marker) table_end = content.find(self.end_table_marker) if -1 in (enum_start, enum_end, table_start, table_end): missing = [] if enum_start == -1: missing.append(f"起始 ENUM: {self.start_enum_marker}") if enum_end == -1: missing.append(f"结束 ENUM: {self.end_enum_marker}") if table_start == -1: missing.append(f"起始 TABLE: {self.start_table_marker}") if table_end == -1: missing.append(f"结束 TABLE: {self.end_table_marker}") raise ValueError(f"未找到锚点标记: {missing}") enum_block = content[enum_start:enum_end] table_block = content[table_start:table_end] self.logger.info(f" 修改枚举范围: 第 {self.offset_to_lineno(content, enum_start)} 行 → " f"{self.offset_to_lineno(content, enum_end)} 行") self.logger.info(f" 修改数组范围: 第 {self.offset_to_lineno(content, table_start)} 行 → " f"{self.offset_to_lineno(content, table_end)} 行") replacements = [] # (start, end, replacement) def remove_comments(text): text = re.sub(r'//.*$', '', text, flags=re.MULTILINE) text = re.sub(r'/\*.*?\*/', '', text, flags=re.DOTALL) return text.strip() # === Step 3: 更新 ENUMs === for target in self.locale_targets: enum_name_key = target["enum"] enum_data = self.locale_enums.get(enum_name_key) if not enum_data or "pending_updates" not in enum_data: continue insertions = enum_data["pending_updates"] if not insertions: continue pattern = re.compile( rf'(enum\s+{re.escape(enum_name_key)}\s*\{{)([^}}]*)\}}\s*;', re.DOTALL | re.IGNORECASE ) match = pattern.search(enum_block) if not match: self.logger.warning(f"未找到枚举: {enum_name_key}") continue header_part = match.group(1) body_content = match.group(2) lines = [ln for ln in body_content.split('\n') if ln.strip()] last_line = lines[-1] if lines else "" indent_match = re.match(r'^(\s*)', last_line) line_indent = indent_match.group(1) if indent_match else " " expanded_last = last_line.expandtabs(4) clean_last = remove_comments(last_line) first_macro_match = re.search(r'LOCALE_[A-Z0-9_]+', clean_last) default_indent_len = len(line_indent.replace('\t', ' ')) target_macro_col = default_indent_len if first_macro_match: raw_before = last_line[:first_macro_match.start()] expanded_before = raw_before.expandtabs(4) target_macro_col = len(expanded_before) eq_match = re.search(r'=\s*\d+', clean_last) if eq_match and first_macro_match: eq_abs_start = first_macro_match.start() + eq_match.start() raw_eq_part = last_line[:eq_abs_start] expanded_eq_part = raw_eq_part.expandtabs(4) target_eq_col = len(expanded_eq_part) else: target_eq_col = target_macro_col + 30 new_body = body_content.rstrip() if not new_body.endswith(','): new_body += ',' for macro_name, next_idx in insertions: current_visual_len = len(macro_name.replace('\t', ' ')) padding_to_eq = max(1, target_eq_col - target_macro_col - current_visual_len) formatted_macro = f"{macro_name}{' ' * padding_to_eq}= {next_idx}" visible_macros = len(re.findall(r'LOCALE_[A-Z0-9_]+', clean_last)) MAX_PER_LINE = 4 if visible_macros < MAX_PER_LINE and last_line.strip(): insertion = f" {formatted_macro}," updated_last = last_line.rstrip() + insertion new_body = body_content.rsplit(last_line, 1)[0] + updated_last last_line = updated_last clean_last = remove_comments(last_line) else: raw_indent_len = len(line_indent.replace('\t', ' ')) leading_spaces = max(0, target_macro_col - raw_indent_len) prefix_padding = ' ' * leading_spaces new_line = f"\n{line_indent}{prefix_padding}{formatted_macro}," new_body += new_line last_line = new_line.strip() clean_last = remove_comments(last_line) new_enum = f"{header_part}{new_body}\n}};" full_start = enum_start + match.start() full_end = enum_start + match.end() replacements.append((full_start, full_end, new_enum)) self.logger.debug(f"插入 ENUM: {dict(insertions)}") enum_data.pop("pending_updates", None) # === Step 4: 更新 TABLEs —— 使用 pending_appends 中的数据 === seen = set() table_names = [] for target in self.locale_targets: name = target["table"] if name not in seen: table_names.append(name) seen.add(name) for table_name in table_names: if table_name not in self.power_tables: self.logger.debug(f"跳过未定义的表: {table_name}") continue if table_name not in self.table_pending_appends: self.logger.debug(f"无待插入数据: {table_name}") continue data_to_insert = self.table_pending_appends[table_name] if not data_to_insert: continue pattern = re.compile( rf'(\b{re.escape(table_name)}\s*\[\s*\]\s*=\s*\{{)(.*?)(\}}\s*;\s*)', re.DOTALL | re.IGNORECASE ) match = pattern.search(table_block) if not match: self.logger.warning(f"未找到数组定义: {table_name}") continue header_part = match.group(1) body_content = match.group(2) footer_part = match.group(3) lines = [ln for ln in body_content.split('\n') if ln.strip()] last_line = lines[-1] if lines else "" indent_match = re.match(r'^(\s*)', last_line) line_indent = indent_match.group(1) if indent_match else " " new_body = body_content.rstrip() # ==== 遍历每个待插入的 locale 数据块 ==== for item in data_to_insert: locale_tag = item['locale_tag'] locale_display = locale_tag.replace('_', '-') macro_suffix = locale_tag # 添加注释标记(与原始风格一致) new_body += f"\n{line_indent}/* Locale {locale_display} ({macro_suffix}) */" # 原始行加空格,不 strip,不加额外 indent for raw_line in item['data_lines']: # 仅排除纯空白行(可选),保留所有格式 if raw_line.strip(): # 排除空行 # 使用原始缩进,不再加 {line_indent} new_body += f"\n{line_indent}{raw_line}" # 构造新 table 内容 full_start = table_start + match.start() full_end = table_start + match.end() new_table = f"{header_part}{new_body}\n{footer_part}" replacements.append((full_start, full_end, new_table)) self.logger.debug(f"插入{len(data_to_insert)} 个 Locale 数据块到 {table_name}") # 清除防止重复写入 self.table_pending_appends.pop(table_name, None) # === Step 5: 应用所有替换(倒序避免偏移错乱)=== if not replacements: self.logger.info("无任何修改需要写入") return replacements.sort(key=lambda x: x[0], reverse=True) # 倒序应用 final_content = content for start, end, r in replacements: #self.logger.info(f"增加 [{start}:{end}] → 新内容:\n{r[:150]}...") final_content = final_content[:start] + r + final_content[end:] if content == final_content: self.logger.info("文件内容未发生变化,无需写入") return # 备份原文件 backup_path = self.c_file_path.with_suffix('.c.bak') copy2(self.c_file_path, backup_path) self.logger.info(f"已备份 → {backup_path}") # 写入新内容 self.c_file_path.write_text(final_content, encoding='utf-8') self.logger.info(f"成功写回 C 文件: {self.c_file_path}") self.logger.info(f"共更新 {len(replacements)} 个区块") except Exception as e: self.logger.error(f"写回文件失败: {e}", exc_info=True) raise def run(self): self.logger.info("开始同步 POWER LOCALE 定义...") try: self.parse_c_power_definitions() was_modified = self.validate_and_repair() if was_modified: if self.dry_run: self.logger.info("预览模式:检测到变更,但不会写入文件") else: self._write_back_in_blocks() # 执行写入操作 self.logger.info("同步完成:已成功更新 C 文件") else: self.logger.info("所有 Locale 已存在,无需修改") return was_modified except Exception as e: self.logger.error(f"同步失败: {e}", exc_info=True) raise def main(): logging.basicConfig( level=logging.INFO, format='%(asctime)s [%(levelname)s] %(name)s: %(message)s', handlers=[ logging.FileHandler(LOG_FILE, encoding='utf-8'), logging.StreamHandler(sys.stdout) ], force=True ) logger = logging.getLogger(__name__) # 固定配置 c_file_path = "input/wlc_clm_data_6726b0.c" dry_run = False log_level = "INFO" config_path = "config/config.json" logging.getLogger().setLevel(log_level) print(f"开始同步 POWER LOCALE 定义...") print(f"C 源文件: {c_file_path}") if dry_run: print("启用 dry-run 模式:仅预览变更,不修改文件") try: sync = PowerTableSynchronizer( c_file_path=None, dry_run=dry_run, config_path=config_path, ) sync.run() print("同步完成!") print(f"详细日志已保存至: {LOG_FILE}") except FileNotFoundError as e: logger.error(f"文件未找到: {e}") print("请检查文件路径是否正确。") sys.exit(1) except PermissionError as e: logger.error(f"权限错误: {e}") print("无法读取或写入文件,请检查权限。") sys.exit(1) except Exception as e: logger.error(f"程序异常退出: {e}", exc_info=True) sys.exit(1) if __name__ == '__main__': main() 我希望它能读取不同频段的功率表文件然后写入主要是这个地方 # === Step 5: 功率表文件 === gen_file = PROJECT_ROOT / "output" / "tx_limit_table.c" if not gen_file.exists(): self.logger.error(f" 找不到生成文件: {gen_file}") raise FileNotFoundError(f"请先运行 excel_to_clm.py 生成 tx_limit_table.c: {gen_file}") try: self.power = gen_file.read_text(encoding='utf-8') except Exception as e: self.logger.error(f" 读取 {gen_file} 失败: {e}") raise我目前有tx_limit_table_2g.c\tx_limit_table_5g.c\tx_limit_table_6g.其中6G还没填写内容
10-29
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值