Files
utun2/replace_printf.py
T

173 lines
6.0 KiB
Python

#!/usr/bin/env python3
"""
Replace printf with DEBUG_ macros in test files.
"""
import os
import re
import sys
def add_debug_include(content):
"""Add #include \"../lib/debug_config.h\" if not present."""
if '#include "../lib/debug_config.h"' in content:
return content
# Find position after last #include
lines = content.split('\n')
new_lines = []
include_added = False
for line in lines:
new_lines.append(line)
if line.strip().startswith('#include') and not include_added:
# Add our include after the last #include block
# Check if next line is not #include
pass
# Simpler: insert after first #include line that includes something from ../lib or ../src
# Actually, just insert after the first #include line
for i, line in enumerate(lines):
if line.strip().startswith('#include'):
# Insert after this line
lines.insert(i + 1, '#include "../lib/debug_config.h"')
break
return '\n'.join(lines)
def add_debug_init(content):
"""Add debug initialization at the beginning of main()."""
if 'debug_config_init();' in content:
return content
# Find int main() {
pattern = r'int main\s*\(\s*\)\s*\{'
match = re.search(pattern, content)
if not match:
return content
start = match.end()
# Insert after the opening brace
# Find the next newline after brace
newline_pos = content.find('\n', start)
if newline_pos == -1:
return content
insertion_point = newline_pos + 1
init_code = '\n debug_config_init();\n debug_set_level(DEBUG_LEVEL_TRACE);\n debug_set_categories(DEBUG_CATEGORY_ALL);\n'
content = content[:insertion_point] + init_code + content[insertion_point:]
return content
def determine_category(filename, line):
"""Determine debug category based on filename and line content."""
filename_lower = filename.lower()
if 'crypto' in filename_lower:
return 'DEBUG_CATEGORY_CRYPTO'
elif 'etcp' in filename_lower:
return 'DEBUG_CATEGORY_ETCP'
elif 'memory' in filename_lower:
return 'DEBUG_CATEGORY_MEMORY'
elif 'u_async' in filename_lower:
return 'DEBUG_CATEGORY_UASYNC'
elif 'll_queue' in filename_lower:
return 'DEBUG_CATEGORY_LL_QUEUE'
elif 'config' in filename_lower:
return 'DEBUG_CATEGORY_CONFIG'
else:
return 'DEBUG_CATEGORY_ALL'
def determine_level(line):
"""Determine debug level based on line content."""
line_lower = line.lower()
if '❌' in line or 'error' in line_lower or 'failed' in line_lower:
return 'DEBUG_ERROR'
elif 'warn' in line_lower:
return 'DEBUG_WARN'
elif '✅' in line_lower or 'success' in line_lower or 'passed' in line_lower:
return 'DEBUG_INFO'
elif '[debug]' in line_lower:
return 'DEBUG_DEBUG'
elif 'info' in line_lower:
return 'DEBUG_INFO'
else:
return 'DEBUG_INFO'
def replace_printf(content, filename):
"""Replace printf calls with DEBUG_ macros."""
# Pattern to match printf("...", ...);
# Simple approach: replace line by line
lines = content.split('\n')
new_lines = []
i = 0
while i < len(lines):
line = lines[i]
stripped = line.strip()
# Check for printf
if stripped.startswith('printf('):
# Extract format string and arguments
# Simple regex to capture printf("format", args);
match = re.match(r'printf\("([^"]*)"\s*,?(.*)\);', stripped)
if match:
fmt = match.group(1)
args = match.group(2).strip()
# Remove ❌ and ✅ symbols
fmt = fmt.replace('❌', '').replace('✅', '').strip()
# Determine category and level
category = determine_category(filename, line)
level = determine_level(line)
# Build new macro call
if args:
new_line = line.replace(stripped, f'{level}({category}, "{fmt}", {args});')
else:
new_line = line.replace(stripped, f'{level}({category}, "{fmt}");')
new_lines.append(new_line)
# Check if next line is fflush(stdout);
if i + 1 < len(lines) and 'fflush(stdout);' in lines[i + 1]:
i += 1 # Skip fflush line
else:
# Keep original if pattern doesn't match
new_lines.append(line)
elif stripped.startswith('fprintf(') and 'stderr' in stripped:
# Replace fprintf(stderr, ...) with DEBUG_ERROR
match = re.match(r'fprintf\s*\(\s*stderr\s*,\s*"([^"]*)"\s*,?(.*)\);', stripped)
if match:
fmt = match.group(1)
args = match.group(2).strip()
category = determine_category(filename, line)
new_line = line.replace(stripped, f'DEBUG_ERROR({category}, "{fmt}", {args});')
new_lines.append(new_line)
else:
new_lines.append(line)
else:
new_lines.append(line)
i += 1
return '\n'.join(new_lines)
def process_file(filepath):
"""Process a single file."""
print(f"Processing {filepath}")
with open(filepath, 'r') as f:
content = f.read()
original = content
# Step 1: Add debug include
content = add_debug_include(content)
# Step 2: Add debug initialization in main()
content = add_debug_init(content)
# Step 3: Replace printf calls
content = replace_printf(content, os.path.basename(filepath))
if content != original:
with open(filepath, 'w') as f:
f.write(content)
print(f" Updated {filepath}")
else:
print(f" No changes needed")
def main():
test_dir = 'tests'
for root, dirs, files in os.walk(test_dir):
for file in files:
if file.endswith('.c'):
filepath = os.path.join(root, file)
process_file(filepath)
if __name__ == '__main__':
main()