@ -527,10 +527,70 @@ def parse_function(lines_info, start_idx):
'pre': pre_lines,
'pre': pre_lines,
'start': start_idx,
'start': start_idx,
'end': closing,
'end': closing,
'decl_end': decl_end, # Store the line with opening brace
'line_count': closing - start_idx + 1
'line_count': closing - start_idx + 1
}
}
def normalize_whitespace(text):
"""Normalize whitespace: replace multiple spaces/newlines with single space."""
# Replace all whitespace (spaces, tabs, newlines) with single space
text = re.sub(r'\s+', ' ', text)
# Strip leading/trailing whitespace
return text.strip()
def get_function_signature(lines, func):
"""Get normalized function signature (like prototype)."""
# Get all lines from start to the line with opening brace
start = func['start']
end = func.get('decl_end', func['start']) # We need to track decl_end in parse_function
# Collect signature lines
sig_lines = []
for i in range(start, min(end + 1, len(lines))):
line = lines[i]
# Remove comments
if '//' in line:
line = line[:line.index('//')]
sig_lines.append(line)
# Join and normalize
sig = ' '.join(sig_lines)
sig = normalize_whitespace(sig)
# Remove the opening brace if present
if '{' in sig:
sig = sig[:sig.index('{')].strip()
# Ensure it ends with semicolon
if not sig.endswith(';'):
sig += ';'
return sig
def get_declaration_text(lines, decl):
"""Get normalized declaration text for struct/enum."""
start = decl['start']
end = decl['end']
# Collect all lines
decl_lines = []
for i in range(start, min(end + 1, len(lines))):
line = lines[i]
# Remove comments
if '//' in line:
line = line[:line.index('//')]
decl_lines.append(line)
# Join and normalize
text = ' '.join(decl_lines)
text = normalize_whitespace(text)
return text
def main():
def main():
if len(sys.argv) < 2:
if len(sys.argv) < 2:
print("Usage: c_util toc | func <file> <funcname> | struct <file> <structname> | enum <file> <enumname>")
print("Usage: c_util toc | func <file> <funcname> | struct <file> <structname> | enum <file> <enumname>")
@ -553,26 +613,43 @@ def main():
project_enums[f] = enums
project_enums[f] = enums
if cmd == 'toc':
if cmd == 'toc':
first_file = True
for f in files:
for f in files:
if f not in contents:
if f not in contents:
continue
continue
print(f"File: {f}")
# Get all declarations for this file
declarations = []
# Add functions
for func in project_functions.get(f, []):
sig = get_function_signature(contents[f], func)
declarations.append((func['start'], func['end'], sig))
# Add structs
for s in project_structs.get(f, []):
text = get_declaration_text(contents[f], s)
declarations.append((s['start'], s['end'], text))
# Add enums
for e in project_enums.get(f, []):
text = get_declaration_text(contents[f], e)
declarations.append((e['start'], e['end'], text))
if not declarations:
continue
funcs = project_functions.get(f, [])
# Sort by line number
if funcs:
declarations.sort(key=lambda x: x[0])
for func in funcs:
print(f"Function: {func['ret']} {func['name']}({func['args']}) - {func['line_count']} lines")
strs = project_structs.get(f, [])
# Print empty line between files (except before first)
if strs:
if not first_file :
for s in strs:
print()
print(f"Struct: {s['name']} - {s['line_count']} lines")
first_file = False
enums = project_enums.get(f, [])
# Print in new format
if enums:
for start, end, text in declarations:
for e in enums:
print(f"[{start + 1}-{end + 1}] {text}")
print(f"Enum: {e['name']} - {e['line_count']} lines")
elif cmd == 'func':
elif cmd == 'func':
if len(sys.argv) < 4:
if len(sys.argv) < 4: